├── .gitattributes ├── .github └── workflows │ └── nightly.yml ├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── LICENSE ├── README.md ├── boot ├── README.md ├── boot.cmake └── legacy │ ├── link.ld │ └── startup.s ├── driver ├── README.md ├── neko.cmake ├── staging │ └── example.e ├── stub.cmake └── stub.s ├── src ├── eapp.cmake ├── eapp.h ├── eapp.s ├── eint.h ├── ekrnln.c ├── ekrnln.cmake ├── ekrnln.h ├── elkernel.cmake ├── elkernel.e └── link.ld ├── target ├── 001-combine-files.cmake ├── 010-build-image.cmake └── 100-init-fs.cmake └── tools ├── make-bootimg.py └── patch-symbol.py /.gitattributes: -------------------------------------------------------------------------------- 1 | *.e linguist-language=EPL 2 | -------------------------------------------------------------------------------- /.github/workflows/nightly.yml: -------------------------------------------------------------------------------- 1 | name: Nightly Build 2 | 3 | on: 4 | push: 5 | branches: [ main, ci ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | 11 | compile: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v4 15 | 16 | - name: Configure CMake 17 | uses: threeal/cmake-action@main 18 | with: 19 | run-build: false 20 | build-dir: build 21 | 22 | - name: Configure Build Environment 23 | run: | 24 | sudo dpkg --add-architecture i386 25 | sudo apt install gcc-multilib qemu-utils 26 | 27 | - name: Build Images 28 | run: | 29 | cd build && make 30 | ls -al 31 | 32 | - uses: actions/upload-artifact@v4 33 | name: Upload Artifact 34 | with: 35 | name: elkernel-nightly 36 | path: | 37 | build/elf* 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vs/ 2 | .vscode/ 3 | .win32/ 4 | .build/ 5 | 6 | # EPL or binary files 7 | *.bak 8 | *.obj 9 | *.lib 10 | *.res 11 | 12 | # IDA files 13 | *.id0 14 | *.id1 15 | *.id2 16 | *.nam 17 | *.til 18 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "third-party/rucfs"] 2 | path = third-party/rucfs 3 | url = https://github.com/TheSnowfield/rucfs.git 4 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | # useful directories 4 | set(ELKERNEL_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}) 5 | set(ELKERNEL_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}) 6 | set(ELKERNEL_SOURCE_DIR ${ELKERNEL_ROOT_DIR}/src) 7 | set(ELKERNEL_TARGET_DIR ${ELKERNEL_ROOT_DIR}/target) 8 | set(ELKERNEL_TOOL_DIR ${ELKERNEL_ROOT_DIR}/tools) 9 | set(ELKERNEL_BOOT_DIR ${ELKERNEL_ROOT_DIR}/boot) 10 | set(ELKERNEL_DRIVER_DIR ${ELKERNEL_ROOT_DIR}/driver) 11 | 12 | # bootloader 13 | include(${ELKERNEL_BOOT_DIR}/boot.cmake) 14 | 15 | # driver modules 16 | include(${ELKERNEL_DRIVER_DIR}/stub.cmake) 17 | include(${ELKERNEL_DRIVER_DIR}/neko.cmake) 18 | 19 | # elkernel 20 | include(${ELKERNEL_SOURCE_DIR}/elkernel.cmake) 21 | 22 | # make elfOS 23 | project(elf) 24 | add_custom_target(${PROJECT_NAME} ALL 25 | DEPENDS boot elkernel 26 | COMMENT "Run post builds" 27 | ) 28 | 29 | # post builds 30 | set(_POST_BUILDS "") 31 | file(GLOB_RECURSE _POST_BUILDS ${ELKERNEL_TARGET_DIR}/*.cmake) 32 | foreach(POST_BUILD_FILE IN LISTS _POST_BUILDS) 33 | include(${POST_BUILD_FILE}) 34 | endforeach() 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## elkernel - elfOS 2 | 3 | An x86 toy OS implementation written in EPL. 4 | 5 | Will support the following features in the future: 6 | - [x] Kernel memory management 7 | - [x] Interrupt handling 8 | - [ ] VBE graphics 9 | - [ ] Standard driver model 10 | - [ ] File system model 11 | - [ ] Posix-compatible syscalls 12 | 13 | This project is forked from old branch `snake`, see in the branch [snake](https://github.com/TheSnowfield/elkernel/tree/snake). 14 | 15 | ### Compile the kernel 16 | 17 | For nightly build, please refer to the [GitHub Action](https://github.com/TheSnowfield/elkernel/actions) select latest successful build, then download the artifacts. 18 | 19 | ```bash 20 | $ cmake . -B.build 21 | $ cd .build && make 22 | ``` 23 | 24 | The [el-buildtool](https://github.com/TheSnowfield/el-buildtool/pkgs/container/el-buildtool) docker image will be pulled automatically during the build, then compiling the kernel code without install the EPL environment on your host. 25 | 26 | See more details in the el-buildtool [repository](https://github.com/TheSnowfield/el-buildtool). 27 | 28 | ### How To Debug 29 | > Use QEMU to debug the kernel 30 | ```batch 31 | @echo off 32 | set PATH=%PATH%;YOUR_QEMU_INSTALLATION 33 | qemu-system-i386 -gdb tcp::23333 -fda ./elf-fdd.img 34 | ``` 35 | Execute the batch file, then attach to the QEMU instance.
36 | 37 | ### LICENSE 38 | Licensed under the GPL v2 license with ❤️. 39 | -------------------------------------------------------------------------------- /boot/README.md: -------------------------------------------------------------------------------- 1 | ## Legacy boot 2 | -------------------------------------------------------------------------------- /boot/boot.cmake: -------------------------------------------------------------------------------- 1 | project(boot) 2 | 3 | # search the source codes 4 | set(_BOOT_SRC "") 5 | set(_SEARCH_FILES "") 6 | file(GLOB_RECURSE _SEARCH_FILES ${ELKERNEL_BOOT_DIR}/legacy/*.s) 7 | list(APPEND _BOOT_SRC ${_SEARCH_FILES}) 8 | 9 | # batch assembling 10 | set(_BOOT_BINARY "") 11 | set(_LINK_CMD "") 12 | set(CUSTOM_IMM_PATH ${ELKERNEL_BUILD_DIR}/CMakeFiles) 13 | foreach(_SRC IN LISTS _BOOT_SRC) 14 | get_filename_component(_FILE ${_SRC} NAME) 15 | set (_LINK_CMD ${_LINK_CMD} ${CUSTOM_IMM_PATH}/${_FILE}.dir/${_FILE}.o) 16 | add_custom_target(${_FILE} ALL 17 | # COMMAND mkdir -p ${CUSTOM_IMM_PATH} 18 | COMMAND echo "as --32 ${_SRC} -o ${CUSTOM_IMM_PATH}/${_FILE}.dir/${_FILE}.o" 19 | COMMAND as --32 ${_SRC} -o ${CUSTOM_IMM_PATH}/${_FILE}.dir/${_FILE}.o 20 | ) 21 | endforeach() 22 | 23 | # link executable 24 | add_custom_target(${PROJECT_NAME} ALL 25 | COMMENT "Linking bootloader ${PROJECT_NAME}.elf" 26 | COMMAND ld -m elf_i386 -T ${ELKERNEL_BOOT_DIR}/legacy/link.ld ${_LINK_CMD} -o ${PROJECT_NAME}.elf 27 | 28 | COMMENT "Stripping bootloader binary" 29 | COMMAND objcopy -O binary 30 | --set-section-flags .bootable_sig=alloc,load,readonly 31 | --verbose 32 | ${PROJECT_NAME}.elf ${PROJECT_NAME} 33 | ) 34 | -------------------------------------------------------------------------------- /boot/legacy/link.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT("pe-i386") 2 | ENTRY(_start); 3 | 4 | . = 0x7c00; 5 | 6 | SECTIONS { 7 | 8 | .text : ALIGN(4) { 9 | *(.text) 10 | *(.text*) 11 | KEEP(*(.init)) 12 | KEEP(*(.fini)) 13 | } 14 | 15 | .data : ALIGN(4) { 16 | *(.data); 17 | *(.data*); 18 | } 19 | 20 | .bss : ALIGN(4) { 21 | *(.bss) 22 | } 23 | 24 | _code_end = .; 25 | .bootable_sig : { 26 | . = 0x7e00 - _code_end - 4; 27 | SHORT(0xaa55); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /boot/legacy/startup.s: -------------------------------------------------------------------------------- 1 | .intel_syntax noprefix 2 | 3 | .text 4 | .global _start 5 | .code16 6 | 7 | _start: 8 | 9 | # 清除寄存器 10 | # 不清除會導致在各個仿真器/虛擬機上行爲不同 11 | xor ax, ax 12 | mov ds, ax 13 | mov di, ax 14 | 15 | movb ds:_disk_id, dl # 驅動器 16 | 17 | mov ah, 0x08 18 | int 0x13 19 | 20 | mov dl, cl 21 | and dl, 0x3f 22 | and cx, 0xffc0 23 | 24 | lea bx, _disk_info 25 | movb [bx + 0], dh # 磁頭數量 26 | movb [bx + 1], dl # 扇區數量 27 | movw [bx + 2], cx # 柱面數量 28 | 29 | # 重置顯示器 30 | call _func_reset_screen 31 | 32 | # 加載程序主體部分 33 | call _func_load_bootim 34 | 35 | # 加載全局描述符表 36 | lgdt ds:[_GDT_HEADER] 37 | 38 | call _func_print_newline 39 | lea ax, _msg_booting 40 | call _func_print 41 | 42 | # 進入保護模式 43 | xor eax, eax 44 | cli # 關閉中斷 45 | in al, 0x92 # 使用快速 A20 門 46 | or al, 2 # 啓用 A20 綫 47 | out 0x92, al 48 | mov eax, cr0 49 | or al, 1 # 啓用保護位 50 | mov cr0, eax 51 | 52 | # 原神,啓動! 53 | # 加載內核入口偏移 54 | xchg bx, bx 55 | ljmp [0x8000] 56 | hlt 57 | 58 | # 打印字串 59 | # ax = 字串指針 60 | _func_print: 61 | mov si, ax # 參數 字串所在指針 62 | 63 | _flag_print_continue: 64 | lodsb # 加載指針 65 | cmp al, 0x00 # 是否加載成功 66 | jz _flag_print_break 67 | 68 | mov ah, 0x0e # 中斷函數 69 | int 0x10 70 | jmp _flag_print_continue 71 | 72 | _flag_print_break: 73 | ret 74 | 75 | _func_print_newline: 76 | lea ax, _msg_newline 77 | jmp _func_print 78 | 79 | # 重置默認顯示器 80 | _func_reset_screen: 81 | mov ax, 0x0003 # 設置顯示器 (80x25 16色文本) 82 | int 0x10 83 | ret 84 | 85 | # 解析 bootim 並加載 86 | _func_load_bootim: 87 | 88 | # 先讀取 bootim 所在的扇區,並解析 89 | lea si, _lba_dap 90 | movw [si + 4], 0x0000 # 偏移 91 | movw [si + 6], 0x07e0 # 段 92 | movw [si + 8], 1 # LBA48 低32位 (bootim 在第二扇區) 93 | movw ax, 1 # 讀取 1 扇區 94 | call _func_read_drive 95 | 96 | # 判斷幻數 ELKERNEL 97 | movw ax, ds:0x7e00 98 | movw bx, ds:0x7e02 99 | movw cx, ds:0x7e04 100 | movw dx, ds:0x7e06 101 | cmp ax, 0x4c45 # EL 102 | jnz _flag_missing_bootim 103 | cmp bx, 0x454b # KE 104 | jnz _flag_missing_bootim 105 | cmp cx, 0x4e52 # RN 106 | jnz _flag_missing_bootim 107 | cmp dx, ax # EL 108 | jnz _flag_missing_bootim 109 | 110 | # 打印版本字符串 111 | mov ax, ds:0x7e20 112 | call _func_print 113 | call _func_print_newline 114 | 115 | # 好的 那把整個內核全部請進來吧 (? 116 | # 因爲僅靠 LBA48 的低16位 117 | # 我們就能尋址至多 512B * 0xFFFF 約 32MB 的地址空間 118 | # 而一般內核大小不會超過此大小(<10MB),所以可以擺爛! 119 | lea si, _lba_dap 120 | movw [si + 4], 0x0000 # 偏移 121 | movw [si + 6], 0x0800 # 段 122 | movw [si + 8], 2 # LBA48 低32位 (內核在第3扇區) 123 | movw ax, ds:0x7e10 # 0x7e10 爲 bootim 中定義內核的頁數 124 | call _func_read_drive 125 | ret 126 | 127 | _func_read_drive: 128 | movw ds:_read_pages, 0 129 | movw ds:_total_pages, ax 130 | 131 | # 是否爲軟盤啓動 132 | movb dl, ds:_disk_id 133 | test dl, dl 134 | jz _read_begin_chs 135 | 136 | # movb [si], 0x10 # 大小 137 | # movb [si + 1], 0x00 # 保留 138 | # movw [si + 2], 127 # 要讀取的扇區數 139 | # movw [si + 4], 0x0000 # 偏移 140 | # movw [si + 6], 0x0800 # 段 141 | # movw [si + 8], 2 # LBA48 低32位 (內核在第3扇區) 142 | # movw [si + 10], 0 # LBA48 低32位 143 | # movw [si + 12], 0 # LBA48 高16位 144 | 145 | _read_continue_lba: 146 | 147 | # 讀完沒有呢 148 | movw ax, ds:_total_pages 149 | movw bx, ds:_read_pages 150 | cmp bx, ax # if (_read_pages <= _total_pages) 151 | je _read_end 152 | 153 | sub ax, bx 154 | cmp ax, 127 155 | jl _read_begin_lba # if ( (_total_pages - _read_pages) < 127) 156 | mov ax, 127 157 | 158 | _read_begin_lba: 159 | movw [si + 2], ax 160 | 161 | mov dl, ds:_disk_id # 啓動的磁盤號 162 | mov ah, 0x42 # 中斷號 163 | int 0x13 164 | 165 | jc _flag_disk_failure # 炸了就恐慌 166 | 167 | # 更新結構體 168 | movw ax, [si + 2] 169 | addw ds:_read_pages, ax 170 | addw [si + 4], ax 171 | addw [si + 8], ax 172 | 173 | # 繼續讀取下一個塊 174 | jmp _read_continue_lba 175 | 176 | _read_begin_chs: 177 | 178 | # Todo 179 | jmp $ 180 | 181 | _read_end: 182 | ret 183 | 184 | _flag_missing_bootim: 185 | lea ax, _msg_missing_bootim 186 | jmp _flag_panic 187 | 188 | _flag_disk_failure: 189 | lea ax, _msg_disk_failure 190 | jmp _flag_panic 191 | 192 | _flag_panic: 193 | mov bx, ax 194 | lea ax, _msg_newline 195 | call _func_print 196 | 197 | mov ax, bx 198 | call _func_print 199 | hlt 200 | 201 | .data 202 | _msg_newline: .asciz "\r\n" 203 | _msg_error: .asciz "something went error, panic." 204 | _msg_disk_failure: .asciz "disk failure." 205 | _msg_missing_bootim: .asciz "missing bootim." 206 | _msg_booting: .asciz "booting..." 207 | 208 | _disk_id: 209 | .byte 0 210 | 211 | _disk_info: 212 | .byte 0 # heads 213 | .byte 0 # sectors 214 | .2byte 0 # cylinders 215 | 216 | _lba_dap: 217 | .byte 16 # 長度 218 | .byte 0 219 | .2byte 0 220 | .4byte 0 221 | .8byte 0 222 | 223 | _total_pages: 224 | .2byte 0 225 | 226 | _read_pages: 227 | .2byte 0 228 | 229 | # 全局描述符表 230 | .align 4 231 | _GDT_HEADER: 232 | .2byte _GDT_ENTRIES_END - _GDT_ENTRIES # GDT Size 233 | .4byte _GDT_ENTRIES # GDT Base 234 | 235 | _GDT_ENTRIES: 236 | _GDT_NULL: 237 | .2byte 0x0000 # limit low 238 | .2byte 0x0000 # base low 239 | .byte 0x00 # base middle 240 | .byte 0x00 # access type 241 | .byte 0x00 # limit high, flags 242 | .byte 0x00 # base high 243 | 244 | _GDT_CODE32: 245 | # Base 0x00000000 246 | # Limit 0x000FFFFF 247 | # Access 1(Pr) 00(Privl) 1(S) 1(Ex) 0(DC) 1(RW) 1(Ac) 248 | # Flag 1(Gr) 1(Sz) 0(Null) 0(Null) 249 | .2byte 0xFFFF # limit low 250 | .2byte 0x0000 # base low 251 | .byte 0x00 # base middle 252 | .byte 0x9A # access type 253 | .byte 0xCF # limit high, flags 254 | .byte 0x00 # base high 255 | 256 | _GDT_DATA: 257 | # Base 0x00000000 258 | # Limit 0x000FFFFF 259 | # Access 1(Pr) 00(Privl) 1(S) 0(Ex) 0(DC) 1(RW) 1(Ac) 260 | # Flag 1(Gr) 1(Sz) 0(Null) 0(Null) 261 | .2byte 0xFFFF # limit low 262 | .2byte 0x0000 # base low 263 | .byte 0x00 # base middle 264 | .byte 0x93 # access type 265 | .byte 0xCF # limit high, flags 266 | .byte 0x00 # base high 267 | 268 | _GDT_VIDEO: 269 | _GDT_ENTRIES_END: 270 | -------------------------------------------------------------------------------- /driver/README.md: -------------------------------------------------------------------------------- 1 | ## Driver files 2 | Every driver binary has an extension '.neko' which means _Noob El Kernel Object_. 3 | Work in progress... 4 | -------------------------------------------------------------------------------- /driver/neko.cmake: -------------------------------------------------------------------------------- 1 | # search the source codes 2 | set(_NEKO_SRC "") 3 | set(_SEARCH_FILES "") 4 | file(GLOB_RECURSE _SEARCH_FILES ${ELKERNEL_DRIVER_DIR}/*.e) 5 | list(APPEND _NEKO_SRC ${_SEARCH_FILES}) 6 | 7 | # batch compiling 8 | set(CUSTOM_IMM_PATH ${ELKERNEL_BUILD_DIR}/CMakeFiles/driver.dir) 9 | foreach(_SRC IN LISTS _NEKO_SRC) 10 | get_filename_component(_FILE ${_SRC} NAME_WE) 11 | get_filename_component(_FILE_E ${_SRC} NAME) 12 | get_filename_component(_FILE_DIR ${_SRC} DIRECTORY) 13 | file(RELATIVE_PATH _FILE_OF_ROOT ${ELKERNEL_ROOT_DIR} ${_SRC}) 14 | file(RELATIVE_PATH _FILE_OF_DRIVER ${ELKERNEL_DRIVER_DIR} ${_SRC}) 15 | file(MAKE_DIRECTORY ${CUSTOM_IMM_PATH}/${_FILE_OF_DRIVER}) 16 | set(_NEKO_IMM ${CUSTOM_IMM_PATH}/${_FILE_OF_DRIVER}/${_FILE_E}.o) 17 | 18 | add_custom_target(${_FILE} ALL 19 | 20 | COMMENT "Docker pulling ghcr.io/thesnowfield/el-buildtool:latest" 21 | COMMAND docker pull ghcr.io/thesnowfield/el-buildtool:latest 22 | 23 | COMMENT "Building ${_FILE_OF_ROOT} use el-buildtool" 24 | COMMAND docker run --rm 25 | -e INPUT_FILE=workspace/${_FILE_OF_ROOT} 26 | -e INPUT_OPT_FAST_ARRAY=\"true\" 27 | -e INPUT_OPT_STACK_CHECK=\"false\" 28 | -e INPUT_OPT_DEADLOOP_CHECK=\"false\" 29 | -v \"${ELKERNEL_ROOT_DIR}:/workspace\" 30 | ghcr.io/thesnowfield/el-buildtool:latest 31 | 32 | COMMAND mv -f 33 | ${_FILE_DIR}/${_FILE}.obj 34 | ${CUSTOM_IMM_PATH}/${_FILE_OF_DRIVER}/${_FILE}.obj 35 | ) 36 | 37 | add_custom_command(TARGET ${_FILE} POST_BUILD 38 | COMMENT "[ ** ] Patching symbol '_neko_load@0'" 39 | COMMAND python3 ${ELKERNEL_TOOL_DIR}/patch-symbol.py 40 | _neko_load@0:_neko_load 41 | ${CUSTOM_IMM_PATH}/${_FILE_OF_DRIVER}/${_FILE}.obj ${_NEKO_IMM} 42 | ) 43 | 44 | add_custom_command(TARGET ${_FILE} POST_BUILD 45 | COMMENT "[ ** ] Patching symbol '_neko_unload@0'" 46 | COMMAND python3 ${ELKERNEL_TOOL_DIR}/patch-symbol.py 47 | _neko_unload@0:_neko_unload 48 | ${_NEKO_IMM} ${_NEKO_IMM} 49 | ) 50 | 51 | add_custom_command(TARGET ${_FILE} POST_BUILD 52 | COMMENT "[ ** ] Patching symbol '_neko_on_event@0'" 53 | COMMAND python3 ${ELKERNEL_TOOL_DIR}/patch-symbol.py 54 | _neko_on_event@0:_neko_on_event 55 | ${_NEKO_IMM} ${_NEKO_IMM} 56 | ) 57 | 58 | add_custom_command(TARGET ${_FILE} POST_BUILD 59 | COMMENT "[ ** ] Patching symbol '_krnl_ProcessNotifyLib@12'" 60 | COMMAND python3 ${ELKERNEL_TOOL_DIR}/patch-symbol.py 61 | _krnl_ProcessNotifyLib@12:_krnl_ProcessNotifyLib 62 | ${_NEKO_IMM} ${_NEKO_IMM} 63 | ) 64 | 65 | add_custom_command(TARGET ${_FILE} POST_BUILD 66 | COMMENT "[ ** ] Linking '${_FILE_OF_ROOT}'" 67 | COMMAND ld -melf_i386 -shared 68 | -o ${CUSTOM_IMM_PATH}/${_FILE_OF_DRIVER}/${_FILE}.neko ${_NEKO_IMM} 69 | -L${ELKERNEL_BUILD_DIR} -lnekostub 70 | ) 71 | 72 | endforeach() 73 | -------------------------------------------------------------------------------- /driver/staging/example.e: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSnowfield/elkernel/c4120fc9172440cfc6a2ebaa6ddd7974ad814c80/driver/staging/example.e -------------------------------------------------------------------------------- /driver/stub.cmake: -------------------------------------------------------------------------------- 1 | project(nekostub) 2 | add_compile_options(-m32) 3 | add_link_options(-m32) 4 | 5 | set(_SRC ${ELKERNEL_DRIVER_DIR}/stub.s) 6 | set_property(SOURCE ${_SRC} PROPERTY LANGUAGE C) 7 | 8 | # add source files 9 | add_library(${PROJECT_NAME} SHARED 10 | ${ELKERNEL_DRIVER_DIR}/stub.s 11 | ) 12 | -------------------------------------------------------------------------------- /driver/stub.s: -------------------------------------------------------------------------------- 1 | .intel_syntax noprefix 2 | 3 | .extern _EStartup 4 | .extern ___eapp_info 5 | 6 | .global _krnl_MMain 7 | .global _krnl_MMalloc 8 | .global _krnl_MMallocNoCheck 9 | .global _krnl_MFree 10 | .global _krnl_MRealloc 11 | .global _krnl_MCallKrnlLibCmd 12 | .global _krnl_MCallDllCmd 13 | .global _krnl_MCallLibCmd 14 | .global _krnln_MGetDllCmdAdr 15 | .global _krnl_MExitProcess 16 | .global _krnl_MLoadBeginWin 17 | .global _krnl_MMessageLoop 18 | .global _krnl_MOtherHelp 19 | .global _krnl_MReadProperty 20 | .global _krnl_MReportError 21 | .global _krnl_MWriteProperty 22 | .global _krnl_ProcessNotifyLib 23 | 24 | .text 25 | 26 | _krnl_MMain: 27 | ret 28 | _krnl_MMalloc: 29 | ret 30 | _krnl_MMallocNoCheck: 31 | ret 32 | _krnl_MFree: 33 | ret 34 | _krnl_MRealloc: 35 | ret 36 | _krnl_MCallKrnlLibCmd: 37 | ret 38 | _krnl_MCallDllCmd: 39 | ret 40 | _krnl_MCallLibCmd: 41 | ret 42 | _krnln_MGetDllCmdAdr: 43 | ret 44 | _krnl_MExitProcess: 45 | ret 46 | _krnl_MLoadBeginWin: 47 | ret 48 | _krnl_MMessageLoop: 49 | ret 50 | _krnl_MOtherHelp: 51 | ret 52 | _krnl_MReadProperty: 53 | ret 54 | _krnl_MReportError: 55 | ret 56 | _krnl_MWriteProperty: 57 | ret 58 | _krnl_ProcessNotifyLib: 59 | ret 60 | -------------------------------------------------------------------------------- /src/eapp.cmake: -------------------------------------------------------------------------------- 1 | set(_BINARY_PATH ${ELKERNEL_BUILD_DIR}/CMakeFiles/eapp.dir/elkernel.e.o) 2 | 3 | # pull docker image to build the source code 4 | add_custom_target(eapp ALL 5 | 6 | COMMENT "Docker pulling ghcr.io/thesnowfield/el-buildtool:latest" 7 | COMMAND docker pull ghcr.io/thesnowfield/el-buildtool:latest 8 | 9 | COMMENT "Building elkernel.obj use el-buildtool" 10 | COMMAND docker run --rm 11 | -e INPUT_FILE=workspace/src/elkernel.e 12 | -e INPUT_OPT_FAST_ARRAY=\"true\" 13 | -e INPUT_OPT_STACK_CHECK=\"false\" 14 | -e INPUT_OPT_DEADLOOP_CHECK=\"false\" 15 | -v \"${ELKERNEL_ROOT_DIR}:/workspace\" 16 | ghcr.io/thesnowfield/el-buildtool:latest 17 | 18 | COMMAND mv -f 19 | ${ELKERNEL_SOURCE_DIR}/elkernel.obj 20 | ${_BINARY_PATH} 21 | ) 22 | 23 | # Patch the quirky symbol 24 | add_custom_command(TARGET eapp POST_BUILD 25 | COMMENT "[ ** ] Patching symbol '_krnl_ProcessNotifyLib@12'" 26 | COMMAND python3 ${ELKERNEL_TOOL_DIR}/patch-symbol.py 27 | _krnl_ProcessNotifyLib@12:_krnl_ProcessNotifyLib 28 | ${_BINARY_PATH} 29 | ${ELKERNEL_BUILD_DIR}/eapp.o 30 | ) 31 | -------------------------------------------------------------------------------- /src/eapp.h: -------------------------------------------------------------------------------- 1 | #ifndef _EAPP_H 2 | #define _EAPP_H 3 | 4 | #include "eint.h" 5 | 6 | typedef struct { 7 | uint32_t dwLibFormatVer; 8 | char* szGuid; 9 | int32_t nMajorVersion; 10 | int32_t nMinorVersion; 11 | int32_t nBuildNumber; 12 | int32_t nRqSysMajorVer; 13 | int32_t nRqSysMinorVer; 14 | int32_t nRqSysKrnlLibMajorVer; 15 | int32_t nRqSysKrnlLibMinorVer; 16 | char* szName; 17 | }ELIBINFO; 18 | typedef ELIBINFO* LPELIBINFO; 19 | 20 | typedef struct { 21 | int32_t nType; 22 | int32_t dwState; 23 | int32_t nEAppBuildNumber; 24 | void* lpfnEcode; 25 | void* lpEConst; 26 | void* uEConstSize; 27 | void* lpEForm; 28 | uint32_t uEFormSize; 29 | uint32_t uELibInfoCount; 30 | LPELIBINFO *lpELibInfos; 31 | uint32_t uEDllImportCount; 32 | char** lpEDllNames; 33 | char** lpEDllSymbols; 34 | }EAPPINFO; 35 | typedef EAPPINFO* LPEAPPINFO; 36 | typedef const EAPPINFO* LPCEAPPINFO; 37 | 38 | #define KRNLN_KMEMORY_NOTIFY_MALLOC 0x00 39 | #define KRNLN_KMEMORY_NOTIFY_REALLOC 0x01 40 | #define KRNLN_KMEMORY_NOTIFY_FREEMEM 0x02 41 | typedef uint32_t (EAPP_MEMNOTIFUNC) (uint32_t uNotifyType, uint32_t arg0, uint32_t arg1); 42 | 43 | #endif /* _EAPP_H */ 44 | -------------------------------------------------------------------------------- /src/eapp.s: -------------------------------------------------------------------------------- 1 | .intel_syntax noprefix 2 | 3 | .text 4 | 5 | .extern _EStartup 6 | .extern ___eapp_info 7 | 8 | .global _krnl_MMain 9 | .global _krnl_MMalloc 10 | .global _krnl_MMSetCallback 11 | .global _krnl_MMallocNoCheck 12 | .global _krnl_MFree 13 | .global _krnl_MRealloc 14 | .global _krnl_MCallKrnlLibCmd 15 | .global _krnl_MCallDllCmd 16 | .global _krnl_MCallLibCmd 17 | .global _krnln_MGetDllCmdAdr 18 | .global _krnl_MExitProcess 19 | .global _krnl_MLoadBeginWin 20 | .global _krnl_MMessageLoop 21 | .global _krnl_MOtherHelp 22 | .global _krnl_MReadProperty 23 | .global _krnl_MReportError 24 | .global _krnl_MWriteProperty 25 | .global _krnl_ProcessNotifyLib 26 | 27 | _krnl_MMain: 28 | mov ax, 0x0010 29 | mov ds, ax 30 | mov gs, ax 31 | mov es, ax 32 | 33 | mov esp, 0x7BFF # 設置棧頂 34 | 35 | xor eax, eax # 清空寄存器 36 | mov ebx, eax # 為接下來的代碼做準備 37 | mov ecx, eax 38 | mov edx, eax 39 | 40 | finit 41 | 42 | # bochs 魔術斷點 43 | xchg bx, bx 44 | 45 | # 因爲易語言要先在堆上初始化一些數組 (位於 _EStartup) 46 | # 但是因爲我們的代碼在 ecode (_启动子程序) 47 | # _EStartup 會比 ecode 先調用,導致我們的堆管理器還沒被初始化就被調用了 48 | # 所以我們先調用 ecode 49 | push 0x01 # 0x01 調用原因: 初始化 50 | call _krnl_MMain_eappinfo_ecode 51 | 52 | # 設置內存管理回調 53 | mov _MemoryCallback, eax 54 | 55 | # 取得 _EStartup 的地址 (跳過13字節) 56 | mov eax, offset _EStartup 57 | add eax, 13 58 | 59 | # 調用易語言的 init array 60 | mov ebx, dword ptr [eax+1] 61 | add ebx, eax 62 | add ebx, 5 63 | call ebx 64 | 65 | push 0x00 # 0x01 調用原因: 正式啓動内核 66 | call _krnl_MMain_eappinfo_ecode 67 | 68 | jmp $ 69 | 70 | _krnl_MMain_eappinfo_ecode: 71 | jmp dword ptr [cs:___eapp_info + 12] 72 | 73 | _krnl_MMalloc: 74 | mov eax, dword ptr _MemoryCallback 75 | test eax, eax 76 | jnz _krnl_MMalloc_not_zero 77 | ret 78 | _krnl_MMalloc_not_zero: 79 | push 0 # arg1 80 | push [esp + 8] # arg0 81 | push 0 # uNotifyType 82 | call eax 83 | ret 84 | 85 | _krnl_MMallocNoCheck: 86 | jmp _krnl_MMalloc 87 | 88 | _krnl_MFree: 89 | mov eax, dword ptr _MemoryCallback 90 | test eax, eax 91 | jz _krnl_MFree_not_zero 92 | ret 93 | _krnl_MFree_not_zero: 94 | push 0 # arg1 95 | push [esp + 8] # arg0 96 | push 2 # uNotifyType 97 | call eax 98 | ret 99 | 100 | _krnl_MRealloc: 101 | mov eax, dword ptr _MemoryCallback 102 | test eax, eax 103 | jnz _krnl_MRealloc_not_zero 104 | ret 105 | _krnl_MRealloc_not_zero: 106 | push dword ptr [esp + 8] # arg1 107 | push dword ptr [esp + 8] # arg0 108 | push 1 # uNotifyType 109 | call eax 110 | ret 111 | 112 | _krnl_MCallKrnlLibCmd: 113 | lea eax, dword ptr [esp + 8] 114 | sub esp, 12 115 | push eax 116 | push dword ptr[esp + 20] 117 | xor eax, eax 118 | mov dword ptr [esp + 8], eax 119 | mov dword ptr [esp + 12], eax 120 | mov dword ptr [esp + 16], eax 121 | lea edx, dword ptr [esp + 8] 122 | push edx 123 | call ebx 124 | mov eax, dword ptr [esp + 12] 125 | mov edx, dword ptr [esp + 16] 126 | mov ecx, dword ptr [esp + 20] 127 | add esp, 24 128 | ret 129 | 130 | _krnl_MCallDllCmd: # 調用外部DLL命令 131 | ret 132 | 133 | _krnl_MCallLibCmd: # 調用核心庫除外的支持庫函數 134 | ret 135 | 136 | _krnln_MGetDllCmdAdr: # 獲取外部DLL命令地址 137 | ret 138 | 139 | _krnl_MExitProcess: # 程序結束 退出進程 140 | ret 141 | 142 | _krnl_MLoadBeginWin: # 沒什麽用的 暫時沒見到過 (看名字像創建窗口 143 | ret 144 | 145 | _krnl_MMessageLoop: # 窗口消息循環 沒什麽用 146 | ret 147 | 148 | _krnl_MOtherHelp: # 貌似是初始化用途的函數 沒什麽用 149 | ret 150 | 151 | _krnl_MReadProperty: # 讀窗口屬性字段 不用窗口組件沒什麽用 152 | ret 153 | 154 | _krnl_MReportError: # 報告錯誤 目前沒什麽用 155 | ret 156 | 157 | _krnl_MWriteProperty: # 寫窗口屬性字段 不用窗口組件沒什麽用 158 | ret 159 | 160 | _krnl_ProcessNotifyLib: # 核心支持庫通知回調函數 沒什麽用 161 | ret 12 162 | 163 | .data 164 | _MemoryCallback: 165 | .4byte 0 166 | -------------------------------------------------------------------------------- /src/eint.h: -------------------------------------------------------------------------------- 1 | #ifndef _EINT_H 2 | #define _EINT_H 3 | 4 | #define NULL ((void*)0) 5 | 6 | typedef signed char int8_t, INT8; 7 | typedef short int16_t, SHORT, INT16; 8 | typedef int int32_t, bool, INT, INT32; 9 | typedef long LONG, BOOL, * LPBOOL, * PBOOL, LONG_PTR, * PLONG_PTR; 10 | typedef long long int64_t, QWORD, INT64; 11 | typedef unsigned char uint8_t, byte, BYTE, UINT8, * LPBYTE, * PBYTE; 12 | typedef unsigned short uint16_t, USHORT, UINT16, WORD; 13 | typedef unsigned int uint32_t, UINT32, DWORD; 14 | typedef unsigned long ULONG_PTR, DWORD_PTR; 15 | typedef unsigned long long uint64_t, UINT64; 16 | 17 | typedef signed char int_least8_t; 18 | typedef short int_least16_t; 19 | typedef int int_least32_t; 20 | typedef long long int_least64_t; 21 | typedef unsigned char uint_least8_t; 22 | typedef unsigned short uint_least16_t; 23 | typedef unsigned int uint_least32_t; 24 | typedef unsigned long long uint_least64_t; 25 | 26 | typedef signed char int_fast8_t; 27 | typedef int int_fast16_t; 28 | typedef int int_fast32_t; 29 | typedef long long int_fast64_t; 30 | typedef unsigned char uint_fast8_t; 31 | typedef unsigned int uint_fast16_t; 32 | typedef unsigned int uint_fast32_t; 33 | typedef unsigned long long uint_fast64_t; 34 | 35 | typedef long long intmax_t; 36 | typedef unsigned long long uintmax_t; 37 | 38 | typedef float FLOAT; 39 | typedef double DOUBLE, DATE, * PDATE; 40 | 41 | #define MAKEWORD(a, b) ((WORD)(((BYTE)(((DWORD_PTR)(a)) & 0xff)) | ((WORD)((BYTE)(((DWORD_PTR)(b)) & 0xff))) << 8)) 42 | #define MAKELONG(a, b) ((LONG)(((WORD)(((DWORD_PTR)(a)) & 0xffff)) | ((DWORD)((WORD)(((DWORD_PTR)(b)) & 0xffff))) << 16)) 43 | #define LOWORD(l) ((WORD)(((DWORD_PTR)(l)) & 0xffff)) 44 | #define HIWORD(l) ((WORD)((((DWORD_PTR)(l)) >> 16) & 0xffff)) 45 | #define LOBYTE(w) ((BYTE)(((DWORD_PTR)(w)) & 0xff)) 46 | #define HIBYTE(w) ((BYTE)((((DWORD_PTR)(w)) >> 8) & 0xff)) 47 | 48 | #define INT8_MIN (-127i8 - 1) 49 | #define INT16_MIN (-32767i16 - 1) 50 | #define INT32_MIN (-2147483647i32 - 1) 51 | #define INT64_MIN (-9223372036854775807i64 - 1) 52 | #define INT8_MAX 127i8 53 | #define INT16_MAX 32767i16 54 | #define INT32_MAX 2147483647i32 55 | #define INT64_MAX 9223372036854775807i64 56 | #define UINT8_MAX 0xffui8 57 | #define UINT16_MAX 0xffffui16 58 | #define UINT32_MAX 0xffffffffui32 59 | #define UINT64_MAX 0xffffffffffffffffui64 60 | 61 | #define INT_LEAST8_MIN INT8_MIN 62 | #define INT_LEAST16_MIN INT16_MIN 63 | #define INT_LEAST32_MIN INT32_MIN 64 | #define INT_LEAST64_MIN INT64_MIN 65 | #define INT_LEAST8_MAX INT8_MAX 66 | #define INT_LEAST16_MAX INT16_MAX 67 | #define INT_LEAST32_MAX INT32_MAX 68 | #define INT_LEAST64_MAX INT64_MAX 69 | #define UINT_LEAST8_MAX UINT8_MAX 70 | #define UINT_LEAST16_MAX UINT16_MAX 71 | #define UINT_LEAST32_MAX UINT32_MAX 72 | #define UINT_LEAST64_MAX UINT64_MAX 73 | 74 | #define INT_FAST8_MIN INT8_MIN 75 | #define INT_FAST16_MIN INT32_MIN 76 | #define INT_FAST32_MIN INT32_MIN 77 | #define INT_FAST64_MIN INT64_MIN 78 | #define INT_FAST8_MAX INT8_MAX 79 | #define INT_FAST16_MAX INT32_MAX 80 | #define INT_FAST32_MAX INT32_MAX 81 | #define INT_FAST64_MAX INT64_MAX 82 | #define UINT_FAST8_MAX UINT8_MAX 83 | #define UINT_FAST16_MAX UINT32_MAX 84 | #define UINT_FAST32_MAX UINT32_MAX 85 | #define UINT_FAST64_MAX UINT64_MAX 86 | 87 | #define INTPTR_MIN INT32_MIN 88 | #define INTPTR_MAX INT32_MAX 89 | #define UINTPTR_MAX UINT32_MAX 90 | 91 | #define INTMAX_MIN INT64_MIN 92 | #define INTMAX_MAX INT64_MAX 93 | #define UINTMAX_MAX UINT64_MAX 94 | 95 | #define PTRDIFF_MIN INTPTR_MIN 96 | #define PTRDIFF_MAX INTPTR_MAX 97 | 98 | #define SIZE_MAX UINTPTR_MAX 99 | 100 | #define SIG_ATOMIC_MIN INT32_MIN 101 | #define SIG_ATOMIC_MAX INT32_MAX 102 | 103 | #define WCHAR_MIN 0x0000 104 | #define WCHAR_MAX 0xffff 105 | 106 | #define WINT_MIN 0x0000 107 | #define WINT_MAX 0xffff 108 | 109 | #define INT8_C(x) (x) 110 | #define INT16_C(x) (x) 111 | #define INT32_C(x) (x) 112 | #define INT64_C(x) (x ## LL) 113 | 114 | #define UINT8_C(x) (x) 115 | #define UINT16_C(x) (x) 116 | #define UINT32_C(x) (x ## U) 117 | #define UINT64_C(x) (x ## ULL) 118 | 119 | #define INTMAX_C(x) INT64_C(x) 120 | #define UINTMAX_C(x) UINT64_C(x) 121 | 122 | #endif /*_EINT_H */ 123 | -------------------------------------------------------------------------------- /src/ekrnln.c: -------------------------------------------------------------------------------- 1 | #include "eint.h" 2 | #include "ekrnln.h" 3 | 4 | /** 5 | * @brief 数值转换 - 到整数 6 | * 7 | * 调用格式: 〈整数型〉 到整数 (通用型 待转换的文本或数值) - 系统核心支持库->数值转换 8 | * 英文名称:ToInt 9 | * 返回包含于文本内的整数值,文本中是一个适当类型的数值,支持全角书写方式。本命令也可用作将其他类型的数据转换为整数。本命令为初级命令。 10 | * 参数<1>的名称为“待转换的文本或数值”,类型为“通用型(all)”。 11 | */ 12 | INT krnln_fnToInt(PMDATA_INF pRetData, UINT32 uArgCount, PMDATA_INF pArgInf) { 13 | switch (pArgInf->m_dtDataType) { 14 | 15 | case SDT_BYTE: 16 | return pArgInf->m_byte; 17 | 18 | case SDT_SHORT: 19 | return pArgInf->m_short; 20 | 21 | case SDT_INT: 22 | case SDT_BOOL: 23 | case SDT_SUB_PTR: 24 | return pArgInf->m_int; 25 | 26 | case SDT_FLOAT: 27 | return (INT)pArgInf->m_float; 28 | 29 | case SDT_DOUBLE: 30 | return (INT)pArgInf->m_double; 31 | 32 | case SDT_INT64: 33 | return (INT)pArgInf->m_int64; 34 | default: 35 | return 0; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/ekrnln.cmake: -------------------------------------------------------------------------------- 1 | project(ekrnln) 2 | set(CMAKE_C_STANDARD 11) 3 | add_compile_options(-m32 -masm=intel -nostdlib -nodefaultlibs -fPIC) 4 | # set( CMAKE_VERBOSE_MAKEFILE on) 5 | 6 | # find all src file 7 | set(_SRC "") 8 | set(_SEARCH_FILE "") 9 | file(GLOB_RECURSE _SEARCH_FILE ${ELKERNEL_SOURCE_DIR}/*.s) 10 | list(APPEND _SRC ${_SEARCH_FILE}) 11 | file(GLOB_RECURSE _SEARCH_FILE ${ELKERNEL_SOURCE_DIR}/*.c) 12 | list(APPEND _SRC ${_SEARCH_FILE}) 13 | set_property(SOURCE ${_SRC} PROPERTY LANGUAGE C) 14 | 15 | # add include directories 16 | include_directories( 17 | ${ELKERNEL_SOURCE_DIR} 18 | ) 19 | 20 | # add source files 21 | add_library(${PROJECT_NAME} STATIC 22 | ${_SRC} 23 | ) 24 | -------------------------------------------------------------------------------- /src/ekrnln.h: -------------------------------------------------------------------------------- 1 | #ifndef _EKRNLN_H 2 | #define _EKRNLN_H 3 | 4 | typedef DATE* PDATE; 5 | 6 | /////////////////////////////////// 7 | 8 | // 仅用于库命令定义其参数或返回值的数据类型。 9 | #define _SDT_NULL 0 // 空数据(内部使用,必须为零) 10 | 11 | // 1、当用于定义库命令参数时,_SDT_ALL可以匹配所有数据类型(数组类型必须符合要求)。 12 | // 2、由于定义为返回_SDT_ALL数据类型的库命令不允许返回数组或复合数据类型的数据 13 | // 即用户或库自定义数据类型但不包含窗口或菜单组件,所以_SDT_ALL类型的数据只 14 | // 可能为非数组的系统数据类型或窗口组件、菜单数据类型。 15 | #define _SDT_ALL MAKELONG (MAKEWORD (0, 0), 0x8000) // (内部使用) 16 | 17 | // 以下是由系统定义的基本数据类型 18 | #define SDT_BYTE MAKELONG (MAKEWORD (1, 1), 0x8000) // 字节 19 | #define SDT_SHORT MAKELONG (MAKEWORD (1, 2), 0x8000) // 短整数 20 | #define SDT_INT MAKELONG (MAKEWORD (1, 3), 0x8000) // 整数 21 | #define SDT_INT64 MAKELONG (MAKEWORD (1, 4), 0x8000) // 长整数 22 | #define SDT_FLOAT MAKELONG (MAKEWORD (1, 5), 0x8000) // 小数 23 | #define SDT_DOUBLE MAKELONG (MAKEWORD (1, 6), 0x8000) // 双精度小数 24 | #define SDT_BOOL MAKELONG (MAKEWORD (2, 0), 0x8000) // 逻辑 25 | #define SDT_DATE_TIME MAKELONG (MAKEWORD (3, 0), 0x8000) // 日期时间 26 | #define SDT_TEXT MAKELONG (MAKEWORD (4, 0), 0x8000) // 文本 27 | #define SDT_BIN MAKELONG (MAKEWORD (5, 0), 0x8000) // 字节集 28 | #define SDT_SUB_PTR MAKELONG (MAKEWORD (6, 0), 0x8000) // 子程序指针 29 | #define SDT_STATMENT MAKELONG (MAKEWORD (8, 0), 0x8000) 30 | 31 | // 用作区分系统类型、用户自定义类型、库定义数据类型 32 | #define DTM_SYS_DATA_TYPE_MASK 0x80000000 33 | #define DTM_USER_DATA_TYPE_MASK 0x40000000 34 | #define DTM_LIB_DATA_TYPE_MASK 0x00000000 35 | 36 | // 用作细分用户自定义数据类型 37 | #define UDTM_USER_DECLARE_MASK 0x00000000 // 用户自定义复合数据类型 38 | #define UDTM_WIN_DECLARE_MASK 0x10000000 // 用户自定义窗口类型 39 | 40 | // 在数据类型中的数组标志,如果某数据类型值此位置1,则表示为此数据类型的数组。 41 | // 本标志仅用作在运行时为具有AS_RECEIVE_VAR_OR_ARRAY或AS_RECEIVE_ALL_TYPE_DATA 42 | // 标志的库命令参数说明其为是否为数组数据,其他场合均未使用。因此其他地方均 43 | // 可以忽略本标志。 44 | #define DT_IS_ARY 0x20000000 45 | 46 | // 在数据类型中的传址标志,如果某数据类型值此位置1,则表示为此数据类型的变量地址。 47 | // 本标志仅用作在运行时为具有AS_RECEIVE_VAR_OR_OTHER标志的库命令参数说明其为是否为 48 | // 变量地址,其他场合均未使用。因此其他地方均可以忽略本标志。 49 | // 本标志与上标志不能共存。 50 | #define DT_IS_VAR 0x20000000 51 | 52 | typedef DWORD DATA_TYPE; 53 | typedef DATA_TYPE* PDATA_TYPE; 54 | 55 | //////////////////////////////////////////////////////////////// 56 | 57 | typedef struct { 58 | DWORD m_dwFormID; 59 | DWORD m_dwUnitID; 60 | } MUNIT, *PMUNIT; 61 | 62 | typedef struct { 63 | DWORD m_dwStatmentSubCodeAdr; 64 | DWORD m_dwSubEBP; 65 | } STATMENT_CALL_DATA, *PSTATMENT_CALL_DATA; 66 | 67 | 68 | #pragma pack (push, old_value) 69 | #pragma pack (1) 70 | typedef struct { 71 | union { 72 | BYTE m_byte; // SDT_BYTE 73 | SHORT m_short; // SDT_SHORT 74 | USHORT m_ushort; 75 | INT m_int; // SDT_INT 76 | DWORD m_uint; // (DWORD)SDT_INT 77 | INT64 m_int64; // SDT_INT64 78 | FLOAT m_float; // SDT_FLOAT 79 | DOUBLE m_double; // SDT_DOUBLE 80 | DATE m_date; // SDT_DATE_TIME 81 | BOOL m_bool; // SDT_BOOL 82 | char* m_pText; // SDT_TEXT,不可能为NULL。 83 | // !!!为了避免修改到常量段(m_pText有可能指向常量段区域)中的数据, 84 | // 只可读取而不可更改其中的内容,下同。 85 | LPBYTE m_pBin; // SDT_BIN,不可能为NULL,!!!只可读取而不可更改其中的内容。 86 | DWORD m_dwSubCodeAdr; // SDT_SUB_PTR,记录子程序代码地址。 87 | STATMENT_CALL_DATA m_statment; // SDT_STATMENT数据类型。 88 | MUNIT m_unit; // 窗口组件、菜单数据类型。 89 | void* m_pCompoundData; // 复合数据类型数据指针,指针所指向数据的格式请见 run.h 。 90 | // 可以直接更改其中的数据成员,但是如果需要必须首先释放该成员。 91 | void* m_pAryData; // 数组数据指针,指针所指向数据的格式请见 run.h 。 92 | // 注意如果为文本或字节集数组,则成员数据指针可能为NULL。 93 | // !!! 只可读取而不可更改其中的内容。 94 | 95 | // 为指向变量地址的指针,仅当传入参数到库命令实现函数时才有用。 96 | BYTE* m_pByte; // SDT_BYTE* 97 | SHORT* m_pShort; // SDT_SHORT* 98 | INT* m_pInt; // SDT_INT* 99 | DWORD* m_pUInt; // ((DWORD)SDT_INT)* 100 | INT64* m_pInt64; // SDT_INT64* 101 | FLOAT* m_pFloat; // SDT_FLOAT* 102 | DOUBLE* m_pDouble; // SDT_DOUBLE* 103 | DATE* m_pDate; // SDT_DATE_TIME* 104 | BOOL* m_pBool; // SDT_BOOL* 105 | char** m_ppText; // SDT_TEXT,*m_ppText可能为NULL。 106 | // 注意写入新值之前必须释放前值,即:MFree (*m_ppText)。 107 | // !!!不可直接更改*m_ppText所指向的内容,只能释放原指针后换入新指针。 108 | LPBYTE* m_ppBin; // SDT_BIN,*m_ppBin可能为NULL。 109 | // 注意写入新值之前必须释放前值,即:MFree (*m_ppBin)。 110 | // !!!不可直接更改*m_ppBin所指向的内容,只能释放原指针后换入新指针。 111 | DWORD* m_pdwSubCodeAdr; // SDT_SUB_PTR,子程序代码地址变量。 112 | PSTATMENT_CALL_DATA m_pStatment; // SDT_STATMENT数据类型变量。 113 | PMUNIT m_pUnit; // 窗口组件、菜单数据类型变量。 114 | void** m_ppCompoundData; // 复合数据类型变量。 115 | // 可以直接更改其中的数据成员,但是如果需要必须首先释放该成员。 116 | void** m_ppAryData; // 数组数据变量,注意: 117 | // 1、写入新值之前必须释放原值(使用NRS_FREE_VAR通知)。 118 | // 2、变量如果为文本或字节集数组,则成员数据指针可能为NULL。 119 | // !!!不可直接更改*m_ppAryData所指向的内容,只能释放原指针后换入新指针。 120 | }; 121 | // 1、当用作传入参数时,如果该参数具有 AS_RECEIVE_VAR_OR_ARRAY 或 122 | // AS_RECEIVE_ALL_TYPE_DATA 标志,且为数组数据,则包含数组标志 DT_IS_ARY , 123 | // 这也是 DT_IS_ARY 标志的唯一使用场合。 124 | // 2、当用作传递参数数据时,如果为空白数据,则为 _SDT_NULL 。 125 | DATA_TYPE m_dtDataType; 126 | } MDATA_INF; 127 | typedef MDATA_INF* PMDATA_INF; 128 | #pragma pack (pop, old_value) 129 | 130 | #endif /* _EKRNLN_H */ 131 | -------------------------------------------------------------------------------- /src/elkernel.cmake: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | include(${ELKERNEL_SOURCE_DIR}/eapp.cmake) 4 | include(${ELKERNEL_SOURCE_DIR}/ekrnln.cmake) 5 | 6 | # link executable 7 | project(elkernel) 8 | add_custom_target(${PROJECT_NAME} ALL 9 | DEPENDS ekrnln eapp 10 | 11 | COMMENT "Building ${PROJECT_NAME}.elf" 12 | COMMAND ld -m elf_i386 13 | -T ${ELKERNEL_SOURCE_DIR}/link.ld 14 | ${ELKERNEL_BUILD_DIR}/eapp.o 15 | ${ELKERNEL_BUILD_DIR}/libekrnln.a 16 | -o ${PROJECT_NAME}.elf 17 | 18 | COMMENT "Stripping ${PROJECT_NAME}.elf" 19 | COMMAND objcopy -O binary 20 | --set-section-flags .head=alloc,load,readonly 21 | --verbose 22 | ${PROJECT_NAME}.elf ${PROJECT_NAME}.bin 23 | 24 | COMMENT "Make bootimg" 25 | COMMAND python3 26 | ${ELKERNEL_TOOL_DIR}/make-bootimg.py 27 | ${ELKERNEL_BUILD_DIR}/${PROJECT_NAME}.bin 28 | ${ELKERNEL_BUILD_DIR}/${PROJECT_NAME} 29 | ) 30 | 31 | set(_POST_BUILDS "") 32 | file(GLOB_RECURSE _POST_BUILDS ${ELKERNEL_SOURCE_DIR}/target/*.cmake) 33 | foreach(_BUILD IN LISTS _POST_BUILDS) 34 | include(${_BUILD}) 35 | endforeach() 36 | -------------------------------------------------------------------------------- /src/elkernel.e: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSnowfield/elkernel/c4120fc9172440cfc6a2ebaa6ddd7974ad814c80/src/elkernel.e -------------------------------------------------------------------------------- /src/link.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT("pe-i386") 2 | ENTRY(_krnl_MMain); 3 | 4 | . = 0x8000; 5 | 6 | SECTIONS { 7 | 8 | .head ALIGN(4) : { 9 | SHORT(_krnl_MMain); 10 | SHORT(0x0008) 11 | LONG(0x00000000) 12 | LONG(0x00000000) 13 | LONG(0x00000000) 14 | } 15 | 16 | .text ALIGN(4) : { 17 | *(.text) 18 | *(.text*) 19 | KEEP(*(.init)) 20 | KEEP(*(.fini)) 21 | } 22 | 23 | .rodata ALIGN(4) : { 24 | *(.rodata) 25 | *(.rodata*) 26 | } 27 | 28 | .data ALIGN(4) : { 29 | *(.data) 30 | *(.data*) 31 | *(.rdata) /* quirky section from epl*/ 32 | *(.eh_frame) 33 | } 34 | 35 | .bss ALIGN(4) : { 36 | *(.bss) 37 | *(.bss*) 38 | } 39 | 40 | /DISCARD/ : { 41 | *(.debug*) 42 | *(.comment) 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /target/001-combine-files.cmake: -------------------------------------------------------------------------------- 1 | # Combine bootloader an kernel image 2 | add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD 3 | COMMENT "[ ** ] Building ${PROJECT_NAME}" 4 | COMMAND cat boot elkernel > ${PROJECT_NAME} 5 | ) 6 | -------------------------------------------------------------------------------- /target/010-build-image.cmake: -------------------------------------------------------------------------------- 1 | # Generate bootable CD 2 | set(ELF_BOOTCD ${PROJECT_NAME}-cd.iso) 3 | add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD 4 | COMMENT "[ ** ] Building bootable iso ${ELF_BOOTCD}" 5 | COMMAND rm -rf .bootcd 2>&1 6 | COMMAND mkdir .bootcd 7 | COMMAND cp ${PROJECT_NAME} .bootcd/BOOT 8 | COMMAND truncate -s 1474560 .bootcd/BOOT 9 | COMMAND xorriso -as mkisofs -b BOOT -v -r -l -o ${ELF_BOOTCD} .bootcd 10 | COMMAND rm -rf .bootcd 11 | ) 12 | 13 | # Generate floppy image 14 | set(ELF_FLOPPY ${PROJECT_NAME}-fdd.img) 15 | add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD 16 | COMMENT "[ ** ] Building ${ELF_FLOPPY}" 17 | COMMAND cp ${PROJECT_NAME} ${ELF_FLOPPY} 18 | COMMAND truncate -s 1474560 ${ELF_FLOPPY} 19 | ) 20 | 21 | # Generate vmdk 22 | set(ELF_VMDK ${PROJECT_NAME}.vmdk) 23 | add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD 24 | COMMENT "[ ** ] Building ${ELF_VMDK}" 25 | COMMAND qemu-img convert ${PROJECT_NAME} -f raw -O vmdk ${ELF_VMDK} 26 | ) 27 | -------------------------------------------------------------------------------- /target/100-init-fs.cmake: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSnowfield/elkernel/c4120fc9172440cfc6a2ebaa6ddd7974ad814c80/target/100-init-fs.cmake -------------------------------------------------------------------------------- /tools/make-bootimg.py: -------------------------------------------------------------------------------- 1 | #!/bin/python3 2 | 3 | import os 4 | import sys; 5 | import time; 6 | 7 | # bootimg writer class 8 | class bootimg: 9 | 10 | STRUCT_MAGIC = 0 11 | STRUCT_CRC32 = 8 12 | STRUCT_FLAGS = 12 13 | STRUCT_IMG_PAGES = 16 14 | STRUCT_ENTRY_OFFSET = 20 15 | STRUCT_TIMESTAMP = 24 16 | STRUCT_VERSION = 32 17 | STRUCT_KERNEL = 512 18 | 19 | _time = int(time.time() * 1000) 20 | 21 | def _get_time(self): 22 | return self._time.to_bytes(8, byteorder='little') 23 | 24 | def _get_version(self): 25 | 26 | # get git commit hash 27 | tag = os.popen("git describe --tags").read().strip() 28 | hash = os.popen("git describe --always").read().strip() 29 | branch = os.popen("git rev-parse --abbrev-ref HEAD").read().strip() 30 | 31 | # get gcc version 32 | gcc = os.popen("gcc --version | head -n1").read().strip() 33 | tag = tag.replace("v", "").replace("-", "_") 34 | if tag == "": 35 | tag = "v0.0.0" 36 | 37 | # convert ts to yymmdd 38 | ts = time.strftime("%y%m%d", time.localtime(self._time/1000)) 39 | version = f"elkernel_build{ts}_{branch}_{tag}_{hash} \r\nwith EPL v5.11, {gcc}" 40 | return version.encode('utf-8') 41 | 42 | def _padding_write(self, file): 43 | self.fp.write(file) 44 | 45 | size = len(file) 46 | if size % 512 != 0: 47 | align = 512 - (size % 512) 48 | size += align 49 | self.fp.write(bytearray(align)) 50 | return size 51 | 52 | def __init__(self, path): 53 | self.path = path 54 | self.fp = open(path, "wb") 55 | self.fp.seek(0) 56 | 57 | # write header 58 | self.fp.write(b"ELKERNEL") # 0 magic 59 | self.fp.write(bytearray(4)) # 8 crc32 60 | self.fp.write(bytearray(4)) # 12 flags 61 | self.fp.write(bytearray(2)) # 16 image_pages 62 | self.fp.write(bytearray(2)) # 18 reserved 63 | self.fp.write(bytearray(4)) # 20 entry_offset 64 | self.fp.write(self._get_time()) # 24 timestamp 65 | self.fp.write(self._get_version()) # 32 version 66 | self.fp.write(bytearray(352)) # 160 align 67 | # file content # 512 kernel 68 | 69 | def set_file(self, file): 70 | 71 | # calculate crc32 72 | crc = 0 73 | for i in range(0, len(file)): 74 | crc = crc ^ file[i] 75 | for j in range(0, 8): 76 | if crc & 1: 77 | crc = (crc >> 1) ^ 0xEDB88320 78 | else: 79 | crc = crc >> 1 80 | crc = crc ^ 0xFFFFFFFF 81 | 82 | # write crc32 83 | self.fp.seek(self.STRUCT_CRC32) 84 | self.fp.write(crc.to_bytes(4, byteorder='little')) 85 | 86 | # write file align 512 87 | self.fp.seek(self.STRUCT_KERNEL) 88 | size = int(self._padding_write(file) / 512) 89 | 90 | # write image pages 91 | self.fp.seek(self.STRUCT_IMG_PAGES) 92 | self.fp.write(size.to_bytes(2, byteorder='little')) 93 | 94 | 95 | def close(self): 96 | 97 | self.fp.close() 98 | 99 | 100 | def main(): 101 | 102 | # open bootimg writer 103 | boot = bootimg(sys.argv[2]) 104 | 105 | # open the file and read the bytes 106 | with open(sys.argv[1], "rb") as fp: 107 | file = fp.read() 108 | boot.set_file(file) 109 | 110 | boot.close() 111 | 112 | # # enumerate over the bytes and write to file 113 | # # limit to 128 bytes 114 | # with open(sys.argv[1] + "/ld_version.ld", "wt") as fp: 115 | # i = 0 116 | # for j in range(0, len(version)): 117 | # fp.write(f"BYTE({hex(version[j])});\n") 118 | # if i > 127: break 119 | # fp.write(f"BYTE(0x00);\n") 120 | 121 | pass 122 | 123 | if __name__ == "__main__": 124 | if len(sys.argv) < 2: 125 | print("Usage: make-bootimg.py ") 126 | sys.exit(1) 127 | main() 128 | -------------------------------------------------------------------------------- /tools/patch-symbol.py: -------------------------------------------------------------------------------- 1 | #!/bin/python3 2 | 3 | import io; 4 | import os; 5 | import sys; 6 | 7 | def main(): 8 | 9 | if sys.argv[1].index(':') == -1: 10 | print("Invalid symbol format, expected:
:, got: " + sys.argv[1]) 11 | sys.exit(1) 12 | 13 | split = sys.argv[1].split(':') 14 | symbol = split[0].encode(), split[1].encode() 15 | if len(symbol[1]) > len(symbol[0]): 16 | print("Renamed symbol is longer than the original symbol") 17 | sys.exit(1) 18 | 19 | input = sys.argv[2] 20 | output = sys.argv[3] 21 | 22 | data = None 23 | 24 | with open(input, "rb") as coff: 25 | # search binary in the file 26 | data = coff.read() 27 | 28 | position = data.find(symbol[0]) 29 | if position == -1: 30 | print("Symbol not found") 31 | sys.exit(0) 32 | 33 | # patch with align 34 | print("Patching " + split[0] + " at position: " + str(position)) 35 | align = len(symbol[0]) - len(symbol[1]) 36 | data = data[:position] + symbol[1] + bytearray(align) + data[position + len(symbol[0]):] 37 | 38 | # write 39 | with open(output, "wb") as out: 40 | out.write(data) 41 | 42 | pass 43 | 44 | if __name__ == "__main__": 45 | if len(sys.argv) < 3: 46 | print("Usage: patch-symbol.py ") 47 | sys.exit(1) 48 | main() 49 | --------------------------------------------------------------------------------