├── .clang-format ├── .github └── workflows │ ├── osbuild.yaml │ └── utbuild.yaml ├── CMakeLists.txt ├── LICENSE ├── README.md ├── cmake ├── GenConfigHeaderFile.cmake ├── compile_assemble_link.cmake └── x86 │ ├── commonflags.cmake │ ├── kernelflags.cmake │ ├── unittestflags.cmake │ └── userflags.cmake ├── docs ├── PMM_Calculations.ods ├── collate.sh ├── images │ ├── meghaos_gui0.gif │ ├── meghaos_panic.png │ ├── mos.rbm │ └── moslogo.svg ├── index.md ├── index_template.md ├── memmap.ods ├── notes │ ├── BUGS.md │ ├── CrossPlatform.md │ ├── Scratch.md │ ├── TODO.md │ ├── Vbe.md │ ├── abi.md │ ├── abstract_design.md │ ├── assert-panic-in-meghaos.md │ ├── changes.md │ ├── clocktick.md │ ├── cmake-build.md │ ├── coding_style.md │ ├── gdt.md │ ├── general.md │ ├── interrupt_handling.md │ ├── kmalloc.md │ ├── memorymanagement.md │ ├── object_file_format.md │ ├── opaque_data_types.md │ ├── paging.md │ ├── physical_memory_allocation.md │ ├── physical_memory_manager.md │ ├── processman.md │ ├── recursive_map_clarity_with_example.md │ ├── source_tree_style.md │ ├── ui.md │ ├── usermode_stack.md │ ├── virtual_memory_manager.md │ ├── vmm.md │ └── when-to-assert.md ├── paging.ods ├── titles.sh └── x86_intel_protection.odt ├── include ├── asm │ └── csh.s ├── bitmap.h ├── buildcheck.h ├── cm │ ├── cm.h │ ├── cmbuild.h.in │ ├── debug.h │ ├── err.h │ ├── graphics.h │ ├── osif.h │ ├── syscall.h │ └── types.h ├── compositor.h ├── config.h ├── drivers │ └── x86 │ │ └── pc │ │ ├── 8042_ps2.h │ │ ├── 8254_pit.h │ │ ├── 8259_pic.h │ │ ├── pcspeaker.h │ │ └── ps2_devices.h ├── guicolours.h ├── handle.h ├── intrusive_list.h ├── intrusive_queue.h ├── kassert.h ├── kcmlib.h ├── kdebug.h ├── kernel.h ├── kerror.h ├── kgraphics.h ├── kstdlib.h ├── memloc.h ├── memmanage.h ├── mock │ ├── cm │ │ └── cm.h │ └── kernel │ │ ├── bitmap.h │ │ ├── kstdlib.h │ │ ├── paging.h │ │ ├── pmm.h │ │ ├── salloc.h │ │ ├── vmm.h │ │ └── x86 │ │ ├── boot.h │ │ ├── paging.h │ │ ├── pmm.h │ │ └── vgatext.c ├── moslimits.h ├── mosunittest.h ├── paging.h ├── panic.h ├── pmm.h ├── process.h ├── types.h ├── unittest │ ├── fake.h │ └── unittest.h ├── utils.h ├── vmm.h ├── vmm_struct.h └── x86 │ ├── asm │ └── mos.inc │ ├── boot.h │ ├── boot_struct.h │ ├── config.h │ ├── cpu.h │ ├── gdt.h │ ├── gdt_struct.h │ ├── idt.h │ ├── idt_struct.h │ ├── interrupt.h │ ├── io.h │ ├── memloc.h │ ├── moslimits.h │ ├── paging.h │ ├── process.h │ ├── tss.h │ ├── types.h │ └── vgatext.h ├── scripts ├── create-floppyimg.sh ├── invokeprog.sh ├── lint.sh ├── postbuild.sh └── run.sh ├── src ├── apps │ ├── CMakeLists.txt │ ├── gui0.c │ ├── init.c │ ├── mpdemo.c │ └── proc1.c ├── bootloader │ └── x86 │ │ ├── CMakeLists.txt │ │ ├── boot0 │ │ ├── boot.s │ │ └── loadFile.s │ │ └── boot1 │ │ ├── a20gate.s │ │ ├── boot1.s │ │ ├── gdt.s │ │ └── vbe2.s ├── cm │ ├── CMakeLists.txt │ ├── cm.c │ ├── debug.c │ ├── graphics.c │ ├── malloc.c │ ├── printf.c │ ├── process.c │ ├── string.c │ ├── syscalls.c │ └── x86 │ │ └── crta.c ├── kernel │ ├── CMakeLists.txt │ ├── bitmap.c │ ├── compositor.c │ ├── drivers │ │ └── x86 │ │ │ └── pc │ │ │ ├── 8042_ps2.c │ │ │ ├── 8254_pit.c │ │ │ ├── 8259_pic.c │ │ │ ├── CMakeLists.txt │ │ │ ├── pcspeaker.c │ │ │ ├── ps2kb.c │ │ │ └── ps2mouse.c │ ├── handle.c │ ├── kdebug.c │ ├── kgraphics.c │ ├── kmalloc.c │ ├── kpanic.c │ ├── kstdlib.c │ ├── pmm.c │ ├── printk.c │ ├── salloc.c │ ├── vmm.c │ └── x86 │ │ ├── CMakeLists.txt │ │ ├── _gas_paging.s │ │ ├── boot.c │ │ ├── entry.s │ │ ├── gdt.c │ │ ├── idt.c │ │ ├── interrupts.c │ │ ├── kernel.c │ │ ├── kernel.ld │ │ ├── paging.c │ │ ├── pmm.c │ │ ├── process.c │ │ ├── process.ld │ │ ├── syscalls.c │ │ ├── tss.c │ │ └── vgatext.c ├── mock │ ├── cm │ │ └── cm.c │ ├── kernel │ │ ├── bitmap.c │ │ ├── kstdlib.c │ │ ├── paging.c │ │ ├── pmm.c │ │ ├── salloc.c │ │ ├── vmm.c │ │ └── x86 │ │ │ ├── boot.c │ │ │ ├── paging.c │ │ │ ├── pmm.c │ │ │ └── vgatext.c │ └── mockfortests_x86.cmake └── unittests │ ├── cm │ ├── CMakeLists.txt │ ├── common.c │ ├── malloc_test.c │ ├── printf_test.c │ └── string_test.c │ ├── kernel │ ├── CMakeLists.txt │ ├── bitmap_test.c │ ├── c99_conformance_test.c │ ├── common.c │ ├── handle_test.c │ ├── intrusive_list_test.c │ ├── intrusive_queue_test.c │ ├── kmalloc_test.c │ ├── kstdlib_test.c │ ├── paging_test.c │ ├── pmm_test.c │ ├── printk_test.c │ ├── salloc_test.c │ ├── utils_test.c │ └── x86 │ │ ├── CMakeLists.txt │ │ ├── paging_test.c │ │ └── pmm_test.c │ └── unittest.c └── tools ├── build_i686_gcc.sh ├── changenames.sh ├── indent.sh └── toolchain-i686-elf-pc.cmake /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: LLVM 2 | AlignArrayOfStructures: None 3 | AlignConsecutiveAssignments: Consecutive 4 | AlignConsecutiveDeclarations: None 5 | AlignConsecutiveBitFields: Consecutive 6 | AlignConsecutiveMacros: AcrossEmptyLinesAndComments 7 | AlignTrailingComments: true 8 | AlignEscapedNewlines: Left 9 | AllowShortBlocksOnASingleLine: Never 10 | AllowShortEnumsOnASingleLine: false 11 | AllowShortIfStatementsOnASingleLine: Never 12 | AllowShortCaseLabelsOnASingleLine: false 13 | AllowShortFunctionsOnASingleLine: false 14 | BreakBeforeBraces: Linux 15 | IndentWidth: 4 16 | ColumnLimit: 100 17 | SortIncludes: false 18 | KeepEmptyLinesAtTheStartOfBlocks: false 19 | PointerBindsToType: true 20 | SpacesBeforeTrailingComments: 1 21 | TabWidth: 4 22 | UseTab: Never 23 | IndentPPDirectives: BeforeHash 24 | SpaceBeforeParens: NonEmptyParentheses 25 | PenaltyBreakAssignment: 400 26 | PenaltyBreakOpenParenthesis: 900 27 | PenaltyBreakBeforeFirstCallParameter: 900 28 | Cpp11BracedListStyle: false 29 | -------------------------------------------------------------------------------- /.github/workflows/utbuild.yaml: -------------------------------------------------------------------------------- 1 | # This starter workflow is for a CMake project running on a single platform. There is a different starter workflow if you need cross-platform coverage. 2 | # See: https://github.com/actions/starter-workflows/blob/main/ci/cmake-multi-platform.yml 3 | name: Unittests build and run 4 | 5 | on: [push] 6 | 7 | jobs: 8 | builld_and_test: 9 | # The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac. 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v4 14 | 15 | - name: Install dependencies 16 | run: sudo apt-get install nasm gcc-multilib 17 | 18 | - name: Configure CMake 19 | run: cmake -B ${{github.workspace}}/build -DMARCH="pc" -DARCH="x86" 20 | 21 | - name: Build and run 22 | run: cmake --build ${{github.workspace}}/build --target run 23 | 24 | #- name: Test 25 | # working-directory: ${{github.workspace}}/build 26 | # run: cmake --build . --target run |grep -c FAIL > /dev/null; test $? -eq 1 27 | -------------------------------------------------------------------------------- /cmake/GenConfigHeaderFile.cmake: -------------------------------------------------------------------------------- 1 | 2 | # ================================================================================================== 3 | # Generates C header file to include all the build options for the Kernel. 4 | # The template of the header is taken from another file. 5 | # 6 | # It expects below arguments: 7 | # GenHeader - 1 (always), used to determine if the script was called properly. 8 | # Definitions - Build definitions each separated by space. Individual definitions must in the 9 | # following format: 10 | # * Definition 11 | # * Definition=value (no space around =) 12 | # HeaderFileDestinationPath - Full file name of the header file to generate 13 | # HeaderFileTemplatePath - Full file name of the template header file to generate from. 14 | # ================================================================================================== 15 | if (GenHeader) 16 | # Convert definitions from string to a CMake list. 17 | string(REPLACE " " ";" DefinitionList ${Definitions}) 18 | 19 | foreach(def IN LISTS DefinitionList) 20 | string(REPLACE "=" "\t" def ${def}) 21 | set(GEN_HEADER_CONTENTS "${GEN_HEADER_CONTENTS}\n#define ${def}") 22 | endforeach() 23 | 24 | configure_file(${HeaderFileTemplatePath} ${HeaderFileDestinationPath}) 25 | else() 26 | message(FATAL_ERROR "Should not be called/included on its own") 27 | endif() 28 | # ================================================================================================== 29 | -------------------------------------------------------------------------------- /cmake/x86/commonflags.cmake: -------------------------------------------------------------------------------- 1 | set(MOS_GCC_WARN_FLAGS 2 | -Wpedantic 3 | -Wall 4 | -Wextra 5 | -Wconversion 6 | -Wdangling-else 7 | -Werror 8 | ) 9 | 10 | set(MOS_GCC_FLAGS 11 | -std=c99 12 | -nostartfiles 13 | -ffreestanding 14 | -fno-pie 15 | -fno-stack-protector 16 | -fno-asynchronous-unwind-tables 17 | -m32 18 | -march=i686 19 | -masm=intel 20 | -mno-red-zone 21 | -mno-sse 22 | -malign-data=abi 23 | -Os 24 | -fno-unit-at-a-time 25 | -fno-omit-frame-pointer 26 | -fno-inline-functions-called-once 27 | ) 28 | 29 | set(MOS_LINKER_OPTIONS 30 | -ffreestanding 31 | -nostdlib 32 | ) 33 | -------------------------------------------------------------------------------- /cmake/x86/kernelflags.cmake: -------------------------------------------------------------------------------- 1 | include(${PROJECT_SOURCE_DIR}/cmake/${ARCH}/commonflags.cmake) 2 | 3 | # ---------------------------------------------------- 4 | # GCC 5 | # ---------------------------------------------------- 6 | set(MOS_KERNEL_GCC_FLAGS 7 | ${MOS_GCC_WARN_FLAGS} 8 | ${MOS_GCC_FLAGS} 9 | ) 10 | 11 | set(MOS_KERNEL_GCC_DEFINITIONS 12 | ${MOS_BUILD_MODE} 13 | MARCH=${MARCH} 14 | ARCH=${ARCH} 15 | KERNEL 16 | ) 17 | 18 | if (MOS_PORT_E9_ENABLED) 19 | list(APPEND MOS_KERNEL_GCC_DEFINITIONS PORT_E9_ENABLED) 20 | endif() 21 | 22 | set(MOS_KERNEL_GCC_INCLUDE_DIRS 23 | ${PROJECT_SOURCE_DIR}/include 24 | ) 25 | 26 | # ---------------------------------------------------- 27 | # NASM 28 | # ---------------------------------------------------- 29 | set(MOS_KERNEL_NASM_DEFINITIONS 30 | KERNEL 31 | ) 32 | 33 | set(MOS_KERNEL_NASM_BIN_MODE_FLAGS 34 | -O0 35 | -f bin 36 | ) 37 | 38 | set(MOS_KERNEL_NASM_ELF_MODE_FLAGS 39 | -O0 40 | -f elf 41 | ) 42 | 43 | set(MOS_KERNEL_ASM_INCLUDE_DIRS 44 | ${PROJECT_SOURCE_DIR}/include/asm 45 | ${PROJECT_SOURCE_DIR}/include/x86/asm 46 | ) 47 | 48 | # ---------------------------------------------------- 49 | # Both GCC & NASM 50 | # ---------------------------------------------------- 51 | if (MOS_BUILD_MODE STREQUAL "DEBUG") 52 | list(APPEND MOS_KERNEL_GCC_FLAGS -g) 53 | list(APPEND MOS_KERNEL_NASM_ELF_MODE_FLAGS -g) 54 | endif() 55 | 56 | If (MOS_GRAPHICS_ENABLED) 57 | list(APPEND MOS_KERNEL_GCC_DEFINITIONS 58 | GRAPHICS_MODE_ENABLED 59 | GRAPHICS_BPP=${MOS_GRAPHICS_BPP} 60 | ) 61 | 62 | list(APPEND MOS_KERNEL_NASM_DEFINITIONS 63 | GRAPHICS_MODE_ENABLED 64 | GRAPHICS_BPP=${MOS_GRAPHICS_BPP} 65 | ) 66 | endif() 67 | 68 | 69 | # ---------------------------------------------------- 70 | # LINKER 71 | # ---------------------------------------------------- 72 | set(MOS_KERNEL_LINKER_SCRIPT_FILE ${PROJECT_SOURCE_DIR}/src/kernel/x86/kernel.ld) 73 | -------------------------------------------------------------------------------- /cmake/x86/unittestflags.cmake: -------------------------------------------------------------------------------- 1 | set(MOS_UNITTESTS_GCC_WARN_FLAGS 2 | -wall 3 | -wextra 4 | ) 5 | 6 | set(MOS_UNITTESTS_GCC_FLAGS 7 | ${MOS_UNITTESTS_GCC_FLAGS} 8 | -std=c99 9 | -g 10 | -m32 11 | -march=i386 12 | -masm=intel 13 | --coverage 14 | ) 15 | 16 | set (MOS_UNITTESTS_GCC_DEFINITIONS 17 | UNITTEST 18 | ARCH=${ARCH} 19 | MARCH=${MARCH} 20 | ) 21 | 22 | 23 | if (MOS_BUILD_MODE STREQUAL "DEBUG") 24 | set(MOS_UNITTESTS_GCC_FLAGS ${MOS_UNITTESTS_GCC_FLAGS} -g) 25 | endif() 26 | 27 | set(MOS_UNITEST_LINKER_OPTIONS 28 | -m32 29 | ) 30 | 31 | set(MOS_ASM_INCLUDE_DIRS 32 | ${PROJECT_SOURCE_DIR}/include/asm 33 | ${PROJECT_SOURCE_DIR}/include/${ARCH}/asm 34 | ) 35 | 36 | set(MOS_GCC_INCLUDE_DIRS 37 | ${PROJECT_SOURCE_DIR}/include 38 | ) 39 | -------------------------------------------------------------------------------- /cmake/x86/userflags.cmake: -------------------------------------------------------------------------------- 1 | include(${PROJECT_SOURCE_DIR}/cmake/${ARCH}/commonflags.cmake) 2 | 3 | set(MOS_USER_GCC_FLAGS 4 | ${MOS_GCC_WARN_FLAGS} 5 | ${MOS_GCC_FLAGS} 6 | -fno-inline-small-functions 7 | ) 8 | 9 | set(MOS_USER_GCC_DEFINITIONS 10 | MARCH=${MARCH} 11 | ARCH=${ARCH} 12 | ) 13 | 14 | set(MOS_USER_GCC_INCLUDE_DIRS 15 | ${PROJECT_SOURCE_DIR}/include/cm 16 | ) 17 | 18 | set(MOS_USER_LINKER_SCRIPT_FILE ${PROJECT_SOURCE_DIR}/src/kernel/x86/process.ld) 19 | -------------------------------------------------------------------------------- /docs/PMM_Calculations.ods: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderarjob/meghaos-x86/247edf81c8e8400880ab4ae9795968adcb34ebfe/docs/PMM_Calculations.ods -------------------------------------------------------------------------------- /docs/collate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ################################################################################ 4 | replace_text_in_file() 5 | { 6 | if [ $# -ne 4 ]; then 7 | echo "$0 - Invalid number of arguments" 8 | exit 1 9 | fi 10 | 11 | local template_file=$1 12 | local outfile=$2 13 | local pattern=$3 14 | local replacement=$4 15 | 16 | # Sed will not work in this case because it cannot handle newlines in the 17 | # replacement text. 18 | # 19 | # AWK Manpage: An & in the replacement text is replaced with the text that 20 | # was actually matched. Use \& to get a literal &. 21 | replacement=${replacement//'&'/'\\&'} 22 | awk -v MD="$replacement" '{sub(/'$pattern'/, MD); print;}' \ 23 | $template_file > $outfile 24 | } 25 | 26 | form_pattern() 27 | { 28 | local categories=$@ 29 | export RETURN="%{$categories}%" 30 | } 31 | 32 | ################################################################################ 33 | 34 | TEMPLATE_FILE=index_template.md 35 | INDEX_FILE=index.md 36 | DIR=`dirname "$0"` 37 | 38 | doc_categories=('guideline independent' 39 | 'guideline x86' 40 | 'guideline independent obsolete' 41 | 'guideline x86 obsolete' 42 | 'feature independent' 43 | 'feature x86' 44 | 'feature independent obsolete' 45 | 'feature x86 obsolete' 46 | 'note independent' 47 | 'note x86' 48 | 'note independent obsolete' 49 | 'note independent feature' 50 | 'note x86 obsolete') 51 | 52 | ################################################################################ 53 | pushd "$DIR" 54 | 55 | temp_template_file="./.$TEMPLATE_FILE" 56 | cp "$TEMPLATE_FILE" "$temp_template_file" 57 | 58 | IFS='' # Loop should not split by space, which is the default value of IFS. 59 | for cate in ${doc_categories[@]}; do 60 | list=$(./titles.sh $cate) 61 | form_pattern $cate 62 | pattern=$RETURN 63 | replace_text_in_file "$temp_template_file" "$INDEX_FILE" "$pattern" "$list" 64 | cp "$INDEX_FILE" "$temp_template_file" 65 | done 66 | 67 | rm -f "$temp_template_file" 68 | 69 | popd 70 | -------------------------------------------------------------------------------- /docs/images/meghaos_gui0.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderarjob/meghaos-x86/247edf81c8e8400880ab4ae9795968adcb34ebfe/docs/images/meghaos_gui0.gif -------------------------------------------------------------------------------- /docs/images/meghaos_panic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderarjob/meghaos-x86/247edf81c8e8400880ab4ae9795968adcb34ebfe/docs/images/meghaos_panic.png -------------------------------------------------------------------------------- /docs/images/mos.rbm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderarjob/meghaos-x86/247edf81c8e8400880ab4ae9795968adcb34ebfe/docs/images/mos.rbm -------------------------------------------------------------------------------- /docs/index_template.md: -------------------------------------------------------------------------------- 1 | ## Megha Operating System - V2 2 | -------------------------------------------------------------------------------- 3 | 4 | **Run this command to refresh documents list: `bash collate.sh`** 5 | 6 | ### TODO 7 | - [TODO](notes/TODO.md) 8 | - [Scratch](notes/Scratch.md) 9 | - [BUGS](notes/BUGS.md) 10 | 11 | ### Guidelines Docs 12 | %{guideline independent}% 13 | 14 | ### Obsolete Guidelines Docs 15 | %{guideline independent obsolete}% 16 | 17 | ### x86 Guidelines Docs 18 | %{guideline x86}% 19 | 20 | ### Obsolete x86 Guidelines Docs 21 | %{guideline x86 obsolete}% 22 | ------------------------------------------------ 23 | ### Features Docs 24 | %{feature independent}% 25 | 26 | ### Obsolete Features Docs 27 | %{feature independent obsolete}% 28 | 29 | ### x86 Features Docs 30 | %{feature x86}% 31 | 32 | ### Obsolete x86 Features Docs 33 | %{feature x86 obsolete}% 34 | 35 | ------------------------------------------------ 36 | ### Notes 37 | %{note independent}% 38 | 39 | ### Future feature ideas 40 | %{note independent feature}% 41 | 42 | ### x86 Notes 43 | %{note x86}% 44 | 45 | ### Obsolete Notes 46 | %{note independent obsolete}% 47 | 48 | ### Obsolete x86 Notes 49 | %{note x86 obsolete}% 50 | -------------------------------------------------------------------------------- /docs/memmap.ods: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderarjob/meghaos-x86/247edf81c8e8400880ab4ae9795968adcb34ebfe/docs/memmap.ods -------------------------------------------------------------------------------- /docs/notes/CrossPlatform.md: -------------------------------------------------------------------------------- 1 | ## Megha Operating System V2 - x86 2 | --------------------------------------------------------------------------------------------------- 3 | 4 | ## Cross platform guidelines 5 | categories: guideline, independent 6 | 7 | To make MeghaOS cross platform, we need to ensure little or no direct use (also called coupling) of 8 | platform dependent (PD) code in platform independent (PI) parts of the OS. The following guidelines 9 | will ensure that at the time of adding new architecture there is little change to be made in PI 10 | codes. 11 | 12 | 1. PI code must not call/use PD resources/items directly. Although the reverse is accectable and 13 | will cause no issues. If there is indeed a need to directly use a PD resource (in PI code), then 14 | here are some ways to do that: 15 | a. Introduce an PI abstraction, implemented for each platform in platform dependent way. The 16 | abstraction itself will be platform independent. See below point 2. 17 | b. Use `#if` guards to enclose uses of PI items. When adding a new arch, 18 | new guards need to added in the file. Even though this makes such files no completely be 19 | PI, this is a simple solution with no extra headers or abstractions. I am one man, I have 20 | to cut corners sometimes. 21 | 2. Types/functions/macros which must be present in every arch but whose implementation are platform 22 | dependent. 23 | a. We can use PI opaque types or if possible use unions to make the PI type large enough for any 24 | cast from PD implementation to not fail. Like the implementation of Socket addresses in 25 | Berkly socket. At this point there are no such example from MeghaOS. 26 | b. Declare a function in a PI header file, but implement it in a PD C source file. 27 | This is done for example in the case of `kdisp_ioctl`. It is defined in `include/disp.h` 28 | whose implementation is in `src/kernel/x86/vgadisp.c` 29 | c. Declare typedefs/macros in a PD header file and include the header file in another PI header 30 | file. As the typedefs/macros will be present in every arch, PI part of code can use them 31 | without any problem. 32 | Examples are PI header `include/types.h` includes PD header `include/x86/types.h` which have 33 | concrete implementations for x86 arch. `include/config.h` is another example. 34 | -------------------------------------------------------------------------------- /docs/notes/Vbe.md: -------------------------------------------------------------------------------- 1 | # Megha Operating System V2 - x86 2 | ------------------------------------------------------------------------------ 3 | 4 | ## VESA VBE Graphics mode 5 | categories: feature, x86 6 | 7 | For builds with graphics enabled, bootloader `boot1` first checks for availability of VBE functions 8 | and then selects the first graphics mode which matches every search criteria. 9 | 10 | | Criteria | Value | 11 | |---------------------------|-------------------------------------------------| 12 | | X Resolution | 800 | 13 | | Y Resolution | 600 | 14 | | Bits/pixel | 32 | 15 | | Mode attributes | Graphics mode and Linear frame buffer | 16 | | Memory model | Packed pixel or DirectColor | 17 | | RGBPosition (DirectColor) | Position R,G,B fields positions to be 16,8 & 0. | 18 | 19 | 32 color is selected just because its supported more or less by every emulator and modern PCs. Also 20 | it is easier to adopt drawing functions for 24 and 8 bit color if they were first implemented for 32 21 | bit one. 22 | 23 | 24 bit color and 8 bit colors are not always supported either by the actual hardware or by 24 | emulators. VESA modes which used to be 24 bits now are 32 bits in modern systems For example, mode 25 | 0x115 used to be 800 x 600, 24bpp, but on my laptop the same mode is 800 x 600, 32bpp. 26 | 27 | 800 x 600, 8bpp is also not a standard SVGA mode and thus support is not always present. Another 28 | problem with 8 bit color is due to it being a indexed color, the color palette may not be all same 29 | in every system. For example VirtualBox have a different palette all together and colors all look 30 | wrong.. 31 | 32 | Note that resolution is less of a problem, we can change that easily if the support of color depth 33 | is present. So if we want to run MeghaOS in 1024 x 768 resolution, we just have to mention the 34 | resolution in 'mos.inc' and 'x86/config.h' files. 35 | 36 | If you want to try 8 bit or 24 bit color, change corresponding settings in the above mentioned two 37 | files. 38 | -------------------------------------------------------------------------------- /docs/notes/abi.md: -------------------------------------------------------------------------------- 1 | # Megha Operating System V2 - x86 2 | ------------------------------------------------------------------------------ 3 | 4 | ## Operating System ABI 5 | categories: feature, x86 6 | 7 | ### General 8 | 9 | * When Kernel passes control to the new Process, the GP registers can have any value, except ESP and 10 | EBP. ESP will point to the process stack top and EBP will be zero. 11 | * Stack and Data segment registers must be the same (at all time, this a limitation of modern 12 | Compilers) 13 | * Return value is passed using EAX register. Can also be garbage for `void` functions. 14 | * CDECL calling convention is followed. 15 | 16 | ### System call 17 | 18 | #### Passing of arguments 19 | Arguments to system calls are passed via GP registers. The EAX register is used to pass the syscall 20 | function number to the syscall dispatcher routine. Arguments to the syscall routine are passed via 21 | EBX, ECX, EDX, ESI, EDI registers respectively. 22 | 23 | #### Return value from the system call 24 | Apart from the EAX register, syscall routines can also write to a pointer argument to pass values 25 | that way. 26 | 27 | #### Preservation of states 28 | 29 | The syscall dispatcher routine preserves the state of ESP, EBP, EBX, ECX, EDX, ESI, EDI registers. 30 | EAX is not preserved and can be garbage if the system call routine returns void. It also does not 31 | preserve segment, floating point, MMX etc registers. 32 | 33 | #### Signature of system call routines 34 | 35 | Because of interrupt gate, the processor pushes an Interrupt frame on the stack (kernel stack). This 36 | interrupt frame contains, among other things, the return address. 37 | 38 | Pointer to this interrupt frame is always the first argument and only mandatory argument in the 39 | system call signature. After this one there can be at most 5 arguments of U32 type. Not every system 40 | call must have all 5 argument, that is the maximum amount. 41 | 42 | So all of these are valid signatures: 43 | ``` 44 | void sys_foo_1 (InterruptFrame* frame); 45 | void sys_foo_2 (InterruptFrame* frame, U32 type, char* text); 46 | ``` 47 | 48 | ------------------------------------------------------------------------------ 49 | -------------------------------------------------------------------------------- /docs/notes/abstract_design.md: -------------------------------------------------------------------------------- 1 | # Megha Operating System V2 - x86 2 | ------------------------------------------------------------------------------ 3 | 4 | ## Abstraction is Key for a modular Operating System 5 | categories: note, independent 6 | _25 June 2022_ 7 | 8 | MeghaOS is after all a learning project, this means it should be easier to change parts of the OS 9 | and still be robust. 10 | 11 | If I think about it, there already exists one architecture which allows change. It is the device 12 | driver model. What is so special about this model? Abstraction. 13 | 14 | So my plan is to have almost every part of the OS be behind an abstraction. Other parts of the OS 15 | will talk to this abstraction when it wants to talk to that part. From Physical Memory manager to 16 | scheduling, should have this abstraction. What will come out of this is that the implementation can 17 | be changed without effecting the rest of the OS (provided the implementation worked well, but there 18 | should be no integration issues). 19 | 20 | And if integrated to some devFS, sysFS etc, these modules will be available to the users as files. 21 | This will amaizing be to be able to to read say the PAB (Physical Allocation Bitmap) by reading a 22 | file. 23 | 24 | Let me give an example of Physical Memory Manager: 25 | 26 | ``` 27 | PMM (Implementation) PWM (Abstraction) Kernel User Programs 28 | ^............................^ ^----------^ ^----------------^ 29 | Implements Calls 30 | 31 | ==================== ============================================ 32 | kernel/x86/pmm.c kernel/x86/interface/pmm.c 33 | ==================== ============================================ 34 | var *g_pam global func get_PAM 35 | staic func allocate global func allocate 36 | static func deallocate global func deallocate 37 | static func init global func pmm_set_operations 38 | ==================== global struct {pam, alloc, dealloc} pmm_op 39 | static var *op 40 | ============================================ 41 | ``` 42 | 43 | Just like drivers, pmm module defines and fills an instance of pmm_op and calls 44 | pmm_set_operations to set a pointer and from that time, calls to allocate (global) will call 45 | the allocate method in the implementation. 46 | 47 | If there is another implementation, it will simply call pmm_set_operations to set it self as 48 | the active implementation, then from that point in time on, it will reveive the allocate and 49 | deallocate calls from the abstraction. 50 | 51 | **Note:** 52 | The methods in the abstraction can only be called from programs running the kernel space. 53 | User programs cannot call the abstraction methods directly. They must either interact with the 54 | correcponsing file or call a system call if available. 55 | -------------------------------------------------------------------------------- /docs/notes/changes.md: -------------------------------------------------------------------------------- 1 | ## Megha Operating System V2 - x86 - Updated 2 | ------------------------------------------------------------------------------ 3 | 4 | ### 9th Nov 2020 5 | 6 | * assert.h holds parent assert functions. Assert routines calls `kpanic` if 7 | some predicate is **false**. 8 | kstatic_assert(t) and kassert(t,e) 9 | 10 | * Other assert functions must ultimately call the `kassert()` function. 11 | For example `kassert_perror()` calls `kassert()` when `kerrno != ERR_NONE`. 12 | 13 | * All assert functions must respect the DEBUG/NDEBUG macros, and must produce 14 | no output if DEBUG macro is not defined. 15 | 16 | * Every place where must be a hard stop, `kpanic` must be called. Do not use 17 | `kassert` there. 18 | 19 | * There is no `cross platform kernel.c` file, becuase it is not required at 20 | this point of time. When and if needed in future, it will be created. 21 | 22 | * Think of Terry A. Davis. His operating system may had many faults, but it was 23 | original and upto the idea he had in his mind. He wanted a 64 bit C64 and he 24 | did exactly that. 25 | 26 | The MeghaOs is the Operating System for my use. And it is okay to make 27 | mistakes. 28 | -------------------------------------------------------------------------------- /docs/notes/cmake-build.md: -------------------------------------------------------------------------------- 1 | # Megha Operating System V2 2 | ------------------------------------------------------------------------------ 3 | 4 | ## Equivalence of ELF and flat binary files before and after CMake 5 | categories: note, independent 6 | 25 May 2024 7 | 8 | Binary equivalence of ELF object files depend on two factors: 9 | 1. Build mode is NDEBUG 10 | 2. `-g` compilation option is not added. 11 | 12 | If they are not met then the ELF object files will differ in size and context. This difference comes 13 | due to the source file paths stored in debugging sections and in `.rodata` section for k_assert. For 14 | flat binaries there are no debugging data, but the data in `.rodata` section differences still 15 | remains. 16 | 17 | If the above two conditions are met, then the ELF object files are binary equivalent i.e kmalloc.o 18 | (from build.sh) and kmalloc.c.obj (from cmake) are equivalent. 19 | 20 | When the above conditions are met the flat binaries (can be produced using `objdump -O binary `) of these object files are also binary equivalent. 22 | 23 | When these ELF object files are linked to produce Kernel ELF binary the binaries may differ in size 24 | and content. This difference is due to the order in which the object files are linked and padding 25 | bytes. These differences translate to the flat binaries produced from it. 26 | 27 | However for single source file programs (in case of mpdemo & prog1) there can be no ordering issues 28 | and thus we see no there is no difference either in the ELF files produced after linking or the flat 29 | binaries produced for it. 30 | 31 | Here are some data: 32 | ``` 33 | ---------------|--------|----------|-------|------------|-------------------------------------------- 34 | cmake build.sh 35 | sizes sizes Mode Difference Reason 36 | ---------------|--------|----------|-------|------------|-------------------------------------------- 37 | Kernel.elf 39496 39448 NDEBUG 048 bytes Extra padding bytes due to linking order. 38 | kernel.flt 25128 25104 NDEBUG 024 bytes Extra padding bytes due to linking order. 39 | 35936 35672 DEBUG 264 bytes DEBUG mode has source file info. 40 | __FILE__s 35472 35464 DEBUG 008 bytes Extra padding bytes due to linking order. 41 | removes 42 | ---------------|--------|----------|-------|------------|-------------------------------------------- 43 | mpdemo.elf 5536 5536 NDEBUG 000 bytes Equivallent 44 | mpdemo.flt 872 872 NDEBUG 000 bytes Equivallent 45 | ---------------|--------|----------|-------|------------|-------------------------------------------- 46 | ``` 47 | 48 | -------------------------------------------------------------------------------- /docs/notes/interrupt_handling.md: -------------------------------------------------------------------------------- 1 | ## Megha Operating System V2 - x86 2 | ------------------------------------------------------------------------------ 3 | 4 | ## Interrupt handling 5 | categories: feature, x86 6 | 7 | ## Processor Interrupt frame 8 | 9 | ### Current Privilege level (before interrupt) > 0: 10 | 11 | ``` 12 | Offset Register 13 | ------ -------------- 14 | 0 SS <-- High memory 15 | 4 ESP 16 | 8 EFLAGS 17 | 12 CS 18 | 16 EIP 19 | 20 Error code (not always) <-- Low memory 20 | ``` 21 | 22 | ### Current Privilege level (before interrupt) = 0: 23 | 24 | ``` 25 | Offset Register 26 | ------ -------------- 27 | 8 EFLAGS <-- High memory 28 | 12 CS 29 | 16 EIP 30 | 20 Error code (not always) <-- Low memory 31 | ``` 32 | 33 | ## OS Interrupt frame 34 | 35 | ``` 36 | Offset Register 37 | ------ -------------- 38 | 0 EAX <-- High memory 39 | 4 ECX 40 | 8 EDX 41 | 12 EBX 42 | 16 Original ESP 43 | 20 EBP 44 | 24 ESI 45 | 28 EDI 46 | 32 DS 47 | 36 ES 48 | 40 FS 49 | 44 GS <-- Low memory 50 | 51 | Frame Size = 4 * 12 = 48 Bytes 52 | ``` 53 | 54 | The asm handler routine must preserve all the registers before calling the C handler function. This 55 | is because every register are not 'Caller preserved' according to the C ABI. 56 | 57 | > System V ABI: 58 | > Registers EBP, EBX, EDI, ESI and ESP 'belong' to the calling function. In other words, a called 59 | > function must preserve these registers’ values for its caller. 60 | > Remaining registers 'belong' to the called function. If a calling function wants to preserve 61 | > such a register value across a function call, it must save the value in its local stack frame. 62 | 63 | We keep things simple and preserve every general purpose as well as segment registers. Segment 64 | registers as can be seen from the ABI statement, are also not preserved. 65 | 66 | EFLAGS register is not preserved in the OS interrupt frame as it is preserved by the processor in 67 | the Processor's Interrupt frame before calling the interrupt handler. 68 | -------------------------------------------------------------------------------- /docs/notes/memorymanagement.md: -------------------------------------------------------------------------------- 1 | # Megha Operating System V2 - x86 2 | ------------------------------------------------------------------------------ 3 | 4 | ## Physical page allocation basics 5 | categories: note, x86 6 | 7 | Currently GDT, IDT are all at a fixed memory location. The GDT which is 8 | initially set by 'boot1', is at physical 0x800 location and IDT is set by the 9 | kernel at location physical 0x0000. 10 | 11 | These fixed addresses, will be moved to new allocations by the memory manager. 12 | The TSS instance is allocated on the .bss by the linker. This too will be 13 | moved to an address provided by the MM. 14 | 15 | 1. Physical page allocation 16 | ---------------------------- 17 | I partition the physical memory into 4 KByte pages and will use a bitmap 18 | (Page Allocation Bitmap/PAB) to keep track of free physical memory pages. 19 | Each bit in this map correspond to a physical memory page. 20 | 21 | The amount of physical memory, which MOS supports, determines the size of PAB. 22 | bitmap_size_byte = (Ram_Bytes/4096)/8 23 | bitmap_size_page = bitmap_size_byte/4096 24 | 25 | Below table shows, how PAB size changes with RAM size. 26 | |-----------|-------------|-------------| 27 | | Ram_Bytes | bitmap_page | bitmap_size | 28 | |-----------|-------------|-------------| 29 | | 4 GB | 32 | 128 KB | 30 | | 128 MB | 1 | 4 KB | 31 | | 256 MB | 2 | 8 KB | 32 | | 64 MB | 0.5 | 2 KB | 33 | | 32 MB | 0.25 | 1 KB | 34 | |-----------|-------------|-------------| 35 | 36 | Thus supporting 4 GB of RAM, is not too much of an overhead, just 128 KB of 37 | PAB. But for a small OS like MOS, at this stage, 4 GB is just overkill. I want 38 | to start small and grow from there. 39 | 40 | The PAB size will thus be determined by the MAX RAM supported by the build. 41 | 42 | [!] But how small do I want to start? 43 | 32 MB. Why not! 44 | 45 | [!] Where should PAB reside? In the bss, allocated by the linker, or 46 | calculated dynamically and placed say after page0. 47 | -------------------------------------------------------------------------------- /docs/notes/recursive_map_clarity_with_example.md: -------------------------------------------------------------------------------- 1 | # Megha Operating System V2 - x86 2 | ------------------------------------------------------------------------------ 3 | 4 | ## Recursive mapping and temporary mapping in Kernel 5 | categories: note, x86 6 | _24 Feb 2024_ 7 | 8 | ### Introduction 9 | 10 | When you add an entry to a PDE (which is a physical page), if recursive mapping is setup you will 11 | find two Virtual addresses for the physical page. One using the PDE you just added and another 12 | because of the recursive mapping setup. 13 | 14 | ### Notation used 15 | 16 | | Notation | Description | Example | 17 | |------------|-----------------------------------------------------------|------------------------| 18 | | A[X] | Access item at index X. Each of the items is of type A. | PDE[768] | 19 | | [A:B:C] X | Virtual address X from PDE[A], PTE[B] and offset C. | [1023:0:0] 0xFFC0_0000 | 20 | | A[X], B[Y] | Nested access item at index Y (of type B) within the item | PDE[768]PTE[0] | 21 | | | at index X (of type A). | | 22 | 23 | ### Basics uses of Recursive mapping 24 | 25 | Now the kernel uses the PDE[1023] for recursive mapping. This allows us to do the following: 26 | 27 | ##### To access each PDE like an array: 28 | ``` 29 | PDE[0] to PDE[1023] -> [1023:1023:0000] 0xFFFF_F000 to [1023:1023:1023] 0xFFFF_FFFC 30 | ``` 31 | 32 | ##### To Access each PTE like an array 33 | ``` 34 | PDE[0], PTE[0] to PTE[1023] -> [1023:0000:0000] 0xFFC0_0000 to [1023:0000:1023] 0xFFC0_0FFC. 35 | PDE[1], PTE[0] to PTE[1023] -> [1023:0001:0000] 0xFFC0_1000 to [1023:0001:1023] 0xFFC0_1FFC. 36 | PDE[768], PTE[0] to PTE[1023] -> [1023:0768:0000] 0xFFF0_0000 to [1023:0768:1023] 0xFFF0_0FFC. 37 | PDE[769], PTE[0] to PTE[1023] -> [1023:0769:0000] 0xFFF0_1000 to [1023:0769:1023] 0xFFF0_1FFC. 38 | ``` 39 | 40 | Here is the actual mapping at kenrel initialization (after enabling recursive mapping) 41 | 42 | ``` 43 | 0x00000000c0000000-0x00000000c01fffff -> 0x000000000000-0x0000001fffff 44 | 0x00000000fff00000-0x00000000fff00fff -> 0x000000044000-0x000000044fff 45 | 0x00000000fffff000-0x00000000ffffffff -> 0x000000043000-0x000000043fff 46 | ``` 47 | 48 | ### Temporary mapping pages 49 | 50 | Temporary mapping is used to map a physical page into the current kernel address space. I say 51 | 'Kernel' address space and not 'current' address space because the Kernel page table is used. This 52 | means the temporary map is not 'per-process'. Previously this was not the case when one entry in the 53 | PD of the current process was used for temporary map. However that approach had the issue where 54 | seemingly sporadic changes happened to the address space as MMU is interpreting the contents of the 55 | temporarily mapped as a valid page table. 56 | 57 | Anyways the current mapping is 58 | ``` 59 | PDE[768], PTE[1023] -> [768:1023:0000] 0xC03F_F000 to [768:1023:1023] 0xC03F_FFFC 60 | ``` 61 | 62 | This temporary mapping does not have user access (only kernel can read/write to this page). 63 | -------------------------------------------------------------------------------- /docs/notes/usermode_stack.md: -------------------------------------------------------------------------------- 1 | # Megha Operating System V2 - x86 2 | ------------------------------------------------------------------------------ 3 | 4 | ## What happens if kernel stack is used in user mode 5 | categories: note, x86 6 | _31 Mar 2024_ 7 | 8 | The use of kernel stack also in user mode, will cause stack corruption. The CPU sets the stack 9 | pointer to `Kernel Stack Top` when going from user mode to kernel mode. 10 | 11 | Then any Push in the Kernel space will overwrite the user stack. The SS & ESP itself will be 12 | restored when returning from an Interrupt, however the because the memory remains the common, it 13 | gets modified by the stack operations of the Kernel mode. 14 | -------------------------------------------------------------------------------- /docs/paging.ods: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderarjob/meghaos-x86/247edf81c8e8400880ab4ae9795968adcb34ebfe/docs/paging.ods -------------------------------------------------------------------------------- /docs/titles.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | TAG_LINE_PATTERN="categories" 4 | TAG_PAT="" 5 | 6 | if [ $# -eq 0 ]; then 7 | echo "Usage: $0 category [category] ..." 8 | exit 1 9 | fi 10 | 11 | for arg in $@; do 12 | TAG_PAT="${TAG_PAT}.*$arg" 13 | done 14 | TAG_PAT="${TAG_PAT}[\ \t]*$" 15 | 16 | FILES_WITH_TITLE=$(grep -a -B1 --no-group-separator \ 17 | -ire "^$TAG_LINE_PATTERN$TAG_PAT" | \ 18 | grep -v "$TAG_LINE_PATTERN") 19 | 20 | IFS=$'\n' # $'' expands to the escape character. Here its new line. 21 | for data in ${FILES_WITH_TITLE[@]}; do 22 | filename=${data%.md-*} # Get filename. Eveything left of the first `.md` 23 | title=${data#*-##\ } # Title style 2. Everything right of the first -# 24 | title=${title#\ *} # Remove leading space 25 | id=${title//\ /-} # Replace spaces with `-` (To be valid links) 26 | id=${id//\?/} # Remove `?`s (To be valid links) 27 | echo "- [$title]($filename.md#$id)" 28 | done 29 | -------------------------------------------------------------------------------- /docs/x86_intel_protection.odt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderarjob/meghaos-x86/247edf81c8e8400880ab4ae9795968adcb34ebfe/docs/x86_intel_protection.odt -------------------------------------------------------------------------------- /include/asm/csh.s: -------------------------------------------------------------------------------- 1 | 2 | 3 | %ifndef __CSH_S__ 4 | %define __CSH_S__ 5 | 6 | ; Calculates the cylinder/track, circular sector and head for INT 0x14 7 | ; Input: 8 | ; AX - Sector number 9 | ; Output: 10 | ; ch - Cylinder number 11 | ; dl - sector number (1 - 63) 12 | ; dh - head number 13 | csh: 14 | push ax 15 | push bx 16 | 17 | ; disk sector (circular sector) 18 | xor dx, dx ; clear dx again, for second div 19 | div word [SectorsPerTrack] 20 | add dx, 1 ; sector starts from 1 in INT 13 21 | mov bl, dl ; save the sector in BL 22 | 23 | ; track with more than one head 24 | xor dx, dx 25 | div word [HeadCount] 26 | mov ch, al ; cylinder 27 | mov cl, bl ; sector 28 | mov dh, dl ; head 29 | mov dl, 0 ; disk 0 30 | 31 | pop bx 32 | pop ax 33 | ret 34 | %endif ; __CSH_S__ 35 | 36 | -------------------------------------------------------------------------------- /include/bitmap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - Cross Platform Kernel - Bitmap 4 | * 5 | * Bitmap implementation for use in the OS. 6 | * --------------------------------------------------------------------------- 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | 14 | typedef U8 BitmapState; 15 | 16 | typedef struct Bitmap 17 | { 18 | BitmapState *bitmap; /* Pointer to the actual Bitmap */ 19 | SIZE size; /* Number of bytes in the bitmap array. */ 20 | SIZE bitsPerState; /* one state in bitmap requires this many bits. Must be a factor 21 | of 8. */ 22 | bool (*allow)(UINT index, 23 | BitmapState old, 24 | BitmapState new); /* Function returns true if state change can be done. */ 25 | } Bitmap; 26 | 27 | #define BITMAP_MAX_STATE(b) (POWER_OF_TWO((b)->bitsPerState)) 28 | #define BITMAP_STATE_MASK(b) (POWER_OF_TWO((b)->bitsPerState) - 1) 29 | #define BITMAP_STATES_PER_BYTE(b) (8 / ((b)->bitsPerState)) 30 | #define BITMAP_CAPACITY(b) ((b)->size * BITMAP_STATES_PER_BYTE(b)) 31 | 32 | BitmapState bitmap_get (Bitmap *b, UINT index); 33 | bool bitmap_setContinous (Bitmap *b, UINT index, UINT len, BitmapState state); 34 | INT bitmap_findContinous (Bitmap *b, BitmapState state, UINT len); 35 | bool bitmap_findContinousAt (Bitmap *b, BitmapState state, UINT len, UINT indexAt); 36 | -------------------------------------------------------------------------------- /include/buildcheck.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - Checks build environment. 4 | * --------------------------------------------------------------------------- 5 | */ 6 | 7 | #if __STDC_VERSION__ >= 199901 8 | #define __C99__ 9 | #endif 10 | 11 | #if defined(__linux__) && !defined(UNITTEST) 12 | #error "You are targetting Linux. Which is wrong!" 13 | #endif 14 | 15 | #if !defined(__i386__) && !(defined(UNITTEST) && ARCH == x86) 16 | #error "You are not targetting i386." 17 | #endif 18 | 19 | #if !defined (DEBUG) && !defined(GRAPHICS_MODE_ENABLED) && !defined (UNITTEST) 20 | #error "Non-Graphics mode is only for debug." 21 | #endif 22 | 23 | #if !defined (DEBUG) && defined(PORT_E9_ENABLED) && !defined (UNITTEST) 24 | #error "PORT 0xE9 is for debug mode only." 25 | #endif 26 | -------------------------------------------------------------------------------- /include/cm/cmbuild.h.in: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - Cross Platform Kernel - Kernel build definitions 4 | * --------------------------------------------------------------------------- 5 | * :::: Auto generated header file template :::: 6 | * This file contains compiler definitions used for the build 7 | * --------------------------------------------------------------------------- 8 | */ 9 | 10 | #pragma once 11 | 12 | @GEN_HEADER_CONTENTS@ 13 | -------------------------------------------------------------------------------- /include/cm/debug.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------- 3 | * Megha Operating System V2 - Mos libc - Library debug 4 | * ------------------------------------------------------------------------------------------------- 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #ifndef LIBCM 11 | #include 12 | #endif 13 | 14 | #if defined(DEBUG) && defined(PORT_E9_ENABLED) 15 | typedef enum CM_DebugLogType { 16 | CM_DEBUG_LOG_TYPE_INFO, 17 | CM_DEBUG_LOG_TYPE_FUNC, 18 | CM_DEBUG_LOG_TYPE_ERROR, 19 | CM_DEBUG_LOG_TYPE_WARN, 20 | } CM_DebugLogType; 21 | 22 | void cm_debug_log_ndu (CM_DebugLogType type, const char* func, UINT line, char* fmt, ...); 23 | 24 | #define CM_DBG_INFO(...) \ 25 | cm_debug_log_ndu (CM_DEBUG_LOG_TYPE_INFO, __func__, __LINE__, __VA_ARGS__) 26 | #define CM_DBG_ERROR(...) \ 27 | cm_debug_log_ndu (CM_DEBUG_LOG_TYPE_ERROR, __func__, __LINE__, __VA_ARGS__) 28 | #define CM_DBG_FUNC_ENTRY(...) \ 29 | cm_debug_log_ndu (CM_DEBUG_LOG_TYPE_FUNC, __func__, __LINE__, "" __VA_ARGS__) 30 | #define CM_DBG_WARN(...) \ 31 | cm_debug_log_ndu (CM_DEBUG_LOG_TYPE_WARN, __func__, __LINE__, __VA_ARGS__) 32 | #else 33 | #define CM_DBG_INFO(...) (void)0 34 | #define CM_DBG_ERROR(...) (void)0 35 | #define CM_DBG_FUNC_ENTRY(...) (void)0 36 | #define CM_DBG_WARN(...) (void)0 37 | #endif // PORT_E9_ENABLED 38 | 39 | #if defined(DEBUG) 40 | /*************************************************************************************************** 41 | * Magic break point used by bochs emulator 42 | * 43 | * @return Nothing 44 | **************************************************************************************************/ 45 | #define cm_debug_bochs_breakpoint() __asm__ volatile("xchg bx, bx") 46 | 47 | #if ARCH == x86 48 | #define cm_debug_x86_outb(p, v) __asm__ volatile("out dx, al;" : : "a"(v), "d"(p)) 49 | #define cm_debug_x86_inb(p, v) __asm__ volatile("in al, dx" : "=a"(v) : "d"(p)) 50 | #endif 51 | #endif // DEBUG 52 | -------------------------------------------------------------------------------- /include/cm/err.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - C MOS App library - Library errors 4 | * --------------------------------------------------------------------------- 5 | */ 6 | 7 | #include 8 | #if defined(LIBCM) || defined (UNITTEST) 9 | #include 10 | #include 11 | #include 12 | #else 13 | #include 14 | #include 15 | #include 16 | #endif 17 | 18 | #define CM_FAILURE (-1) 19 | 20 | typedef enum CMErrors { 21 | // OS Errors start from 0 and must end before the start of library errors 22 | LIBRARY_ERRORS_START = 100, 23 | CM_ERR_INVALID_INPUT = 100, 24 | CM_ERR_EVENT_HANDLER_ALREADY_REGISTERED = 101, 25 | CM_ERR_OUT_OF_HEAP_MEM = 102, 26 | } CMErrors; 27 | 28 | uint32_t cm_get_lib_error(); 29 | 30 | static inline uint32_t cm_get_os_error() 31 | { 32 | return (uint32_t)syscall (OSIF_SYSCALL_GET_OS_ERROR, 0, 0, 0, 0, 0); 33 | } 34 | -------------------------------------------------------------------------------- /include/cm/graphics.h: -------------------------------------------------------------------------------- 1 | /* 2 | * -------------------------------------------------------------------------------------------------- 3 | * Megha Operating System V2 - Cross Platform Kernel - Kernel graphics header 4 | * -------------------------------------------------------------------------------------------------- 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #if defined(LIBCM) || defined (UNITTEST) 11 | #include 12 | #else 13 | #include 14 | #endif 15 | 16 | // This is a arch independent color type large enough for all the color modes supported. 17 | typedef U32 Color; 18 | typedef OSIF_WindowFrameBufferInfo GraphicsContext; 19 | 20 | void graphics_rect (const GraphicsContext* g, UINT x, UINT y, UINT w, UINT h, Color color); 21 | void graphics_image_ppm (const GraphicsContext* g, UINT x, UINT y, UINT w, UINT h, 22 | UINT bytesPerPixel, U8* bytes); 23 | void graphics_drawfont (const GraphicsContext* g, UINT x, UINT y, UCHAR a, Color fg, Color bg); 24 | void graphics_putpixel (const GraphicsContext* g, UINT x, UINT y, Color color); 25 | void kgraphics_blit (const GraphicsContext* destg, UINT x, UINT y, const GraphicsContext* srcg); 26 | 27 | static inline void kgraphics_hline (const GraphicsContext* g, UINT x, UINT y, UINT w, UINT th, 28 | Color color) 29 | { 30 | graphics_rect (g, x, y, w, th, color); 31 | } 32 | 33 | static inline void kgraphics_vline (const GraphicsContext* g, UINT x, UINT y, UINT h, UINT th, 34 | Color color) 35 | { 36 | graphics_rect (g, x, y, th, h, color); 37 | } 38 | 39 | /* Draws rectangle with borders on the inside of a rectangle */ 40 | static inline void kgraphics_inborder (const GraphicsContext* g, UINT x, UINT y, UINT w, UINT h, 41 | UINT th, Color color) 42 | { 43 | kgraphics_hline (g, x, y, w, th, color); // Top 44 | kgraphics_vline (g, x, y, h, th, color); // Left 45 | kgraphics_vline (g, (x + w - th), y, h, th, color); // Right 46 | kgraphics_hline (g, x, (y + h - th), w, th, color); // Bottom 47 | } 48 | -------------------------------------------------------------------------------- /include/cm/osif.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------- 3 | * Megha Operating System V2 - OS, application library interfaces 4 | * ------------------------------------------------------------------------------------------------- 5 | */ 6 | 7 | #pragma once 8 | #include 9 | 10 | typedef struct OSIF_WindowFrameBufferInfo { 11 | UINT width_px; 12 | UINT height_px; 13 | UINT bytesPerPixel; 14 | UINT bytesPerRow; 15 | U8* buffer; 16 | SIZE bufferSizeBytes; 17 | } OSIF_WindowFrameBufferInfo; 18 | 19 | typedef enum OSIF_SYSCALLS { 20 | OSIF_SYSCALL_CONSOLE_WRITELN = 0, 21 | OSIF_SYSCALL_CREATE_PROCESS = 1, 22 | OSIF_SYSCALL_YIELD_PROCESS = 2, 23 | OSIF_SYSCALL_KILL_PROCESS = 3, 24 | OSIF_SYSCALL_CONSOLE_SETCOLOR = 4, 25 | OSIF_SYSCALL_CONSOLE_SETCURSORPOS = 5, 26 | OSIF_SYSCALL_POP_PROCESS_EVENT = 6, 27 | OSIF_SYSCALL_PROCESS_GETPID = 7, 28 | OSIF_SYSCALL_TIMER_GET_TICKCOUNT = 8, 29 | OSIF_SYSCALL_PROCESS_GET_DATAMEM_START = 9, 30 | OSIF_SYSCALL_WINDOW_CREATE = 10, 31 | OSIF_SYSCALL_WINDOW_DESTORY = 11, 32 | OSIF_SYSCALL_WINDOW_GET_WINDOW_FB = 12, 33 | OSIF_SYSCALL_WINDOW_FLUSH_GRAPHICS = 13, 34 | OSIF_SYSCALL_GET_OS_ERROR = 14, 35 | OSIF_SYSCALL_GET_BOOTLOADED_FILE = 15, 36 | OSIF_SYSCALL_ABORT_PROCESS = 16, 37 | OSIF_SYSCALL_TEST = 17, 38 | } OSIF_SYSCALLS; 39 | 40 | typedef enum OSIF_ProcessEvents { 41 | OSIF_PROCESS_EVENT_NONE = 0, 42 | OSIF_PROCESS_EVENT_PROCCESS_YIELD_REQ = 1, 43 | OSIF_PROCESS_EVENT_PROCCESS_CHILD_KILLED = 2, 44 | OSIF_PROCESS_EVENTS_COUNT 45 | } OSIF_ProcessEvents; 46 | 47 | typedef struct OSIF_ProcessEvent { 48 | OSIF_ProcessEvents event; 49 | U64 data; 50 | } OSIF_ProcessEvent; 51 | 52 | typedef struct OSIF_BootLoadedFiles { 53 | void* startLocation; 54 | U16 length; 55 | } OSIF_BootLoadedFiles; 56 | -------------------------------------------------------------------------------- /include/cm/syscall.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------- 3 | * Megha Operating System V2 - App Library - OS Syscall calls 4 | * ------------------------------------------------------------------------------------------------- 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #if defined(LIBCM) || defined (UNITTEST) 11 | #include 12 | #else 13 | #include 14 | #endif 15 | 16 | S32 syscall (OSIF_SYSCALLS fn, U32 arg1, U32 arg2, U32 arg3, U32 arg4, U32 arg5); 17 | UINT cm_get_tick_period_us(); 18 | 19 | static inline UINT cm_tickcount_to_microsec(UINT tick) 20 | { 21 | return ((tick)*cm_get_tick_period_us()); 22 | } 23 | 24 | static inline void cm_putstr (char* text) 25 | { 26 | syscall (OSIF_SYSCALL_CONSOLE_WRITELN, (PTR)text, 0, 0, 0, 0); 27 | } 28 | 29 | static inline U32 cm_get_tickcount() 30 | { 31 | return (U32)syscall (OSIF_SYSCALL_TIMER_GET_TICKCOUNT, 0, 0, 0, 0, 0); 32 | } 33 | 34 | static inline Handle cm_window_create (const char* title) 35 | { 36 | return (Handle)syscall (OSIF_SYSCALL_WINDOW_CREATE, (PTR)title, 0, 0, 0, 0); 37 | } 38 | 39 | static inline U32 cm_window_destory (Handle h) 40 | { 41 | return (U32)syscall (OSIF_SYSCALL_WINDOW_DESTORY, (U32)h, 0, 0, 0, 0); 42 | } 43 | 44 | static inline void* cm_window_flush_graphics() 45 | { 46 | return (void*)syscall (OSIF_SYSCALL_WINDOW_FLUSH_GRAPHICS, 0, 0, 0, 0, 0); 47 | } 48 | 49 | static inline bool cm_window_getFB (Handle h, OSIF_WindowFrameBufferInfo* wfb) 50 | { 51 | return syscall (OSIF_SYSCALL_WINDOW_GET_WINDOW_FB, (U32)h, (PTR)wfb, 0, 0, 0); 52 | } 53 | -------------------------------------------------------------------------------- /include/cm/types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - App library - Potable Types 4 | * --------------------------------------------------------------------------- 5 | */ 6 | 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | 12 | typedef uint8_t U8; 13 | typedef uint16_t U16; 14 | typedef uint32_t U32; 15 | typedef int32_t S32; 16 | typedef uint64_t U64; 17 | typedef int64_t S64; 18 | typedef unsigned char UCHAR; 19 | typedef char CHAR; 20 | typedef size_t SIZE; 21 | 22 | #if defined(__i386__) || (defined(UNITTEST) && ARCH == x86) 23 | /* For any environment, UINT and INT will match the native width of registers. So when fast speed is 24 | * required, or variables are platform independent, use UINT or INT instead of U32 or S32.*/ 25 | 26 | typedef uintptr_t PTR; 27 | typedef S64 LLONG; 28 | typedef U64 ULLONG; 29 | typedef S32 INT; 30 | typedef S32 LONG; 31 | typedef U32 UINT; 32 | typedef U32 ULONG; 33 | #endif 34 | 35 | typedef INT Handle; 36 | -------------------------------------------------------------------------------- /include/compositor.h: -------------------------------------------------------------------------------- 1 | /* 2 | * -------------------------------------------------------------------------------------------------- 3 | * Megha Operating System V2 - Cross Platform Kernel - Window compositor header 4 | * -------------------------------------------------------------------------------------------------- 5 | */ 6 | 7 | #pragma once 8 | 9 | #ifndef GRAPHICS_MODE_ENABLED 10 | #error "Compositor only works in graphics mode" 11 | #endif 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | typedef struct Window { 18 | struct { 19 | UINT screen_x; 20 | UINT screen_y; 21 | } position; 22 | KGraphicsArea windowArea; 23 | KGraphicsArea workingArea; 24 | ListNode windowListNode; 25 | UINT processID; 26 | } Window; 27 | 28 | #define WINMAN_GRID_ROWS_MAX (2U) 29 | #define WINMAN_GRID_COLS_MAX (2U) 30 | #define WINMAN_GRID_CELL_COUNT (WINMAN_GRID_ROWS_MAX * WINMAN_GRID_COLS_MAX) 31 | 32 | #define WINMAN_GRID_CELL_WIDTH_PX() (g_kstate.gx_backfb.width_px / WINMAN_GRID_COLS_MAX) 33 | #define WINMAN_GRID_CELL_HEIGHT_PX() (g_kstate.gx_backfb.height_px / WINMAN_GRID_ROWS_MAX) 34 | 35 | // Window grid coordiate of rows and columns to screen coordinates 36 | #define WINMAN_GRID_CELL_Y(r) (WINMAN_GRID_CELL_HEIGHT_PX() * r) 37 | #define WINMAN_GRID_CELL_X(c) (WINMAN_GRID_CELL_WIDTH_PX() * c) 38 | 39 | // Window grid index to window grid coordiate of rows and columns 40 | #define WINMAN_GRID_CELL_ROW(wini) (wini / WINMAN_GRID_COLS_MAX) 41 | #define WINMAN_GRID_CELL_COL(wini) (wini % WINMAN_GRID_COLS_MAX) 42 | 43 | // Window grid coordiate of rows and columns to Window grid index 44 | #define WINMAN_WININDEX_FROM_CELL_POS(r, c) (r * WINMAN_GRID_COLS_MAX + c) 45 | 46 | void kcompose_init(); 47 | void kcompose_flush(); 48 | Window* kcompose_createWindow (const char* const title); 49 | bool kcompose_destroyWindow (Window* win); 50 | -------------------------------------------------------------------------------- /include/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - Cross Platform Kernel - Configuration 4 | * --------------------------------------------------------------------------- 5 | */ 6 | 7 | #ifndef MOS_CONFIG_H 8 | #define MOS_CONFIG_H 9 | 10 | #include 11 | 12 | #if defined(__i386__) || (defined(UNITTEST) && ARCH == x86) 13 | #include 14 | #endif 15 | 16 | #if defined(UNITTEST) 17 | #include 18 | #undef CONFIG_HANDLES_ARRAY_ITEM_COUNT 19 | #define CONFIG_HANDLES_ARRAY_ITEM_COUNT MOCK_THIS_MACRO_USING (config_handles_array_item_count) 20 | #endif 21 | 22 | #endif // MOS_CONFIG_H 23 | -------------------------------------------------------------------------------- /include/drivers/x86/pc/8042_ps2.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------- 3 | * Megha Operating System V2 - x86, PC Kernel - 8042 PS/2 Controller Header 4 | * ------------------------------------------------------------------------------------------------- 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #define PS2_DATA_PORT (0x60) 14 | #define PS2_CMD_PORT (0x64) 15 | #define PS2_SPEAKER_PORT (0x61) 16 | 17 | // PS2 Controller config bit positions 18 | #define PS2_CONFIG_FIRST_PORT_INTERRUPT_ENABLE (1 << 0U) 19 | #define PS2_CONFIG_SECOND_PORT_INTERRUPT_ENABLE (1 << 1U) 20 | #define PS2_CONFIG_FIRST_PORT_CLOCK_DISABLE (1 << 4U) 21 | #define PS2_CONFIG_SECOND_PORT_CLOCK_DISABLE (1 << 5U) 22 | #define PS2_CONFIG_FIRST_PORT_TRANSLATION_ENABLE (1 << 6U) 23 | 24 | // PS2 Controller commands 25 | #define PS2_CMD_DISABLE_SECOND_PORT (0xA7) 26 | #define PS2_CMD_ENABLE_SECOND_PORT (0xA8) 27 | #define PS2_CMD_DISABLE_FIRST_PORT (0xAD) 28 | #define PS2_CMD_ENABLE_FIRST_PORT (0xAE) 29 | #define PS2_CMD_TEST_CONTROLLER (0xAA) 30 | #define PS2_CMD_READ_CONFIGURATION_BYTE (0x20) 31 | #define PS2_CMD_WRITE_CONFIGURATION_BYTE (0x60) 32 | #define PS2_CMD_TEST_FIRST_PORT (0xAB) 33 | #define PS2_CMD_TEST_SECOND_PORT (0xA9) 34 | #define PS2_CMD_SEND_TO_SECOND_PORT (0xD4) 35 | 36 | // Common responses from PS2 controller 37 | #define PS2_RES_TEST_CONTROLLER_PASSED (0x55) 38 | #define PS2_RES_TEST_CONTROTEST_FAILED (0xFC) 39 | #define PS2_RES_TEST_PORT_PASSED (0x00) 40 | 41 | // Common PS2 device commands 42 | #define PS2_DEV_CMD_RESET (0xFF) 43 | #define PS2_DEV_CMD_SET_TO_DEFAULT (0xF6) 44 | #define PS2_DEV_CMD_IDENTIFY (0xF2) 45 | #define PS2_DEV_CMD_DISABLE_SCANNING (0xF5) 46 | #define PS2_DEV_CMD_ENABLE_SCANNING (0xF4) 47 | 48 | // Common responses from PS2 devices 49 | #define PS2_DEV_RES_ACK (0xFA) 50 | #define PS2_DEV_RES_RESEND (0xFE) 51 | 52 | #define PS2_FIRST_DEVICE (0U) 53 | #define PS2_SECOND_DEVICE (1U) 54 | 55 | bool ps2_init(); 56 | bool ps2_wait_read (UINT ioport, U8* data); 57 | bool ps2_wait_write (UINT ioport, U8 data); 58 | void ps2_write_device_data_no_ack (UINT device_id, U8 data); 59 | bool ps2_write_device_data_wait_ack (UINT device_id, U8 cmd); 60 | bool ps2_configuration (U8 enabled, U8 disabled, U8* original_config); 61 | INT ps2_identify_device (UINT device_id); 62 | 63 | static inline U8 ps2_no_wait_read (UINT ioport) 64 | { 65 | U8 data; 66 | inb (ioport, data); 67 | return data; 68 | } 69 | -------------------------------------------------------------------------------- /include/drivers/x86/pc/8254_pit.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------- 3 | * Megha Operating System V2 - x86, PC Kernel - 8254 PIT dirver headers 4 | * ------------------------------------------------------------------------------------------------- 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #define PIT_BASE_CLOCK_FREQ_HZ 1193182 14 | 15 | typedef enum PITCounterModes { 16 | PIT_COUNTER_MODE_2 = 2, 17 | PIT_COUNTER_MODE_3 = 3 18 | } PITCounterModes; 19 | 20 | typedef enum X86_PITCounters { 21 | PIT_COUNTER_0 = 0, 22 | PIT_COUNTER_2 = 2 23 | } PITCounters; 24 | 25 | void pit_get_counter (PITCounters cntr, U8* status, U16* value); 26 | void pit_set_counter (PITCounters cntr, PITCounterModes mode, U16 value); 27 | void pit_get_interrupt_counter (PITCounterModes* mode, U16* value); 28 | void pit_stop_start_counter (PITCounters cntr, bool turnOn); 29 | 30 | static inline void pit_set_interrupt_counter (PITCounterModes mode, UINT freq) 31 | { 32 | k_assert (freq >= MIN_INTERRUPT_CLOCK_FREQ_HZ, "Freq too small"); 33 | pit_set_counter (PIT_COUNTER_0, mode, (U16)(PIT_BASE_CLOCK_FREQ_HZ / freq)); 34 | } 35 | 36 | static inline void pit_set_speaker_counter (UINT freq) 37 | { 38 | k_assert (freq >= MIN_INTERRUPT_CLOCK_FREQ_HZ, "Freq too small"); 39 | pit_set_counter (PIT_COUNTER_2, PIT_COUNTER_MODE_3, (U16)(PIT_BASE_CLOCK_FREQ_HZ / freq)); 40 | } 41 | -------------------------------------------------------------------------------- /include/drivers/x86/pc/8259_pic.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------- 3 | * Megha Operating System V2 - x86, PC Kernel - 8259 PIC dirver headers 4 | * ------------------------------------------------------------------------------------------------- 5 | */ 6 | 7 | #pragma once 8 | #include 9 | 10 | typedef enum PC_IRQ { 11 | PIC_IRQ_TIMER = 0, 12 | PIC_IRQ_KEYBOARD = 1, 13 | PIC_IRQ_SLAVE_PIC = 2, 14 | PIC_IRQ_PS2_MOUSE = 12, 15 | PIC_IRQ_7 = 7, 16 | PIC_IRQ_15 = 15, 17 | } PIC_IRQ; 18 | 19 | void pic_init (U8 master_vector_start, U8 slave_vector_start); 20 | void pic_enable_disable_irq (PIC_IRQ irq, bool enable); 21 | void pic_read_IRR_ISR (bool readISR, UINT *master, UINT *slave); 22 | void pic_send_eoi (PIC_IRQ irq); 23 | -------------------------------------------------------------------------------- /include/drivers/x86/pc/pcspeaker.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------- 3 | * Megha Operating System V2 - x86, PC Kernel - PC Speaker Header 4 | * ------------------------------------------------------------------------------------------------- 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | void pcspeaker_set_freq (UINT freq); 12 | void pcspeaker_turnon(); 13 | void pcspeaker_turnoff(); 14 | -------------------------------------------------------------------------------- /include/drivers/x86/pc/ps2_devices.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------- 3 | * Megha Operating System V2 - x86, PC Kernel - PS/2 Devices 4 | * ------------------------------------------------------------------------------------------------- 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #define PS2_MOUSE_CMD_GET_ID (0xF2) 12 | #define PS2_MOUSE_CMD_STATUS_REQ (0xE9) 13 | #define PS2_MOUSE_CMD_SET_SAMPLE_RATE (0xF3) 14 | #define PS2_MOUSE_CMD_GET_MOUSE_PACKET (0xEB) 15 | #define PS2_MOUSE_CMD_ENTER_REMOTE_MODE (0xF0) 16 | #define PS2_MOUSE_CMD_ENTER_STREAM_MODE (0xEA) 17 | 18 | #define PS2_MOUSE_PACKET_BYTE0_LEFT_BTN_MASK (1 << 0) 19 | #define PS2_MOUSE_PACKET_BYTE0_RIGHT_BTN_MASK (1 << 1) 20 | #define PS2_MOUSE_PACKET_BYTE0_MID_BTN_MASK (1 << 2) 21 | #define PS2_MOUSE_PACKET_BYTE0_X_SIGN_BTN_MASK (1 << 4) 22 | #define PS2_MOUSE_PACKET_BYTE0_Y_SIGN_BTN_MASK (1 << 5) 23 | #define PS2_MOUSE_PACKET_BYTE0_X_OVERFLOW_BTN_MASK (1 << 6) 24 | #define PS2_MOUSE_PACKET_BYTE0_Y_OVERFLOW_BTN_MASK (1 << 7) 25 | 26 | #define PS2_MOUSE_STATE_BYTE_0_RIGHT_BTN_MASK (1 << 0) 27 | #define PS2_MOUSE_STATE_BYTE_0_MID_BTN_MASK (1 << 1) 28 | #define PS2_MOUSE_STATE_BYTE_0_LEFT_BTN_MASK (1 << 2) 29 | #define PS2_MOUSE_STATE_BYTE_0_SCALE_2x1_ENABLED_MASK (1 << 4) 30 | #define PS2_MOUSE_STATE_BYTE_0_DATA_REPORTING_ENABLED_MASK (1 << 5) 31 | #define PS2_MOUSE_STATE_BYTE_0_REMOTE_MODE_ENABLED (1 << 6) 32 | 33 | typedef struct MousePositionData { 34 | INT x; 35 | INT y; 36 | bool left_button; 37 | bool right_button; 38 | bool middle_button; 39 | } MousePositionData; 40 | 41 | bool ps2_mouse_init(); 42 | bool ps2_kb_init(); 43 | MousePositionData ps2_mouse_get_packet(); 44 | -------------------------------------------------------------------------------- /include/guicolours.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------------------- 3 | * Megha Operating System V2 - Cross Platform Kernel - GUI colors 4 | * --------------------------------------------------------------------------------------- 5 | */ 6 | 7 | #pragma once 8 | 9 | #if CONFIG_GXMODE_BITSPERPIXEL == 8 10 | #define COLOR_WHITE (15) 11 | #define WINDOW_TITLE_BAR_BG_COLOR (126) 12 | #define WINDOW_TITLE_BAR_FG_COLOR (15) 13 | #define WINDOW_BG_COLOR (29) 14 | #define WINDOW_BORDER_COLOR1 (26) 15 | #define WINDOW_BORDER_COLOR2 (30) 16 | #define DESKTOP_BG_COLOR (123) 17 | #define MOUSE_BG_COLOR (18) 18 | #define MOUSE_FG_COLOR (15) 19 | #define COLOR_BG_BSOD (106) 20 | #elif CONFIG_GXMODE_BITSPERPIXEL == 32 || CONFIG_GXMODE_BITSPERPIXEL == 24 21 | #define COLOR_WHITE (0xFFFFFF) 22 | #define WINDOW_TITLE_BAR_BG_COLOR (0x003971) 23 | #define WINDOW_TITLE_BAR_FG_COLOR (0xFFFFFF) 24 | #define WINDOW_BG_COLOR (0xDFDFDF) 25 | #define WINDOW_BORDER_COLOR1 (0xAAAAAA) 26 | #define WINDOW_BORDER_COLOR2 (0xF2F2F2) 27 | #define DESKTOP_BG_COLOR (0x007155) 28 | #define MOUSE_BG_COLOR (0x202020) 29 | #define MOUSE_FG_COLOR (0xFFFFFF) 30 | #define COLOR_BG_BSOD (0x390071) 31 | #endif 32 | -------------------------------------------------------------------------------- /include/handle.h: -------------------------------------------------------------------------------- 1 | /* 2 | * -------------------------------------------------------------------------------------------------- 3 | * Megha Operating System V2 - Cross Platform Kernel - Kernel Object Handle management headers 4 | * 5 | * Handles identify objects in the kernel and can safely be passed to applications as well. 6 | * -------------------------------------------------------------------------------------------------- 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | 14 | #define INVALID_HANDLE KERNEL_EXIT_FAILURE 15 | 16 | void khandle_init(); 17 | Handle khandle_createHandle (void* obj); 18 | bool khandle_freeHandle (Handle h); 19 | void* khandle_getObject (Handle h); 20 | -------------------------------------------------------------------------------- /include/intrusive_list.h: -------------------------------------------------------------------------------- 1 | #ifndef INTRUSIVE_LIST_H 2 | #define INTRUSIVE_LIST_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | typedef struct ListNode 9 | { 10 | struct ListNode* next; 11 | struct ListNode* prev; 12 | } ListNode; 13 | 14 | static inline void list_init (ListNode* node) 15 | { 16 | node->next = node; 17 | node->prev = node; 18 | } 19 | 20 | static inline bool list_is_empty(ListNode *head) 21 | { 22 | return (head->next == head && head->prev == head); 23 | } 24 | 25 | static inline void list_add_before (ListNode* node, ListNode* item) 26 | { 27 | item->next = node; 28 | item->prev = node->prev; 29 | node->prev->next = item; 30 | node->prev = item; 31 | } 32 | 33 | static inline void list_add_after (ListNode* node, ListNode* item) 34 | { 35 | item->prev = node; 36 | item->next = node->next; 37 | node->next->prev = item; 38 | node->next = item; 39 | } 40 | 41 | static inline void list_remove (ListNode* item) 42 | { 43 | item->prev->next = item->next; 44 | item->next->prev = item->prev; 45 | item->next = NULL; 46 | item->prev = NULL; 47 | } 48 | 49 | #define LIST_ITEM(node, type, member) (type*)((uintptr_t)node - offsetof (type, member)) 50 | 51 | #define list_for_each(head, node) \ 52 | for ((node) = (head)->next; (node) != (head); (node) = (node)->next) 53 | 54 | #endif // INTRUSIVE_LIST_H 55 | -------------------------------------------------------------------------------- /include/intrusive_queue.h: -------------------------------------------------------------------------------- 1 | #ifndef INTRU_QUEUE_H 2 | #define INTRU_QUEUE_H 3 | #include 4 | 5 | static inline void enqueue (ListNode* head, ListNode* item) 6 | { 7 | list_add_before (head, item); 8 | } 9 | 10 | static inline ListNode* dequeue (ListNode* head) 11 | { 12 | if (head->next == head) { 13 | return NULL; 14 | } 15 | ListNode* node = head->next; 16 | list_remove (head->next); 17 | return node; 18 | } 19 | 20 | static inline void queue_remove (ListNode* node) 21 | { 22 | list_remove (node); 23 | } 24 | 25 | static inline void enqueue_front (ListNode* head, ListNode* item) 26 | { 27 | list_add_after (head, item); 28 | } 29 | 30 | static inline ListNode* dequeue_back (ListNode* head) 31 | { 32 | if (head->prev == head) { 33 | return NULL; 34 | } 35 | 36 | ListNode* node = head->prev; 37 | list_remove (head->prev); 38 | return node; 39 | } 40 | 41 | #define queue_for_each(head, node) \ 42 | for ((node) = (head)->next; (node) != (head); (node) = (node)->next) 43 | 44 | #define queue_for_each_backward(head, node) \ 45 | for ((node) = (head)->prev; (node) != (head); (node) = (node)->prev) 46 | 47 | #endif // INTRU_QUEUE_H 48 | -------------------------------------------------------------------------------- /include/kassert.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - Cross Platform Kernel - k_assert () 4 | * 5 | * Note: 6 | * Remember that these header files are for building OS and its utilitites, it 7 | * is not a SDK. 8 | * --------------------------------------------------------------------------- 9 | * 10 | * Dated: 5st November 2020 11 | */ 12 | #ifndef KASSERT_H 13 | #define KASSERT_H 14 | 15 | #include 16 | 17 | #if defined(DEBUG) 18 | #include 19 | /* If assertion `t' is false, call k_panic () and halts. 20 | * Displays message `e' in the panic message. 21 | */ 22 | #define k_assert(t, e) \ 23 | do { \ 24 | if (!(t)) \ 25 | k_panic ("Assertion failed: %s\nAt %s:%u", e, __FILE__, __LINE__); \ 26 | } while (0) 27 | 28 | /* If expression `t' is false, compiler will generate an error. 29 | * 30 | * This works because an array dimension cannot be negative, which is what the macro expands to 31 | * when t == false. 32 | */ 33 | #define CALL_COMPILER_CHECK2_NDU(m, t) \ 34 | __attribute__ ((unused)) typedef char static_assert_##m[(t) ? 1 : -1] 35 | 36 | #define CALL_COMPILER_CHECK_NDU(m, t) CALL_COMPILER_CHECK2_NDU (m, t) 37 | 38 | #define k_staticAssert(t) CALL_COMPILER_CHECK_NDU (__LINE__, t) 39 | 40 | #else 41 | #define k_assert(t, e) (void)0 42 | #define k_staticAssert(t) (void)0 43 | #endif // DEBUG 44 | 45 | #endif // KASSERT_H 46 | -------------------------------------------------------------------------------- /include/kcmlib.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - App library Kernel Header - Private type/function declarations 4 | * --------------------------------------------------------------------------- 5 | * Types and function declarations defined here are private to the CM library and should not be 6 | * exposed to the applications. 7 | */ 8 | #pragma once 9 | 10 | #include 11 | #include 12 | 13 | typedef struct CM_MallocHeader 14 | { 15 | size_t netNodeSize; /// Size of a region together with the header size. 16 | bool isAllocated; /// Is the region allocated or free. 17 | ListNode adjnode; /// A node in the Adjacent list. 18 | ListNode freenode; /// A node in the Free list. 19 | ListNode allocnode; /// A node in the Allocation list 20 | } CM_MallocHeader; 21 | 22 | #if defined(UNITTEST) 23 | #define CM_MALLOC_MEM_SIZE_BYTES MOCK_THIS_MACRO_USING (cm_arch_mem_len_bytes_malloc) 24 | #else 25 | #define CM_MALLOC_MEM_SIZE_BYTES (ARCH_MEM_LEN_BYTES_PROCESS_DATA / 2) 26 | #endif 27 | 28 | extern uint32_t cm_error_num; 29 | 30 | /* Can be used to store an error code and return from a function */ 31 | #define CM_RETURN_ERROR(errno, rval) \ 32 | do { \ 33 | CM_DBG_ERROR ("Error %x.", errno); \ 34 | cm_error_num = errno; \ 35 | return rval; \ 36 | } while (0) 37 | -------------------------------------------------------------------------------- /include/kdebug.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - Cross Platform Kernel - Printing to debug console. 4 | * --------------------------------------------------------------------------- 5 | */ 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | typedef enum KernelDebugLogType { 13 | KDEBUG_LOG_TYPE_INFO, 14 | KDEBUG_LOG_TYPE_FUNC, 15 | KDEBUG_LOG_TYPE_ERROR, 16 | KDEBUG_LOG_TYPE_WARN, 17 | } KernelDebugLogType; 18 | 19 | /* Prints formatted string to 0xE9 port and can optionally print to vga 20 | * buffer. 21 | */ 22 | 23 | #if defined(PORT_E9_ENABLED) 24 | void kdebug_log_ndu (KernelDebugLogType type, const char* func, UINT line, char* fmt, ...); 25 | 26 | #define INFO(...) kdebug_log_ndu (KDEBUG_LOG_TYPE_INFO, __func__, __LINE__, __VA_ARGS__) 27 | 28 | #define FUNC_ENTRY(...) \ 29 | kdebug_log_ndu (KDEBUG_LOG_TYPE_FUNC, __func__, __LINE__, "" __VA_ARGS__) 30 | #define ERROR(...) kdebug_log_ndu (KDEBUG_LOG_TYPE_ERROR, __func__, __LINE__, __VA_ARGS__) 31 | #define WARN(...) kdebug_log_ndu (KDEBUG_LOG_TYPE_WARN, __func__, __LINE__, __VA_ARGS__) 32 | 33 | #else 34 | #define INFO(...) (void)0 35 | #define FUNC_ENTRY(...) (void)0 36 | #define ERROR(...) (void)0 37 | #define WARN(...) (void)0 38 | #endif 39 | 40 | #if defined(DEBUG) 41 | #if !defined(GRAPHICS_MODE_ENABLED) 42 | typedef enum DisplayControls { 43 | DISP_GETCOORDS, 44 | DISP_SETCOORDS, 45 | DISP_COORDS_MAX, 46 | DISP_SETATTR, 47 | DISP_GETATTR 48 | } DisplayControls; 49 | 50 | INT kdisp_ioctl (INT request, ...); 51 | void kdisp_scrollDown(); 52 | void kdisp_init(); 53 | void kdisp_putc (CHAR c); 54 | #endif 55 | INT kearly_printf (const CHAR* fmt, ...); 56 | #else 57 | #define kearly_printf(...) (void)0 58 | #endif // DEBUG 59 | 60 | INT kearly_snprintf (CHAR* dest, size_t size, const CHAR* fmt, ...); 61 | INT kearly_vsnprintf (CHAR* dest, size_t size, const CHAR* fmt, va_list l); 62 | 63 | /*************************************************************************************************** 64 | * Moves to the next line and prints formatted input on the screen. 65 | * 66 | * @return For description for `kearly_vsnprintf`. 67 | **************************************************************************************************/ 68 | #define kearly_println(...) kearly_printf ("\n" __VA_ARGS__) 69 | 70 | /*************************************************************************************************** 71 | * Magic break point used by bochs emulator 72 | * 73 | * @return Nothing 74 | **************************************************************************************************/ 75 | #define kbochs_breakpoint() __asm__ volatile("xchg bx, bx") 76 | 77 | // TODO: Should all bugs be fatal? 78 | #define BUG() ERROR ("\n\nBUG: %s:%u", __FILE__, __LINE__); 79 | #define FATAL_BUG() k_panic ("\n\nBUG: %s:%u", __FILE__, __LINE__); 80 | 81 | #define WARN_ON(t, ...) \ 82 | do { \ 83 | if (!(t)) { \ 84 | WARN ("\n\nWARN ON: (" #t ") failed\n" __VA_ARGS__); \ 85 | } \ 86 | } while (0) 87 | 88 | #define BUG_ON(t, ...) \ 89 | do { \ 90 | if (!(t)) { \ 91 | BUG(); \ 92 | } \ 93 | } while (0) 94 | -------------------------------------------------------------------------------- /include/kernel.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - x86 Platform Kernel - Kernel Management 4 | * --------------------------------------------------------------------------- 5 | */ 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #ifdef GRAPHICS_MODE_ENABLED 13 | #include 14 | #endif // GRAPHICS_MODE_ENABLED 15 | 16 | typedef struct KernelStateInfo { 17 | enum { 18 | KERNEL_PHASE_STATE_BOOT_COMPLETE = 0, 19 | #if defined(DEBUG) && !defined(GRAPHICS_MODE_ENABLED) 20 | KERNEL_PHASE_STATE_TEXTDISP_READY, 21 | #endif 22 | KERNEL_PHASE_STATE_PMM_READY, 23 | KERNEL_PHASE_STATE_SALLOC_READY, 24 | KERNEL_PHASE_STATE_VMM_READY, 25 | KERNEL_PHASE_STATE_KMALLOC_READY, 26 | #ifdef GRAPHICS_MODE_ENABLED 27 | KERNEL_PHASE_STATE_GRAPHICS_READY, 28 | #endif 29 | KERNEL_PHASE_STATE_KERNEL_READY 30 | } phase; // Phase in which the Kernel is in currently. 31 | UINT errorNumber; // Code for last error. 32 | VMemoryManager* context; 33 | U32 tick_count; // incremented every CONFIG_TICK_PERIOD_MICROSEC micro seconds. 34 | #ifdef GRAPHICS_MODE_ENABLED 35 | // Kernel Graphics back buffer 36 | KGraphicsArea gx_backfb; 37 | // HW Video Framebuffer 38 | KGraphicsArea gx_hwfb; 39 | #endif 40 | } KernelStateInfo; 41 | 42 | extern volatile KernelStateInfo g_kstate; 43 | 44 | typedef enum KernelEvents { 45 | KERNEL_EVENT_NONE = 0, 46 | KERNEL_EVENT_PROCCESS_YIELD_REQ = 1, 47 | KERNEL_EVENT_PROCCESS_CHILD_KILLED = 2 48 | } KernelEvents; 49 | 50 | #define KERNEL_PHASE_SET(p) \ 51 | do { \ 52 | k_assert (p == 0 || (g_kstate.phase + 1) == p, "Current state is unsuitable for " #p); \ 53 | g_kstate.phase = p; \ 54 | } while (0) 55 | 56 | #define KERNEL_PHASE_CHECK(p) (g_kstate.phase >= (p)) 57 | 58 | #define KERNEL_PHASE_VALIDATE(p) k_assert (g_kstate.phase >= p, "Current state is not " #p); 59 | 60 | #define KERNEL_MICRODEC_TO_TICK_COUNT(us) ((U32)((us) / CONFIG_TICK_PERIOD_MICROSEC)) 61 | #define KERNEL_TICK_COUNT_TO_MICROSEC(tick) ((U64)(tick) * (U64)CONFIG_TICK_PERIOD_MICROSEC) 62 | 63 | void k_delay (UINT ms); 64 | void keventmanager_invoke(); 65 | -------------------------------------------------------------------------------- /include/kerror.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - Cross Platform Kernel - errno and error reporting 4 | * routines. 5 | * --------------------------------------------------------------------------- 6 | * 7 | * Dated: 9th November 2020 8 | */ 9 | 10 | #ifndef ERRORNO_H 11 | #define ERRORNO_H 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | /* Error codes that can be set inside the kernel.*/ 20 | typedef enum KernelErrorCodes { 21 | ERR_NONE = 0, // No error 22 | ERR_UNKNOWN = 1, // Unknown error 23 | ERR_INVALID_RANGE = 2, // Outside of valid range 24 | ERR_OVERFLOW = 3, // Overflow 25 | ERR_OUT_OF_MEM = 4, // Out of physical & virtual pages 26 | ERR_DOUBLE_FREE = 5, // Double free 27 | ERR_DOUBLE_ALLOC = 6, // Double allocation 28 | ERR_WRONG_ALIGNMENT = 7, // Byte alignment is wrong 29 | ERR_OUTSIDE_ADDRESSABLE_RANGE = 8, // Byte is outside addressable range. 30 | ERR_INVALID_ARGUMENT = 9, // Invalid argument.", 31 | ERR_PAGE_WRONG_STATE = 10, // Page table/directory is in wrong state 32 | ERR_SCHEDULER_QUEUE_FULL = 11, // No space for new process in process table 33 | ERR_QUEUE_EMPTY = 12, // Queue empty. Dequeue failed. 34 | ERR_VMM_NOT_ALLOCATED = 13, // Virutal address space is not allocated 35 | ERR_VMM_OVERLAPING_VAS = 14, // New Virtual address space is overlaps another one 36 | ERR_VMM_NULL_PAGE_ACCESS = 15, // Trying to commit a NULL page. 37 | ERR_PROC_EXIT_NOT_ALLOWED = 16, // Process exit not allowed (its the only one left) 38 | ERR_DEVICE_INIT_FAILED = 17, // Device initialization failed 39 | ERR_DEVICE_NOT_READY = 18, // Device is not ready for access 40 | ERR_TIMEOUT = 19, // Operation timed out. 41 | ERR_INVALID_HANDLE = 20, // Object handle is either outside range/no object is there 42 | ERR_INVALID_SYSCALL = 21, // Invalid system call number invoked 43 | ERR_PROC_CREATE_NOT_ALLOWED = 22, // Process creation not allowed. 44 | } KernelErrorCodes; 45 | 46 | // Use this with RETURN_ERROR when you do not want to set a new error number but pass through what 47 | // is already set. 48 | #define ERROR_PASSTHROUGH g_kstate.errorNumber 49 | 50 | #define KERNEL_EXIT_SUCCESS 0 51 | #define KERNEL_EXIT_FAILURE -1 52 | 53 | /* Can be used to store an error code and return from a function */ 54 | #define RETURN_ERROR(errno, rval) \ 55 | do { \ 56 | ERROR ("Error %x.", errno); \ 57 | g_kstate.errorNumber = errno; \ 58 | return rval; \ 59 | } while (0) 60 | 61 | /* Displays error description if error code != 0 */ 62 | #define k_assertOnError() k_assert (g_kstate.errorNumber == ERR_NONE, "Assert on error") 63 | #define k_panicOnError() \ 64 | do { \ 65 | if (g_kstate.errorNumber != ERR_NONE) { \ 66 | k_panic ("Panic on error.Error %x\n", g_kstate.errorNumber); \ 67 | } \ 68 | } while (0) 69 | 70 | #endif // ERRORNO_H 71 | -------------------------------------------------------------------------------- /include/kgraphics.h: -------------------------------------------------------------------------------- 1 | /* 2 | * -------------------------------------------------------------------------------------------------- 3 | * Megha Operating System V2 - Cross Platform Kernel - Kernel graphics header 4 | * -------------------------------------------------------------------------------------------------- 5 | */ 6 | 7 | #pragma once 8 | 9 | #ifndef GRAPHICS_MODE_ENABLED 10 | #error "Gui demo only works in graphics mode" 11 | #endif 12 | 13 | #include 14 | 15 | // This is a arch independent color type large enough for all the color modes supported. 16 | typedef U32 Color; 17 | 18 | typedef U8 IndexColor8Bit; 19 | 20 | // RGB is BGR in memory and that is the order in which the fields apprear. This simplifies when 21 | // assignning/copying color values from memory (like in graphics_rect, graphics_drawfont etc). 22 | // Note: PPM and RAW image formats etc, which store RGB however store color in R,G,B and not B,G,R. 23 | typedef struct RGBColor24Bits { 24 | U8 blue; 25 | U8 green; 26 | U8 red; 27 | } __attribute__ ((packed)) RGBColor24Bits; 28 | 29 | // ARGB is BGRA in memory and that is the order in which the fields apprear. This simplifies when 30 | // assignning/copying color values from memory (like in graphics_rect, graphics_drawfont etc). 31 | // Note: PPM and RAW image formats etc, which store RGB however store color in R,G,B and not B,G,R. 32 | typedef struct RGBColor32Bits { 33 | U8 blue; 34 | U8 green; 35 | U8 red; 36 | U8 alpha; 37 | } __attribute__ ((packed)) RGBColor32Bits; 38 | 39 | typedef struct KGraphicsArea { 40 | UINT width_px; 41 | UINT height_px; 42 | UINT bytesPerPixel; 43 | UINT bytesPerRow; 44 | U8* buffer; 45 | SIZE bufferSizeBytes; 46 | } KGraphicsArea; 47 | 48 | #if CONFIG_GXMODE_BITSPERPIXEL == 8 49 | typedef IndexColor8Bit GxColor; 50 | #elif CONFIG_GXMODE_BITSPERPIXEL == 24 51 | typedef RGBColor24Bits GxColor; 52 | #elif CONFIG_GXMODE_BITSPERPIXEL == 32 53 | typedef RGBColor32Bits GxColor; 54 | #endif 55 | 56 | void kgraphics_rect (const KGraphicsArea* g, UINT x, UINT y, UINT w, UINT h, Color color); 57 | void kgraphics_image_raw (const KGraphicsArea* g, UINT x, UINT y, UINT w, UINT h, UINT bytesPerPixel, 58 | U8* bytes); 59 | void kgraphics_drawfont (const KGraphicsArea* g, UINT x, UINT y, UCHAR a, Color fg, Color bg); 60 | void kgraphics_putpixel (const KGraphicsArea* g, UINT x, UINT y, Color color); 61 | void kgraphis_flush(); 62 | void kgraphics_blit (const KGraphicsArea* destg, UINT x, UINT y, const KGraphicsArea* srcg); 63 | bool kgraphics_init(); 64 | void kgraphics_drawstring (const KGraphicsArea* g, UINT x, UINT y, const char* text, Color fg, 65 | Color bg); 66 | 67 | static inline void kgraphics_hline (const KGraphicsArea* g, UINT x, UINT y, UINT w, UINT th, 68 | Color color) 69 | { 70 | kgraphics_rect (g, x, y, w, th, color); 71 | } 72 | 73 | static inline void kgraphics_vline (const KGraphicsArea* g, UINT x, UINT y, UINT h, UINT th, 74 | Color color) 75 | { 76 | kgraphics_rect (g, x, y, th, h, color); 77 | } 78 | 79 | /* Draws rectangle with borders on the inside of a rectangle */ 80 | static inline void kgraphics_inborder (const KGraphicsArea* g, UINT x, UINT y, UINT w, UINT h, 81 | UINT th, Color color) 82 | { 83 | kgraphics_hline (g, x, y, w, th, color); // Top 84 | kgraphics_vline (g, x, y, h, th, color); // Left 85 | kgraphics_vline (g, (x + w - th), y, h, th, color); // Right 86 | kgraphics_hline (g, x, (y + h - th), w, th, color); // Bottom 87 | } 88 | -------------------------------------------------------------------------------- /include/kstdlib.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - Cross Platform Kernel - Common stdlib functions 4 | * --------------------------------------------------------------------------- 5 | */ 6 | 7 | #ifndef MEM_H 8 | #define MEM_H 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | /* Copies n bytes from src to dest. Returns dest */ 15 | void* k_memcpy (void* dest, const void* src, size_t n); 16 | 17 | /* Fills memory with constant byte */ 18 | void* k_memset (void* s, U8 c, size_t n); 19 | 20 | /* Copies n bytes from src to physical dest memory.*/ 21 | void k_memcpyToPhyMem (Physical dest, PTR src, UINT destOffset, UINT srcOffset, SIZE n); 22 | 23 | /* Fills memory with a multi byte pattern*/ 24 | void* k_memset_pat4 (void* s, U32 p, SIZE szp, SIZE n); 25 | 26 | /* Copies at most 'n' characters from one string to another.*/ 27 | char* k_strncpy (char* d, const char* s, SIZE n); 28 | 29 | /* Gets lenght of a NULL terminated string.*/ 30 | UINT k_strlen (const char* s); 31 | 32 | /* Compares n bytes from src to dest. Output is true if they match exactly. */ 33 | bool k_memcmp (const void* const dest, const void* const src, size_t n); 34 | #endif // MEM_H 35 | -------------------------------------------------------------------------------- /include/memloc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - Cross Platform Kernel - Static Memory Locations 4 | * --------------------------------------------------------------------------- 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #if defined(UNITTEST) 12 | #include 13 | #define ARCH_MEM_START_KERNEL_PAB MOCK_THIS_MACRO_USING (arch_mem_start_kernel_pab) 14 | #define ARCH_MEM_START_SALLOC MOCK_THIS_MACRO_USING (arch_mem_start_salloc) 15 | #define ARCH_MEM_LEN_BYTES_SALLOC MOCK_THIS_MACRO_USING (arch_mem_len_bytes_salloc) 16 | #define ARCH_MEM_LEN_BYTES_KMALLOC MOCK_THIS_MACRO_USING (arch_mem_len_bytes_kmalloc) 17 | #else 18 | #if defined(__i386__) || (defined(UNITTEST) && ARCH == x86) 19 | #include 20 | 21 | #define ARCH_MEM_START_SALLOC X86_MEM_START_SALLOC 22 | #define ARCH_MEM_LEN_BYTES_SALLOC X86_MEM_LEN_BYTES_SALLOC 23 | 24 | #define ARCH_MEM_LEN_BYTES_KMALLOC X86_MEM_LEN_BYTES_KMALLOC 25 | 26 | #define ARCH_MEM_START_KERNEL_PAB X86_MEM_START_KERNEL_PAB 27 | #define ARCH_MEM_LEN_BYTES_KERNEL_PAB X86_MEM_LEN_BYTES_KERNEL_PAB 28 | 29 | #define ARCH_MEM_START_PROCESS_MEMORY X86_MEM_START_PROCESS_MEMORY 30 | #define ARCH_MEM_END_PROCESS_MEMORY X86_MEM_END_PROCESS_MEMORY 31 | #define ARCH_MEM_START_PROCESS_TEXT X86_MEM_START_PROCESS_TEXT 32 | #define ARCH_MEM_LEN_BYTES_PROCESS_STACK X86_MEM_LEN_BYTES_PROCESS_STACK 33 | #define ARCH_MEM_LEN_BYTES_PROCESS_DATA X86_MEM_LEN_BYTES_PROCESS_DATA 34 | #endif 35 | #endif 36 | -------------------------------------------------------------------------------- /include/memmanage.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------------------- 3 | * Megha Operating System V2 - Cross Platform Kernel - Kernel memory management functions 4 | * --------------------------------------------------------------------------------------- 5 | */ 6 | 7 | #ifndef MEMMANAGE_H 8 | #define MEMMANAGE_H 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #define SALLOC_GRANUALITY (8 * Byte) 15 | #define KMALLOC_GRANULARITY (16 * bytes) 16 | 17 | typedef struct KMallocHeader 18 | { 19 | size_t netNodeSize; /// Size of a region together with the header size. 20 | bool isAllocated; /// Is the region allocated or free. 21 | ListNode adjnode; /// A node in the Adjacent list. 22 | ListNode freenode; /// A node in the Free list. 23 | ListNode allocnode; /// A node in the Allocation list 24 | } KMallocHeader; 25 | 26 | void ksalloc_init(); 27 | void* ksalloc (UINT bytes); 28 | void* kscalloc (UINT bytes); 29 | SIZE ksalloc_getUsedMemory(); 30 | 31 | void* kmalloc (size_t bytes); 32 | void* kmallocz (size_t bytes); 33 | bool kfree (void* addr); 34 | void kmalloc_init(); 35 | SIZE kmalloc_getUsedMemory(); 36 | 37 | #endif // MEMMANAGE_H 38 | -------------------------------------------------------------------------------- /include/mock/cm/cm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | DECLARE_FUNC (void*, cm_memset, void*, U8, size_t); 7 | DECLARE_FUNC (char*, cm_strncpy, char*, const char*, size_t); 8 | DECLARE_FUNC (S32, syscall, U32, U32, U32, U32, U32, U32); 9 | 10 | void resetCMFake(); 11 | -------------------------------------------------------------------------------- /include/mock/kernel/bitmap.h: -------------------------------------------------------------------------------- 1 | #ifndef BITMAP_FAKE_H 2 | #define BITMAP_FAKE_H 3 | 4 | #include 5 | #include 6 | 7 | DECLARE_FUNC(BitmapState, bitmap_get, Bitmap *, UINT); 8 | DECLARE_FUNC(bool, bitmap_setContinous, Bitmap *, UINT, UINT, BitmapState); 9 | DECLARE_FUNC(INT, bitmap_findContinous, Bitmap *, BitmapState, UINT); 10 | DECLARE_FUNC(bool, bitmap_findContinousAt, Bitmap *, BitmapState, UINT, UINT); 11 | 12 | void resetBitmapFake(); 13 | #endif // BITMAP_FAKE_H 14 | 15 | -------------------------------------------------------------------------------- /include/mock/kernel/kstdlib.h: -------------------------------------------------------------------------------- 1 | #ifndef MEM_FAKE_H 2 | #define MEM_FAKE_H 3 | 4 | #include 5 | #include 6 | 7 | DECLARE_FUNC(void *, k_memcpy, void *, const void *, size_t); 8 | DECLARE_FUNC(void *, k_memset, void *, U8, size_t); 9 | 10 | void resetStdLibFake(); 11 | #endif //MEM_FAKE_H 12 | -------------------------------------------------------------------------------- /include/mock/kernel/paging.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | DECLARE_FUNC (void *, kpg_temporaryMap, Physical); 7 | DECLARE_FUNC_VOID (kpg_temporaryUnmap); 8 | 9 | void resetPagingFake(); 10 | -------------------------------------------------------------------------------- /include/mock/kernel/pmm.h: -------------------------------------------------------------------------------- 1 | #ifndef PMM_FAKE_H 2 | #define PMM_FAKE_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | DECLARE_FUNC_VOID(kpmm_init); 9 | DECLARE_FUNC(bool, kpmm_free, Physical, UINT); 10 | DECLARE_FUNC(bool, kpmm_alloc, Physical*, UINT, KernelPhysicalMemoryRegions); 11 | DECLARE_FUNC(bool, kpmm_allocAt, Physical, UINT, KernelPhysicalMemoryRegions); 12 | DECLARE_FUNC(size_t, kpmm_getFreeMemorySize); 13 | DECLARE_FUNC(USYSINT, kpmm_getUsableMemorySize, KernelPhysicalMemoryRegions); 14 | 15 | void resetPmm(); 16 | 17 | #endif // PMM_FAKE_H 18 | -------------------------------------------------------------------------------- /include/mock/kernel/salloc.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | DECLARE_FUNC(void*, ksalloc,UINT); 4 | DECLARE_FUNC(void*, kscalloc,UINT); 5 | void reset_sallocFake(); 6 | -------------------------------------------------------------------------------- /include/mock/kernel/vmm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | DECLARE_FUNC(PTR, kvmm_memmap, VMemoryManager*, PTR, Physical const* const, SIZE, 8 | VMemoryMemMapFlags, Physical* const ); 9 | 10 | void resetVMMFake(); 11 | -------------------------------------------------------------------------------- /include/mock/kernel/x86/boot.h: -------------------------------------------------------------------------------- 1 | #ifndef BOOT_FAKE_X86_H 2 | #define BOOT_FAKE_X86_H 3 | 4 | #include 5 | #include 6 | 7 | DECLARE_FUNC (U16, kboot_getBootFileItemCount); 8 | DECLARE_FUNC (BootFileItem,kboot_getBootFileItem, INT); 9 | DECLARE_FUNC (BootMemoryMapItem,kboot_getBootMemoryMapItem, INT); 10 | DECLARE_FUNC (U16,kboot_getBootMemoryMapItemCount); 11 | DECLARE_FUNC (ULLONG,kboot_calculateInstalledMemory); 12 | DECLARE_FUNC (BootGraphicsModeInfo,kboot_getGraphicsModeInfo); 13 | 14 | void resetBootFake(); 15 | #endif //BOOT_FAKE_X86_H 16 | -------------------------------------------------------------------------------- /include/mock/kernel/x86/paging.h: -------------------------------------------------------------------------------- 1 | #ifndef PAGING_FAKE_X86_H 2 | #define PAGING_FAKE_X86_H 3 | 4 | #include 5 | #include 6 | 7 | DECLARE_FUNC(ArchPageDirectoryEntry*, s_getPdeFromCurrentPd, UINT); 8 | DECLARE_FUNC(ArchPageTableEntry*, s_getPteFromCurrentPd, UINT); 9 | DECLARE_FUNC (void *, s_getLinearAddress, UINT, UINT, UINT); 10 | 11 | void resetPagingFake(); 12 | 13 | #endif // PAGING_FAKE_X86_H 14 | -------------------------------------------------------------------------------- /include/mock/kernel/x86/pmm.h: -------------------------------------------------------------------------------- 1 | #ifndef PMM_FAKE_X86_H 2 | #define PMM_FAKE_X86_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | DECLARE_FUNC_VOID(kpmm_arch_init, Bitmap *); 9 | DECLARE_FUNC(U64, kpmm_arch_getInstalledMemoryByteCount); 10 | 11 | void resetX86Pmm(); 12 | 13 | #endif // PMM_FAKE_X86_H 14 | -------------------------------------------------------------------------------- /include/mock/kernel/x86/vgatext.c: -------------------------------------------------------------------------------- 1 | #ifndef VGADISP_FAKE_H 2 | #define VGADISP_FAKE_H 3 | 4 | #include 5 | #include 6 | 7 | DECLARE_FUNC_VOID(kdisp_putc, CHAR); 8 | DECLARE_FUNC_VOID(kdisp_scrollDown); 9 | DECLARE_FUNC_VOID(kdisp_init); 10 | 11 | void resetVgaDisp(); 12 | #endif // VGADISP_FAKE_H 13 | -------------------------------------------------------------------------------- /include/moslimits.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - Cross Platform Kernel - Limits 4 | * 5 | * Note: 6 | * Remember that these header files are for building OS and its utilitites, it 7 | * is not a SDK. 8 | * --------------------------------------------------------------------------- 9 | * 10 | * Dated: 7th September 2021 11 | */ 12 | 13 | #ifndef MOS_LIMITS_H 14 | #define MOS_LIMITS_H 15 | 16 | #include 17 | 18 | #if defined(__i386__) || (defined(UNITTEST) && ARCH == x86) 19 | #include 20 | #endif 21 | 22 | #endif //MOS_LIMITS_H 23 | -------------------------------------------------------------------------------- /include/mosunittest.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - Mocking macros for unit testing 4 | * --------------------------------------------------------------------------- 5 | */ 6 | 7 | #pragma once 8 | 9 | #if defined(UNITTEST) 10 | #include 11 | #include 12 | 13 | typedef struct MockedMacro { 14 | // Add fields here corresponding to the macro you are mocking 15 | int recursive_pde_index; 16 | int kernel_pde_index; 17 | int temporary_pte_index_extern; 18 | int temporary_pte_index_internal; 19 | uintptr_t arch_mem_start_kernel_pab; 20 | uintptr_t arch_mem_start_salloc; 21 | size_t arch_mem_len_bytes_salloc; 22 | size_t arch_mem_len_bytes_kmalloc; 23 | size_t config_handles_array_item_count; 24 | // LibCM 25 | size_t cm_arch_mem_len_bytes_malloc; 26 | } MockedMacro; 27 | 28 | // Need to define it when building unittests 29 | extern MockedMacro g_utmm; 30 | 31 | #define MOCK_THIS_MACRO_USING(mock_variable_name) g_utmm.mock_variable_name 32 | #define SET_MACRO_MOCK(mock_variable_name, value) g_utmm.mock_variable_name = (value) 33 | #endif // UNITTEST 34 | -------------------------------------------------------------------------------- /include/paging.h: -------------------------------------------------------------------------------- 1 | /* 2 | * -------------------------------------------------------------------------------- 3 | * Megha Operating System V2 - Cross Platform Kernel - Kernel and usermode paging 4 | * structures and casting methods. 5 | * 6 | * Methods to create PD, PT, map/unmap physical and virtual pages etc, in a Cross 7 | * platform way. 8 | * -------------------------------------------------------------------------------- 9 | */ 10 | 11 | #ifndef PAGING_H 12 | #define PAGING_H 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | typedef struct PageAttributes { 20 | bool present; 21 | bool writable; 22 | bool userAccessable; 23 | bool cacheDisable; 24 | bool writeThrough; 25 | } __attribute__ ((aligned (4))) PageAttributes; 26 | 27 | typedef struct ArchPageDirectoryEntry ArchPageDirectoryEntry; 28 | typedef struct ArchPageTableEntry ArchPageTableEntry; 29 | 30 | typedef ArchPageDirectoryEntry* PageDirectory; 31 | typedef ArchPageTableEntry* PageTable; 32 | 33 | typedef enum PagingMapFlags { 34 | PG_MAP_FLAG_KERNEL = (1 << 0), 35 | PG_MAP_FLAG_CACHE_ENABLED = (1 << 1), 36 | PG_MAP_FLAG_WRITABLE = (1 << 2), 37 | PG_MAP_FLAG_NOT_PRESENT = (1 << 3), 38 | PG_MAP_FLAG_DEFAULT = (PG_MAP_FLAG_CACHE_ENABLED), 39 | PG_MAP_FLAG_KERNEL_DEFAULT = (PG_MAP_FLAG_DEFAULT | PG_MAP_FLAG_KERNEL), 40 | } PagingMapFlags; 41 | 42 | typedef enum PagingOperationFlags { 43 | PG_NEWPD_FLAG_COPY_KERNEL_PAGES = (1 << 0), 44 | PG_NEWPD_FLAG_RECURSIVE_MAP = (1 << 1), 45 | PG_DELPD_FLAG_KEEP_KERNEL_PAGES = (1 << 2), 46 | PG_NEWPD_FLAG_CREATE_NEW = (1 << 3), 47 | } PagingOperationFlags; 48 | 49 | // Physical start of the page frame 'pf'. 50 | #define PAGEFRAME_TO_PHYSICAL(pf) (PAGEFRAMES_TO_BYTES (pf)) 51 | 52 | // A linear address to corresponding number of page frames. 53 | #define PHYSICAL_TO_PAGEFRAME(addr) (BYTES_TO_PAGEFRAMES_FLOOR (addr)) 54 | 55 | PageDirectory kpg_getcurrentpd(); 56 | bool kpg_mapContinous (PageDirectory pd, PTR vaStart, Physical paStart, SIZE numPages, 57 | PagingMapFlags flags); 58 | bool kpg_map (PageDirectory pd, PTR va, Physical pa, PagingMapFlags flags); 59 | bool kpg_unmapContinous (PageDirectory pd, PTR vaStart, SIZE numPages); 60 | bool kpg_unmap (PageDirectory pd, PTR va); 61 | void* kpg_temporaryMap (Physical pa); 62 | void kpg_temporaryUnmap(); 63 | bool kpg_doesMappingExists (PageDirectory pd, PTR va, Physical* pa); 64 | bool kpg_setupPageDirectory (Physical* const pd, PagingOperationFlags flags, 65 | Physical const* const kernelPD); 66 | bool kpg_deletePageDirectory (Physical pd, PagingOperationFlags flags); 67 | 68 | #endif // PAGING_H 69 | -------------------------------------------------------------------------------- /include/panic.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - Cross Platform Kernel - k_panic () 4 | * 5 | * Note: 6 | * Remember that these header files are for building OS and its utilitites, it 7 | * is not a SDK. 8 | * --------------------------------------------------------------------------- 9 | * 10 | * Dated: 5st November 2020 11 | */ 12 | #pragma once 13 | 14 | #include 15 | #include 16 | 17 | #ifndef UNITTEST 18 | void kpanic_ndu (UINT line, const CHAR* file, const CHAR* fmt, ...); 19 | 20 | /* Displays an error message on the screen and Halts */ 21 | #define k_panic(...) \ 22 | do { \ 23 | ARCH_DISABLE_INTERRUPTS() \ 24 | kpanic_ndu(__LINE__, __FILE__, __VA_ARGS__); \ 25 | } while (0) 26 | #else // UNITTEST 27 | void unittest_panic_handler (const CHAR* s, ...); 28 | extern bool panic_invoked; 29 | 30 | /* Returns from the 'function under testing', when an assert/panic is hit. 31 | * 32 | * There is x86 assembly hard coded in an arch independent header, however this corresponds to 33 | * the host (not the target) arch. Which implies that unittests can only be built & run on an 34 | * x86 machine. 35 | * 36 | * TODO: Find some way to make this host independent. 37 | * NOTE: EAX is not preserved by GCC. So there is not point adding it to the clobber list. 38 | */ 39 | #define UNITTEST_RETURN() __asm__ volatile("mov esp, ebp; pop ebp; mov eax, 0; ret;" ::) 40 | 41 | #define k_panic(s, ...) \ 42 | do \ 43 | { \ 44 | unittest_panic_handler ("\r\nPanic! " s ". In %s:%u", ##__VA_ARGS__, __func__, \ 45 | __LINE__); \ 46 | UNITTEST_RETURN(); \ 47 | } while (0) 48 | #endif // UNITTEST 49 | 50 | /* Halts the processor by going into infinite loop */ 51 | #define k_halt() \ 52 | ARCH_DISABLE_INTERRUPTS(); \ 53 | for (;;) 54 | -------------------------------------------------------------------------------- /include/pmm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - Cross Platform Kernel - Physical Memory Management Header 4 | * --------------------------------------------------------------------------- 5 | */ 6 | 7 | #ifndef PMM_H_X86 8 | #define PMM_H_X86 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | typedef enum KernelPhysicalMemoryRegions 18 | { 19 | PMM_REGION_ANY 20 | } KernelPhysicalMemoryRegions; 21 | 22 | typedef enum KernelPhysicalMemoryStates { 23 | PMM_STATE_FREE = 0, 24 | PMM_STATE_USED, 25 | PMM_STATE_RESERVED, 26 | PMM_STATE_INVALID 27 | } KernelPhysicalMemoryStates; 28 | 29 | void kpmm_init (); 30 | void kpmm_arch_init (Bitmap *bitmap); 31 | 32 | bool kpmm_free (Physical startAddress, UINT pageCount); 33 | bool kpmm_alloc (Physical *address, UINT pageCount, KernelPhysicalMemoryRegions reg); 34 | bool kpmm_allocAt (Physical start, UINT pageCount, KernelPhysicalMemoryRegions reg); 35 | 36 | size_t kpmm_getFreeMemorySize (); 37 | U64 kpmm_arch_getInstalledMemoryByteCount (); 38 | USYSINT kpmm_getUsableMemorySize (KernelPhysicalMemoryRegions reg); 39 | KernelPhysicalMemoryStates kpmm_getPageStatus(Physical phy); 40 | #endif // PMM_H_X86 41 | -------------------------------------------------------------------------------- /include/process.h: -------------------------------------------------------------------------------- 1 | /* 2 | * -------------------------------------------------------------------------------- 3 | * Megha Operating System V2 - Cross Platform Kernel - Process management 4 | * -------------------------------------------------------------------------------- 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define PROCESS_ID_KERNEL 0x0 16 | #define PROCESS_ID_INVALID -1 17 | #define KPROCESS_EXIT_CODE_FORCE_KILLED (255U) 18 | 19 | typedef enum KProcessStates { 20 | PROCESS_STATE_INVALID = 0, 21 | PROCESS_STATE_RUNNING = 1, 22 | PROCESS_STATE_IDLE = 2, 23 | } KProcessStates; 24 | 25 | typedef enum KProcessFlags { 26 | PROCESS_FLAGS_NONE = 0, 27 | PROCESS_FLAGS_KERNEL_PROCESS = (1 << 0), 28 | PROCESS_FLAGS_THREAD = (1 << 1), 29 | } KProcessFlags; 30 | 31 | __asm__(".equ PROCESS_FLAGS_KERNEL_PROCESS, (1 << 0);" 32 | ".equ PROCESS_FLAGS_THREAD, (1 << 1);"); 33 | 34 | typedef struct KProcessRegisterState ProcessRegisterState; 35 | 36 | typedef struct KProcessSections { 37 | PTR virtualMemoryStart; 38 | SIZE sizePages; 39 | } KProcessSections; 40 | 41 | typedef struct KProcessEvent { 42 | KernelEvents event; 43 | U64 data; 44 | ListNode eventQueueNode; 45 | } KProcessEvent; 46 | 47 | typedef struct KProcessInfo { 48 | // ---------------------- 49 | // Initial states. These do not change throuout the lifetime of the process. 50 | // ---------------------- 51 | KProcessSections binary; 52 | KProcessSections stack; 53 | KProcessSections data; 54 | VMemoryManager* context; 55 | ListNode schedulerQueueNode; // Processes are part of scheduler queue through this node. 56 | ListNode eventsQueueHead; // Start of the process events queue. 57 | ListNode childrenListHead; // Start of child processes list 58 | ListNode childrenListNode; // Processes are linked to the parent through this node. 59 | struct KProcessInfo* parent; // Parent process. NULL for processes with no parent (Root 60 | // processes). 61 | UINT processID; 62 | KProcessFlags flags; 63 | // ---------------------- 64 | // States which change 65 | // ---------------------- 66 | KProcessStates state; 67 | ProcessRegisterState* registerStates; 68 | } KProcessInfo; 69 | 70 | void kprocess_init(); 71 | INT kprocess_create (void* processStartAddress, SIZE binLengthBytes, KProcessFlags flags); 72 | bool kprocess_yield (ProcessRegisterState* currentState); 73 | bool kprocess_exit (U8 exitCode, bool destroyContext); 74 | VMemoryManager* kprocess_getCurrentContext(); 75 | UINT kprocess_getCurrentPID(); 76 | bool kprocess_popEvent (UINT pid, KProcessEvent* ev); 77 | bool kprocess_pushEvent (UINT pid, UINT eventID, UINT eventData); 78 | KProcessSections* kprocess_getCurrentProcessDataSection(); 79 | void kprocess_syncPD(); 80 | -------------------------------------------------------------------------------- /include/types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - Cross Platform Kernel - Potable Types 4 | * 5 | * Note: 6 | * Remember that these header files are for building OS and its utilitites, it 7 | * is not a SDK. 8 | * --------------------------------------------------------------------------- 9 | * 10 | * Dated: 1st November 2020 11 | */ 12 | 13 | #ifndef PORTABLE_TYPES 14 | #define PORTABLE_TYPES 15 | 16 | #include 17 | #include /*TODO: Remvoe this*/ 18 | 19 | #if defined(__i386__) || (defined(UNITTEST) && ARCH == x86) 20 | #include 21 | #endif 22 | 23 | typedef INT Handle; 24 | 25 | /* Casts a bit field of n bits to UINT. */ 26 | static inline UINT CAST_BITN_TO_U32 (UINT t, UINT n) { 27 | return (UINT)(t & (UINT)((1 << n) -1)); 28 | } 29 | 30 | /** Specific type to store Physical addresses. 31 | * This type will prevent mixing physical and virtual addresses and may be also lessen the need for 32 | * Hungarian notations. 33 | * 34 | * For ease of use, any variable of type USYSINT can be passed to a function expecting Physical 35 | * without any case (because of transparent union). 36 | 37 | * Use the 'Physical' macro for initializing variables or function parameters of type Physical. 38 | */ 39 | typedef union 40 | { 41 | USYSINT val; 42 | } __attribute__ ((packed)) Physical; 43 | 44 | #define PHYSICAL(address) {.val = address} 45 | 46 | static inline Physical createPhysical (USYSINT address) { 47 | Physical p = {.val = address}; 48 | return p; 49 | } 50 | 51 | #endif // PORTABLE_TYPES 52 | -------------------------------------------------------------------------------- /include/vmm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * -------------------------------------------------------------------------------------------------- 3 | * Megha Operating System V2 - Cross Platform Kernel - Virtual Memory Management Header 4 | * -------------------------------------------------------------------------------------------------- 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | typedef enum VMemoryMemMapFlags { 15 | VMM_MEMMAP_FLAG_NONE = 0, 16 | VMM_MEMMAP_FLAG_KERNEL_PAGE = (1 << 0), 17 | VMM_MEMMAP_FLAG_READONLY = (1 << 1), 18 | VMM_MEMMAP_FLAG_NULLPAGE = (1 << 2), // Never backed, page fault on access. 19 | VMM_MEMMAP_FLAG_IMMCOMMIT = (1 << 3), // Commit physical pages (use provided input) now. 20 | VMM_MEMMAP_FLAG_COMMITTED = (1 << 4), // VAs are already mapped outside VMM. 21 | } VMemoryMemMapFlags; 22 | 23 | typedef struct VMemoryManager VMemoryManager; 24 | 25 | VMemoryManager* kvmm_new (PTR start, PTR end, Physical pd, 26 | KernelPhysicalMemoryRegions physicalRegion); 27 | Physical kvmm_getPageDirectory (const VMemoryManager* vmm); 28 | bool kvmm_delete (VMemoryManager** vmm); 29 | bool kvmm_free (VMemoryManager* vmm, PTR start_va); 30 | bool kvmm_commitPage (VMemoryManager* vmm, PTR va); 31 | PTR kvmm_findFree (VMemoryManager* vmm, SIZE szPages); 32 | PTR kvmm_memmap (VMemoryManager* vmm, PTR va, Physical const* const pa, SIZE szPages, 33 | VMemoryMemMapFlags flags, Physical* const outPA); 34 | bool kvmm_checkbounds (VMemoryManager* vmm, PTR addr); 35 | bool kvmm_isPageDirectoryDirty (VMemoryManager* const vmm); 36 | 37 | #if defined(DEBUG) && defined(PORT_E9_ENABLED) 38 | void kvmm_printVASList (VMemoryManager* vmm); 39 | #else 40 | #define kvmm_printVASList(a) (void)0 41 | #endif 42 | 43 | #ifdef DEBUG 44 | void kvmm_setAddressSpaceMetadata (VMemoryManager const* const vmm, PTR addr, 45 | CHAR const* const purpose, UINT const* const pid); 46 | #else 47 | #define kvmm_setAddressSpaceMetadata(a, b, c, d) (void)0 48 | #endif // DEBUG 49 | -------------------------------------------------------------------------------- /include/vmm_struct.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - Cross Platform Kernel - VMM abstract structures 4 | * --------------------------------------------------------------------------- 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | typedef struct VMemoryShare { 15 | Physical* pages; 16 | SIZE count; // Number of pages added to the pages array 17 | SIZE refcount; // Number of VirtualAddressSpace objects that share this Memory 18 | } VMemoryShare; 19 | 20 | struct VMemoryManager { 21 | PTR start; 22 | PTR end; 23 | bool isStaticAllocated; 24 | Physical parentProcessPD; 25 | bool isPageDirectoryDirty; // Process's PageDirectory has changed. Will be reset once read. 26 | KernelPhysicalMemoryRegions physicalRegion; 27 | ListNode head; 28 | }; 29 | 30 | typedef struct VMemoryAddressSpace { 31 | bool isStaticAllocated; 32 | VMemoryMemMapFlags flags; 33 | PTR start_vm; // Address space starts from this Virtual address 34 | SIZE allocationSzBytes; // Number of virtual pages reserved by this Address space 35 | VMemoryShare* share; // MemoryShare associated with this mapping. 36 | ListNode adjMappingNode; // Adds to Virtual Address space list through this node. 37 | // These are debug specific properties/metadata and no operation in VMM depend on them. 38 | #ifdef DEBUG 39 | U32 processID; // 0 - Associated with kernel, otherwise this is the process ID 40 | char purpose[10]; // The purpose of this address space. 41 | 42 | #endif // DEBUG 43 | } VMemoryAddressSpace; 44 | -------------------------------------------------------------------------------- /include/x86/boot.h: -------------------------------------------------------------------------------- 1 | /* 2 | * -------------------------------------------------------------------------------------------------- 3 | * Megha Operating System V2 - x86 Bootloader 4 | * 5 | * Contains abstract structure declarations and methods that is used to get information from the 6 | * bootloader. 7 | * -------------------------------------------------------------------------------------------------- 8 | */ 9 | 10 | #pragma once 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #define BOOT_FONTS_GLYPH_COUNT 128U 17 | #define BOOT_FONTS_GLYPH_BYTES ((CONFIG_GXMODE_FONT_WIDTH * CONFIG_GXMODE_FONT_HEIGHT) / 8U) 18 | 19 | enum BootMemoryMapTypes { 20 | MMTYPE_FREE = 1, 21 | MMTYPE_RESERVED = 2, 22 | MMTYPE_ACPI_RECLAIM = 3, 23 | }; 24 | 25 | typedef U32 BootMemoryMapTypes; 26 | typedef struct BootLoaderInfo BootLoaderInfo; 27 | 28 | typedef struct BootMemoryMapItem { 29 | const U64 baseAddr; 30 | const U64 length; 31 | const BootMemoryMapTypes type; 32 | } __attribute__ ((packed)) BootMemoryMapItem; 33 | 34 | typedef struct BootFileItem { 35 | const U8 name[CONFIG_BOOT_FILENAME_LEN_CHARS]; 36 | const U32 startLocation; 37 | const U16 length; 38 | } __attribute__ ((packed)) BootFileItem; 39 | 40 | typedef struct BootGraphicsModeInfo { 41 | const U16 xResolution; 42 | const U16 yResolution; 43 | const U8 bitsPerPixel; 44 | const U16 graphicsMode; 45 | const U16 vbeVersion; 46 | const Physical framebufferPhysicalPtr; 47 | const U16 bytesPerScanLine; 48 | } __attribute__ ((packed)) BootGraphicsModeInfo; 49 | 50 | U16 kboot_getBootFileItemCount(); 51 | BootFileItem kboot_getBootFileItem (INT index); 52 | BootFileItem kboot_findBootFileItem (const CHAR* const filename); 53 | BootMemoryMapItem kboot_getBootMemoryMapItem (INT index); 54 | U16 kboot_getBootMemoryMapItemCount(); 55 | ULLONG kboot_calculateInstalledMemory(); 56 | 57 | BootGraphicsModeInfo kboot_getGraphicsModeInfo(); 58 | const U8* kboot_getFontData(); 59 | -------------------------------------------------------------------------------- /include/x86/boot_struct.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - x86 Bootloader 4 | * 5 | * Contains structures and methods that is used to get information from 6 | * bootloader. 7 | * --------------------------------------------------------------------------- 8 | */ 9 | 10 | #ifndef BOOT_STRUCT_H_X86 11 | #define BOOT_STRUCT_H_X86 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | struct BootLoaderInfo { 19 | const U8 font_data[BOOT_FONTS_GLYPH_COUNT * BOOT_FONTS_GLYPH_BYTES]; 20 | const struct BootGraphicsModeInfo gxInfo; 21 | const U16 filecount; 22 | const struct BootFileItem files[11]; 23 | const U16 count; 24 | const struct BootMemoryMapItem items[]; 25 | } __attribute__ ((packed)); 26 | 27 | #endif // BOOT_STRUCT_H_X86 28 | -------------------------------------------------------------------------------- /include/x86/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - x86 Kernel - Configuration 4 | * 5 | * These configurations can be used directly, but are most usually will be used 6 | * to calculate various limits and branch 7 | * --------------------------------------------------------------------------- 8 | */ 9 | 10 | #ifndef MOS_CONFIG_H_X86 11 | #define MOS_CONFIG_H_X86 12 | 13 | #include 14 | 15 | #define Byte (1U) 16 | #define KB (1024U) 17 | #define MB (1024U * KB) 18 | #define GB (1024U * MB) 19 | 20 | #define CONFIG_PAGE_SIZE_BITS (12U) 21 | #define CONFIG_PAGE_FRAME_SIZE_BYTES (4U * KB) 22 | #define CONFIG_MIN_RAM_BYTES (2U * MB) 23 | #define CONFIG_TXMODE_COLUMNS 80 // TODO: Replace MAX_VGA_ROWS, COLUMNS with these. 24 | #define CONFIG_TXMODE_ROWS 50 25 | #define CONFIG_MAX_CALL_TRACE_DEPTH 10 26 | #define CONFIG_PAB_NUMBER_OF_PAGES 1 /* Must be 1. Limitations of current Physical Map */ 27 | #define CONFIG_GXMODE_FONT_WIDTH 8 28 | #define CONFIG_GXMODE_FONT_HEIGHT 16 29 | #define CONFIG_GXMODE_XRESOLUTION 800 30 | #define CONFIG_GXMODE_YRESOLUTION 600 31 | #define CONFIG_GXMODE_BITSPERPIXEL GRAPHICS_BPP 32 | 33 | #define CONFIG_INTERRUPT_CLOCK_FREQ_HZ (1000U) 34 | #define CONFIG_PROCESS_PERIOD_US (20000U) /* Processes should yield before this time */ 35 | #define CONFIG_VIDEO_REFRESH_PERIOD_US (20000U) 36 | 37 | #define CONFIG_HANDLES_ARRAY_ITEM_COUNT (1000) /* Number of objects stored in handles array */ 38 | 39 | #define CONFIG_PS2_MOUSE_SAMPLE_RATE (40) 40 | 41 | #define CONFIG_BOOT_FILENAME_LEN_CHARS (12) /* Fat12. Zero terminated string */ 42 | 43 | /** Derived Configs 44 | * SHOULD NOT BE EDITTED MANUALLY */ 45 | #define CONFIG_PAGE_FRAME_SIZE_BITS (31U - CONFIG_PAGE_SIZE_BITS) 46 | #define CONFIG_INTERRUPT_CLOCK_TP_MICROSEC (1000000U/CONFIG_INTERRUPT_CLOCK_FREQ_HZ) 47 | #define CONFIG_TICK_PERIOD_MICROSEC (CONFIG_INTERRUPT_CLOCK_TP_MICROSEC) 48 | 49 | #endif // MOS_CONFIG_H_X86 50 | -------------------------------------------------------------------------------- /include/x86/cpu.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - x86 Kernel - CPU Registers 4 | * --------------------------------------------------------------------------- 5 | */ 6 | #pragma once 7 | 8 | #include 9 | #include 10 | 11 | typedef struct x86_CR3 { 12 | UINT reserved0 : 3; // 0 - 2 13 | UINT pwt : 1; // 3 14 | UINT pcd : 1; // 4 15 | UINT reserved1 : 7; // 5 - 11 16 | UINT physical : 20; // 12 - 31 17 | } __attribute__((packed)) x86_CR3; 18 | 19 | #define X86_EFLAGS_BIT1_ALWAYS_ONE (1 << 1) 20 | #define X86_EFLAGS_INTERRUPT_ENABLE (1 << 9) 21 | 22 | #define x86_LOAD_REG(reg, source) __asm__ volatile("mov " #reg ", %0;" ::"r"(source)) 23 | #define x86_READ_REG(reg, dest) __asm__ volatile("mov %0, " #reg :"=r"(dest)) 24 | #define x86_READ_EFLAGS(dest) __asm__ volatile("pushfd\n pop %0" :"=r"(dest)) 25 | #define X86_PAUSE() __asm__ volatile("pause") 26 | #define X86_ENABLE_INTERRUPTS() __asm__ volatile("sti") 27 | #define X86_DISABLE_INTERRUPTS() __asm__ volatile("cli") 28 | -------------------------------------------------------------------------------- /include/x86/gdt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - x86 Kernel - GDT Header 4 | * --------------------------------------------------------------------------- 5 | */ 6 | #ifndef GDT_H_X86 7 | #define GDT_H_X86 8 | 9 | #include 10 | #include 11 | 12 | typedef struct GdtDescriptor GdtDescriptor; 13 | typedef struct GdtMeta GdtMeta; 14 | 15 | #define GDT_SELECTOR_FROM_INDEX(index, ring) ((index)<<3)|(ring) 16 | 17 | // Kernel Code segment selector. 18 | #define GDT_INDEX_KCODE 1 19 | #define GDT_SELECTOR_KCODE GDT_SELECTOR_FROM_INDEX (GDT_INDEX_KCODE, 0) 20 | 21 | // Kernel Data segment selector. 22 | #define GDT_INDEX_KDATA 2 23 | #define GDT_SELECTOR_KDATA GDT_SELECTOR_FROM_INDEX (GDT_INDEX_KDATA, 0) 24 | 25 | // Kernel TSS segment selector. 26 | #define GDT_INDEX_KTSS 3 27 | #define GDT_SELECTOR_KTSS GDT_SELECTOR_FROM_INDEX (GDT_INDEX_KTSS, 0) 28 | 29 | // User Code segment selector. 30 | #define GDT_INDEX_UCODE 4 31 | #define GDT_SELECTOR_UCODE GDT_SELECTOR_FROM_INDEX (GDT_INDEX_UCODE, 3) 32 | 33 | // User Data segment selector. 34 | #define GDT_INDEX_UDATA 5 35 | #define GDT_SELECTOR_UDATA GDT_SELECTOR_FROM_INDEX (GDT_INDEX_UDATA, 3) 36 | 37 | /* Edits a GDT descriptor in the GDT table. 38 | * Note: If gdt_index < 3 or > gdt_count or > GDT_MAX_COUNT then an exception 39 | * is generated. 40 | */ 41 | void kgdt_edit (U16 gdt_index, U32 base, U32 limit, U8 access, U8 flags); 42 | 43 | /* Writes the GDT structure address and length to the GDTR register. */ 44 | void kgdt_write (); 45 | 46 | #endif // GDT_H_X86 47 | -------------------------------------------------------------------------------- /include/x86/gdt_struct.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - x86 Kernel - GDT abstract structures 4 | * --------------------------------------------------------------------------- 5 | */ 6 | #ifndef GDT_STRUCT_H_X86 7 | #define GDT_STRUCT_H_X86 8 | 9 | #include 10 | #include 11 | 12 | struct GdtDescriptor 13 | { 14 | U16 limit_low; 15 | U16 base_low; 16 | U8 base_middle; 17 | U8 access; 18 | U8 limit_high:4; 19 | U8 flags :4; 20 | U8 base_high; 21 | } __attribute__ ((packed)); 22 | 23 | struct GdtMeta 24 | { 25 | U16 size; 26 | U32 location; 27 | } __attribute__ ((packed)); 28 | 29 | #endif // GDT_STRUCT_H_X86 30 | -------------------------------------------------------------------------------- /include/x86/idt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - x86 Kernel - IDT Header 4 | * --------------------------------------------------------------------------- 5 | */ 6 | #ifndef IDT_H_X86 7 | #define IDT_H_X86 8 | 9 | #include 10 | #include 11 | 12 | typedef enum IDTDescriptorTypes 13 | { 14 | IDT_DES_TYPE_TASK_GATE = 5, 15 | IDT_DES_TYPE_16_INTERRUPT_GATE = 6, 16 | IDT_DES_TYPE_32_INTERRUPT_GATE = 0xE, 17 | IDT_DES_TYPE_16_TRAP_GATE = 7, 18 | IDT_DES_TYPE_32_TRAP_GATE = 0xF 19 | } IDTDescriptorTypes; 20 | 21 | /* IDT Descriptor */ 22 | typedef struct IdtDescriptor IdtDescriptor; 23 | typedef struct IdtMeta IdtMeta; 24 | 25 | /* Fills the IDT table with zeros, and setup the IDTR register */ 26 | void kidt_init (); 27 | 28 | /* Edits an IDT descriptor */ 29 | void kidt_edit (INT index, 30 | void (*func)(), 31 | U16 seg_selector, 32 | IDTDescriptorTypes type, 33 | U8 dpl); 34 | 35 | #endif //IDT_H_X86 36 | -------------------------------------------------------------------------------- /include/x86/idt_struct.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - x86 Kernel - IDT abstract structures 4 | * --------------------------------------------------------------------------- 5 | */ 6 | #ifndef IDT_STRUCT_H_X86 7 | #define IDT_STRUCT_H_X86 8 | 9 | #include 10 | #include 11 | 12 | /* IDT Descriptor */ 13 | struct IdtDescriptor 14 | { 15 | U16 offset_low; 16 | U16 segment_selector; 17 | U8 zeros; 18 | U8 type : 5; 19 | U8 dpl : 2; 20 | U8 p : 1; 21 | U16 offset_high; 22 | } __attribute__ ((packed)); 23 | 24 | struct IdtMeta 25 | { 26 | U16 limit; 27 | U32 location; 28 | } __attribute__ ((packed)); 29 | 30 | #endif //IDT_STRUCT_H_X86 31 | -------------------------------------------------------------------------------- /include/x86/io.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - x86 Kernel - Basic I/O routines. 4 | * 5 | * This is not and never going to be a full featured VGA text mode driver. 6 | * Functions here will be limited to prints or printf like functions. 7 | * NOTE: Actual VGA driver will be a server in User Mode. 8 | * --------------------------------------------------------------------------- 9 | * 10 | * Dated: 24th October 2020 11 | */ 12 | 13 | #ifndef IO_H_X86 14 | #define IO_H_X86 15 | 16 | #include 17 | #include 18 | 19 | #define outb(p,v) __asm__ volatile ("out dx, al;" : :"a" (v), "d" (p)) 20 | #define inb(p,v) __asm__ volatile ("xor %0, %0; in al, dx" :"=a" (v) :"d" (p)) 21 | // Reference: https://wiki.osdev.org/Inline_Assembly/Examples#IO_WAIT 22 | #define io_delay() outb(0x80, 0) 23 | 24 | static inline U8 ioread (INT port) 25 | { 26 | U8 v; 27 | inb (port, v); 28 | return v; 29 | } 30 | 31 | #endif // IO_H_X86 32 | -------------------------------------------------------------------------------- /include/x86/memloc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - x86 Kernel - Static Memory Locations 4 | * 5 | * Note: 6 | * See Physical/Virtual Memory regions documentation for complete memory map 7 | ; --------------------------------------------------------------------------- 8 | */ 9 | 10 | #if !defined(MEM_LOC_H_X86) 11 | #define MEM_LOC_H_X86 12 | 13 | #if !defined(UNITTEST) 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define MEM_START_KERNEL_LOW_REGION (3 * GB) 20 | 21 | #define MEM_START_IDT MEM_START_KERNEL_LOW_REGION 22 | #define MEM_START_HIGHER_HALF_MAP MEM_START_KERNEL_LOW_REGION 23 | #define MEM_LEN_BYTES_IDT (4 * KB) 24 | 25 | #define MEM_START_GDT 0xC0001000 26 | #define MEM_LEN_BYTES_GDT (4 * KB) 27 | 28 | #define MEM_START_BOOT_INFO 0xC0002000 29 | #define MEM_LEN_BYTES_BOOT_INFO (4 * KB) 30 | 31 | #define MEM_START_KSTACK 0xC0003000 32 | #define MEM_LEN_BYTES_KSTACK (128 * KB) 33 | /* Stack grows down from here */ 34 | #define MEM_KSTACK_TOP ((MEM_START_KSTACK + MEM_LEN_BYTES_KSTACK) - 1) 35 | 36 | #define MEM_START_VGA_TEXT 0xC00B8000 /* VGA Text mode buffer */ 37 | 38 | #define MEM_START_KERNEL_PAGE_DIR 0xC0023000 39 | #define MEM_LEN_BYTES_KERNEL_PAGE_DIR (4 * KB) 40 | 41 | #define MEM_START_KERNEL_PAGE_TABLE 0xC0024000 42 | #define MEM_LEN_BYTES_KERNEL_PAGE_TABLE (4 * KB) 43 | 44 | #define X86_MEM_START_KERNEL_PAB 0xC0025000 45 | #define X86_MEM_LEN_BYTES_KERNEL_PAB PAB_SIZE_BYTES 46 | 47 | #define X86_MEM_START_SALLOC 0xC0026000 48 | #define X86_MEM_LEN_BYTES_SALLOC (128 * KB) 49 | 50 | #define MEM_END_KERNEL_LOW_REGION (0xC0046000 - 1) 51 | #define MEM_LEN_BYTES_KERNEL_LOW_REGION \ 52 | MEM_LEN_BYTES (MEM_START_KERNEL_LOW_REGION, MEM_END_KERNEL_LOW_REGION) 53 | 54 | #define MEM_START_KERNEL_HIGH_REGION 0xC0100000 55 | #ifdef GRAPHICS_MODE_ENABLED 56 | #define X86_MEM_LEN_BYTES_KMALLOC (128 * KB) 57 | #else 58 | #define X86_MEM_LEN_BYTES_KMALLOC (128 * KB) 59 | #endif // GRAPHICS_MODE_ENABLED 60 | 61 | #define MEM_END_HIGHER_HALF_MAP 0xC0200000 62 | 63 | #define X86_MEM_START_PROCESS_MEMORY (4 * KB) // 0000h -> 1000h being NULL page 64 | #define X86_MEM_START_PROCESS_TEXT (64 * KB) // Not sure why I choose 64 KB here! 65 | #define X86_MEM_START_PROCESS_DATA (2 * MB) 66 | #define X86_MEM_LEN_BYTES_PROCESS_STACK (256 * KB) 67 | #define X86_MEM_LEN_BYTES_PROCESS_DATA (256 * KB) 68 | #define X86_MEM_END_PROCESS_MEMORY (3 * GB - 1) 69 | 70 | #define MEM_START_PAGING_EXT_TEMP_MAP 0xC03FE000U // Temporary map for external modules 71 | #define MEM_START_PAGING_INT_TEMP_MAP 0xC03FF000U // Temporary map for Paging module 72 | #define MEM_START_PAGING_RECURSIVE_MAP 0xFFC00000U // Recursive map of PDs 73 | 74 | #define MEM_END_KERNEL_HIGH_REGION (MEM_START_PAGING_RECURSIVE_MAP - 1) 75 | #define MEM_LEN_BYTES_KERNEL_HIGH_REGION \ 76 | MEM_LEN_BYTES (MEM_START_KERNEL_HIGH_REGION, MEM_END_KERNEL_HIGH_REGION) 77 | #endif // UNITTEST 78 | 79 | #endif // MEM_LOC_H_X86 80 | -------------------------------------------------------------------------------- /include/x86/moslimits.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - x86 Kernel - Limits 4 | * 5 | * Note: 6 | * Remember that these header files are for building OS and its utilitites, it 7 | * is not a SDK. 8 | * --------------------------------------------------------------------------- 9 | * 10 | * Dated: 7th September 2021 11 | */ 12 | 13 | #ifndef MOS_LIMITS_H_X86 14 | #define MOS_LIMITS_H_X86 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #define MAX_VGA_COLUMNS 80U 22 | #define MAX_VGA_ROWS 50U 23 | #define MAX_PRINTABLE_STRING_LENGTH (MAX_VGA_COLUMNS * MAX_VGA_ROWS) 24 | 25 | #define MIN_GDT_INDEX 3U /* Minimum index that can be editted in Kernel. */ 26 | #define MAX_GDT_DESC_COUNT 512U /* Number of GDT entries in memory */ 27 | #define MAX_IDT_DESC_COUNT 256U /* Maximum number of IDT entries */ 28 | 29 | /* PAB and addressable RAM */ 30 | #define PAB_BITS_PER_STATE 2U 31 | #define PAB_SIZE_BYTES (CONFIG_PAGE_FRAME_SIZE_BYTES * CONFIG_PAB_NUMBER_OF_PAGES) 32 | 33 | #define MAX_PAB_ADDRESSABLE_PAGE_COUNT (PAB_SIZE_BYTES * 8 / PAB_BITS_PER_STATE) 34 | #define MAX_PAB_ADDRESSABLE_BYTE_COUNT (PAGEFRAME_TO_PHYSICAL (MAX_PAB_ADDRESSABLE_PAGE_COUNT)) 35 | #define MAX_PAB_ADDRESSABLE_BYTE (MAX_PAB_ADDRESSABLE_BYTE_COUNT - 1) 36 | #define MAX_PAB_ADDRESSABLE_PAGE (MAX_PAB_ADDRESSABLE_PAGE_COUNT - 1) 37 | 38 | // Interrupt/Exception frame size 39 | #define INTERRUPT_FRAME_SIZE_BYTES (4 * 12) 40 | 41 | // Interrupt clock 42 | // PIT_BASE_CLOCK_FREQ_HZ/65535 = 18.2 43 | #define MIN_INTERRUPT_CLOCK_FREQ_HZ (19U) 44 | #define MAX_INTERRUPT_CLOCK_TP_MICROSEC (1000000U / MIN_INTERRUPT_CLOCK_FREQ_HZ) 45 | 46 | #endif // MOS_LIMITS_H_X86 47 | -------------------------------------------------------------------------------- /include/x86/process.h: -------------------------------------------------------------------------------- 1 | /* 2 | * -------------------------------------------------------------------------------- 3 | * Megha Operating System V2 - x86 Kernel - Process management 4 | * -------------------------------------------------------------------------------- 5 | */ 6 | #pragma once 7 | 8 | #include 9 | #include 10 | 11 | // Process EAX, ECX and EDX are not preserved by the Scheduler as these are treated as scratch 12 | // registers. If requried these registers must be preserved by the caller just before doing a system 13 | // call. 14 | struct KProcessRegisterState { 15 | U32 ebx; 16 | U32 esi; 17 | U32 edi; 18 | U32 esp; 19 | U32 ebp; 20 | U32 eip; 21 | U32 eflags; 22 | U32 cs; 23 | U32 ds; // Not just DS. SS, ES, FS, GS are also set to this. 24 | }; 25 | -------------------------------------------------------------------------------- /include/x86/tss.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - x86 Kernel - TSS header 4 | * --------------------------------------------------------------------------- 5 | */ 6 | 7 | #ifndef TSS_H_X86 8 | #define TSS_H_X86 9 | 10 | #include 11 | 12 | /* Initializes the tss_entry structure, installs a tss segment in GDT */ 13 | void ktss_init (); 14 | 15 | #endif // TSS_H_X86 16 | -------------------------------------------------------------------------------- /include/x86/types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - x86 Kernel - Platform specific Types 4 | * 5 | * Note: 6 | * Remember that these header files are for building OS and its utilitites, it 7 | * is not a SDK. 8 | * --------------------------------------------------------------------------- 9 | * 10 | * Dated: 1st November 2020 11 | */ 12 | 13 | #ifndef TYPES_H_X86 14 | #define TYPES_H_X86 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | typedef uint8_t U8; 21 | typedef uint16_t U16; 22 | 23 | /* For any environment, UINT and INT will match the native width of 24 | * registers. So when fast speed is required, or variabled are platform 25 | * independent, use UINT or INT instead of U32 or S32.*/ 26 | typedef uint32_t U32; 27 | typedef U32 UINT; 28 | typedef U32 ULONG; 29 | 30 | typedef int32_t S32; 31 | typedef S32 INT; 32 | typedef S32 LONG; 33 | 34 | typedef uint64_t U64; 35 | typedef U64 ULLONG; 36 | 37 | typedef int64_t S64; 38 | typedef S64 LLONG; 39 | 40 | /* The C99 standard, defines the minimum sizes of integer types. So the exact size of compiler 41 | * dependent. CHAR type must be of type CHAR, which is different from int8_t or uint8_t. 42 | */ 43 | typedef unsigned char UCHAR; 44 | typedef char CHAR; 45 | 46 | /* Large enough to hold the largest address possible on a 32 bit system */ 47 | typedef U32 USYSINT; 48 | typedef uintptr_t PTR; 49 | typedef size_t SIZE; 50 | 51 | #endif // TYPES_H_X86 52 | -------------------------------------------------------------------------------- /include/x86/vgatext.h: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - x86 Kernel - VGA Routines etc. 4 | * 5 | * Note: 6 | * Remember that these header files are for building OS and its utilitites, it 7 | * is not a SDK. 8 | * --------------------------------------------------------------------------- 9 | * 10 | * Dated: 1st November 2020 11 | */ 12 | #ifndef VGA_TEXT_H_X86 13 | #define VGA_TEXT_H_X86 14 | 15 | #include 16 | 17 | typedef enum DisplayVgaColors 18 | { 19 | BLACK, 20 | BLUE, 21 | GREEN, 22 | CYAN, 23 | RED, 24 | MAGENTA, 25 | BROWN, 26 | LIGHT_GRAY, 27 | DARK_GRAY, 28 | LIGHT_BLUE, 29 | LIGHT_GREEN, 30 | LIGHT_CYAN, 31 | LIGHT_RED, 32 | PINK, 33 | YELLOW, 34 | WHITE 35 | } DisplayVgaColors; 36 | 37 | #define k_dispAttr(bg,fg,b) ((b)<<7|(bg)<<4|(fg)) 38 | 39 | #endif // VGA_TEXT_H_X86 40 | -------------------------------------------------------------------------------- /scripts/create-floppyimg.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # --------------------------------------------------------------------------- 4 | # Usage: 5 | # 6 | # --------------------------------------------------------------------------- 7 | if [ $# -eq 0 ]; then 8 | echo "Usage $0 " 9 | exit 1 10 | fi 11 | 12 | OBJDIR="$1" 13 | IMAGEDIR="$2" 14 | DISKTEMPDIR=$(mktemp -d) 15 | 16 | # --------------------------------------------------------------------------- 17 | # Build the floppy image 18 | echo " [ Creating disk image ] " 19 | rm -f $IMAGEDIR/mos.flp || exit 20 | mkdosfs -C $IMAGEDIR/mos.flp -F 12 1440 || exit 21 | 22 | # mount the Disk image 23 | echo " [ Mounting Disk image ] " 24 | sudo mount $IMAGEDIR/mos.flp $DISKTEMPDIR || exit 25 | # --------------------------------------------------------------------------- 26 | # Copy the files needed to the floppy 27 | echo " [ Copy files to floppy ] " 28 | sudo cp -v $OBJDIR/* $DISKTEMPDIR ||exit 29 | 30 | # Unmount the image 31 | echo " [ Copy of files done. Unmounting image ] " 32 | sudo umount $DISKTEMPDIR || exit 33 | 34 | # Wrtie the bootloader 35 | echo " [ Writing bootloader to floppy image ] " 36 | dd conv=notrunc if=$OBJDIR/boot0.flt of=$IMAGEDIR/mos.flp || exit 37 | -------------------------------------------------------------------------------- /scripts/invokeprog.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #------------------------------------------------------------------------------- 4 | # To be used to invoke a script/program from build system at build time. There 5 | # is no way to pass arguments from the build system (ex make, ninja etc) to the 6 | # program invoked by it. This is why the script is requried. The arguments are 7 | # passed in ARGS environment variable which this script passed to the invoked 8 | # program in an transparent way. 9 | # Example: 10 | # make ARGS="-S -s" run 11 | #------------------------------------------------------------------------------- 12 | 13 | [[ $# -lt 1 ]] && \ 14 | echo -e "Usage: $0 \n" \ 15 | '\tArguments to are read from `ARGS` env variable' \ 16 | && exit 1 17 | 18 | PROG="$1"; shift 19 | ${PROG} "$@" ${ARGS} 20 | -------------------------------------------------------------------------------- /scripts/lint.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | LINTNAME='cppcheck' 4 | LINTPATH=`which $LINTNAME` 5 | 6 | if [ ! -e "$LINTPATH" ]; then 7 | echo Cannot find linting software. Install $LINTNAME. 8 | exit 1 9 | fi 10 | 11 | OUTFILE=$1 12 | 13 | cppcheck --output-file="$OUTFILE" \ 14 | --language=c \ 15 | --enable=warning,performance,portability,style \ 16 | --template=gcc \ 17 | --std=c99 \ 18 | --inconclusive \ 19 | --quiet \ 20 | --platform=unix32 \ 21 | -I include \ 22 | -D__i386__ \ 23 | -DDEBUG \ 24 | -DPORT_E9_ENABLED \ 25 | src/common src/kernel/ || exit 26 | -------------------------------------------------------------------------------- /scripts/postbuild.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # ----------------------------------------------------------------------------- 4 | # Helper script to run various post-build tools for example ctags, cscope. It 5 | # can also generate unittest coverage reports. 6 | # ----------------------------------------------------------------------------- 7 | 8 | # Valid modes: GENTAG, GENCOV 9 | MODE=GENTAG 10 | 11 | # ----------------------------------------------------------------------------- 12 | # Prints Usage message and exits 13 | function fatal() 14 | { 15 | USAGE="\nGenerates either ctags/cscope db files or unittests coverage.\n" 16 | USAGE+="Usage:\n" 17 | USAGE+="\t$0 [--test-dir= " 18 | USAGE+="--cov-dir=]\n\n" 19 | USAGE+="If no arguments are given, it runs in GENTAG mode and generates" 20 | USAGE+="ctags and cscope db files, otherwise uses the provided input to" 21 | USAGE+="run the unittests and generate coverage report." 22 | 23 | echo -e $USAGE 24 | exit 1 25 | } 26 | # ----------------------------------------------------------------------------- 27 | # Parse Input arguments 28 | # ----------------------------------------------------------------------------- 29 | for arg in "$@"; do 30 | case $arg in 31 | --tests-dir=*) { 32 | TEST_DIR=${arg##*=} 33 | MODE=GENCOV 34 | };; 35 | --cov-dir=* ) { 36 | COV_DIR=${arg##*=} 37 | MODE=GENCOV 38 | };; 39 | * ) echo "Invalid arg $arg" && fatal 40 | esac 41 | done 42 | 43 | # ----------------------------------------------------------------------------- 44 | # Validate input 45 | # ----------------------------------------------------------------------------- 46 | [[ $MODE == "GENCOV" ]] && [[ -z $TEST_DIR ]] && \ 47 | echo "Test directory path not provided. Cannot continue." && fatal 48 | [[ $MODE == "GENCOV" ]] && [[ -z $COV_DIR ]] && \ 49 | echo "Coverage directory path not provided. Cannot continue." && fatal 50 | 51 | # ----------------------------------------------------------------------------- 52 | 53 | function gentag() 54 | { 55 | command -v ctags > /dev/null || { 56 | echo "ctags not found. Skipping" 57 | exit 58 | } 59 | 60 | command -v cscope > /dev/null || { 61 | echo "scope not found. Skipping" 62 | exit 63 | } 64 | 65 | ctags -R ./src ./include 66 | cscope -R -k -b -I ./include 67 | } 68 | 69 | function gencov() 70 | { 71 | local CovDataFile="${COV_DIR}/capture.data" 72 | local CovReportDirPath="${COV_DIR}/report" 73 | 74 | ./scripts/run.sh --tests-dir "${TEST_DIR}" > /dev/null 2>&1 || exit 75 | 76 | lcov --capture --directory . \ 77 | -rc lcov_branch_coverage=1 \ 78 | --output-file $CovDataFile > /dev/null || exit 79 | 80 | genhtml $CovDataFile \ 81 | --branch-coverage \ 82 | --dark-mode \ 83 | -o $CovReportDirPath > /dev/null || exit 84 | } 85 | # ----------------------------------------------------------------------------- 86 | 87 | case $MODE in 88 | "GENTAG") gentag;; 89 | "GENCOV") gencov;; 90 | * ) echo "Invalid mode $MODE" && exit 1 91 | esac 92 | -------------------------------------------------------------------------------- /src/apps/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${PROJECT_SOURCE_DIR}/cmake/${ARCH}/userflags.cmake) 2 | 3 | # --------------------------------------------------------------------------- 4 | # Program - Proc1 5 | # --------------------------------------------------------------------------- 6 | compile_lib( 7 | NAME proc1 8 | SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/proc1.c 9 | FLAGS ${MOS_USER_GCC_FLAGS} 10 | DEPENDS cm 11 | DEFINITIONS ${MOS_USER_GCC_DEFINITIONS} 12 | INCLUDE_DIRECTORIES ${MOS_USER_GCC_INCLUDE_DIRS} 13 | ) 14 | 15 | link( 16 | FLATTEN 17 | NAME proc1.flt 18 | DEPENDS proc1 crta 19 | FLAGS ${MOS_LINKER_OPTIONS} 20 | LINKER_FILE ${MOS_USER_LINKER_SCRIPT_FILE} 21 | LINK_LIBRARIES cm 22 | ) 23 | 24 | # --------------------------------------------------------------------------- 25 | # Program - MPDEMO 26 | # --------------------------------------------------------------------------- 27 | compile_lib( 28 | NAME mpdemo 29 | SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/mpdemo.c 30 | FLAGS ${MOS_USER_GCC_FLAGS} 31 | DEPENDS cm 32 | DEFINITIONS ${MOS_USER_GCC_DEFINITIONS} 33 | INCLUDE_DIRECTORIES ${MOS_USER_GCC_INCLUDE_DIRS} 34 | ) 35 | 36 | link( 37 | FLATTEN 38 | NAME mpdemo.flt 39 | DEPENDS mpdemo crta 40 | FLAGS ${MOS_LINKER_OPTIONS} 41 | LINKER_FILE ${MOS_USER_LINKER_SCRIPT_FILE} 42 | LINK_LIBRARIES cm 43 | ) 44 | 45 | # --------------------------------------------------------------------------- 46 | # Program - GUI0 47 | # --------------------------------------------------------------------------- 48 | compile_lib( 49 | NAME gui0 50 | SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/gui0.c 51 | FLAGS ${MOS_USER_GCC_FLAGS} 52 | DEPENDS cm 53 | DEFINITIONS ${MOS_USER_GCC_DEFINITIONS} 54 | INCLUDE_DIRECTORIES ${MOS_USER_GCC_INCLUDE_DIRS} 55 | ) 56 | 57 | link( 58 | FLATTEN 59 | NAME gui0.flt 60 | DEPENDS gui0 crta 61 | FLAGS ${MOS_LINKER_OPTIONS} 62 | LINKER_FILE ${MOS_USER_LINKER_SCRIPT_FILE} 63 | LINK_LIBRARIES cm 64 | ) 65 | 66 | # --------------------------------------------------------------------------- 67 | # Program - INIT 68 | # --------------------------------------------------------------------------- 69 | set(MOS_INIT_PROGRAM \"MPDEMO.FLT\" CACHE STRING "Program which the init starts first.") 70 | set(MOS_INIT_PROGRAMS \"MPDEMO.FLT\" \"PROC1.FLT\" \"GUI0.FLT\") 71 | set_property(CACHE MOS_INIT_PROGRAM PROPERTY STRINGS ${MOS_INIT_PROGRAMS}) 72 | 73 | compile_lib( 74 | NAME init 75 | SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/init.c 76 | FLAGS ${MOS_USER_GCC_FLAGS} 77 | DEPENDS cm 78 | DEFINITIONS ${MOS_USER_GCC_DEFINITIONS} INIT_PROG=${MOS_INIT_PROGRAM} 79 | INCLUDE_DIRECTORIES ${MOS_USER_GCC_INCLUDE_DIRS} 80 | ) 81 | 82 | link( 83 | FLATTEN 84 | NAME init.flt 85 | DEPENDS init crta 86 | FLAGS ${MOS_LINKER_OPTIONS} 87 | LINKER_FILE ${MOS_USER_LINKER_SCRIPT_FILE} 88 | LINK_LIBRARIES cm 89 | ) 90 | 91 | #--------------------------------------------------------------------------- 92 | # Add to the global 'build-all' target 93 | #--------------------------------------------------------------------------- 94 | add_dependencies(build-all init.flt) 95 | 96 | if (MOS_GRAPHICS_ENABLED) 97 | add_dependencies(build-all gui0.flt) 98 | else() 99 | add_dependencies(build-all proc1.flt mpdemo.flt) 100 | endif() 101 | -------------------------------------------------------------------------------- /src/apps/gui0.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | void thread0(); 8 | void thread1(); 9 | void thread2(); 10 | 11 | static OSIF_WindowFrameBufferInfo createWindow (const char* const title) 12 | { 13 | Handle h = cm_window_create (title); 14 | if (h == INVALID_HANDLE) { 15 | CM_DBG_ERROR ("Window creation failed"); 16 | HALT(); 17 | } 18 | 19 | OSIF_WindowFrameBufferInfo fbi; 20 | if (!cm_window_getFB (h, &fbi)) { 21 | CM_DBG_ERROR ("Window creation failed"); 22 | HALT(); 23 | } 24 | 25 | return fbi; 26 | } 27 | 28 | static void triangle_sum (int* now, int start, int end, int* incby) 29 | { 30 | int l_now = *now; 31 | 32 | l_now += *incby; 33 | 34 | if (l_now >= end) { 35 | l_now = end; 36 | } else if (l_now <= start) { 37 | l_now = start; 38 | } 39 | 40 | if (l_now == end || l_now == start) { 41 | *incby *= -1; 42 | } 43 | 44 | *now = l_now; 45 | } 46 | 47 | static void repaint_on_yield (OSIF_ProcessEvent const* const e) 48 | { 49 | (void)e; 50 | cm_window_flush_graphics(); 51 | } 52 | 53 | void proc_main() 54 | { 55 | cm_window_flush_graphics(); 56 | cm_thread_create (&thread0, false); 57 | cm_thread_create (&thread1, false); 58 | cm_thread_create (&thread2, false); 59 | 60 | cm_process_register_event_handler (OSIF_PROCESS_EVENT_PROCCESS_YIELD_REQ, repaint_on_yield); 61 | 62 | while (1) { 63 | cm_process_handle_events(); 64 | } 65 | } 66 | 67 | void thread0() 68 | { 69 | OSIF_WindowFrameBufferInfo fbi = createWindow ("gui0 - Window 1"); 70 | int value = 1; 71 | int incby = 1; 72 | while (1) { 73 | triangle_sum (&value, 1, 10, &incby); 74 | 75 | for (unsigned int x = 0; x < fbi.width_px; x++) { 76 | for (unsigned int y = 0; y < fbi.height_px; y++) { 77 | UINT color = ((x) * (UINT)value & 255) << 0; 78 | graphics_putpixel (&fbi, x, y, color); 79 | } 80 | } 81 | cm_delay (50); 82 | } 83 | } 84 | 85 | void thread1() 86 | { 87 | OSIF_WindowFrameBufferInfo fbi = createWindow ("gui0 - Window 2"); 88 | int value = 10; 89 | int incby = 1; 90 | while (1) { 91 | triangle_sum (&value, 10, 20, &incby); 92 | 93 | for (unsigned int x = 0; x < fbi.width_px; x++) { 94 | for (unsigned int y = 0; y < fbi.height_px; y++) { 95 | UINT color = ((y) * (UINT)value & 255) << 16; 96 | graphics_putpixel (&fbi, x, y, color); 97 | } 98 | } 99 | cm_delay (50); 100 | } 101 | } 102 | 103 | void thread2() 104 | { 105 | OSIF_WindowFrameBufferInfo fbi = createWindow ("gui0 - Window 3"); 106 | int value = 1; 107 | int incby = 1; 108 | while (1) { 109 | triangle_sum (&value, 1, 10, &incby); 110 | 111 | for (unsigned int x = 0; x < fbi.width_px; x++) { 112 | for (unsigned int y = 0; y < fbi.height_px; y++) { 113 | UINT color = ((x + y) * (UINT)value & 255) << 8; 114 | graphics_putpixel (&fbi, x, y, color); 115 | } 116 | } 117 | cm_delay (80); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/apps/init.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------- 3 | * Megha Operating System V2 - Application - Init program 4 | * ------------------------------------------------------------------------------------------------- 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | static void init_child_killed (OSIF_ProcessEvent const* const e) 12 | { 13 | CM_DBG_INFO ("Child process exited. Code: %x", e->data); 14 | (void)e; 15 | } 16 | 17 | void proc_main() 18 | { 19 | cm_process_register_event_handler (OSIF_PROCESS_EVENT_PROCCESS_CHILD_KILLED, init_child_killed); 20 | 21 | cm_process_create (INIT_PROG, false); 22 | 23 | while (1) { 24 | cm_process_handle_events(); 25 | } 26 | 27 | // Should not return! 28 | cm_panic(); 29 | } 30 | -------------------------------------------------------------------------------- /src/apps/mpdemo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define MAX_VGA_COLUMNS 80U 8 | 9 | typedef enum DisplayVgaColors 10 | { 11 | BLACK, 12 | BLUE, 13 | GREEN, 14 | CYAN, 15 | RED, 16 | MAGENTA, 17 | BROWN, 18 | LIGHT_GRAY, 19 | DARK_GRAY, 20 | LIGHT_BLUE, 21 | LIGHT_GREEN, 22 | LIGHT_CYAN, 23 | LIGHT_RED, 24 | PINK, 25 | YELLOW, 26 | WHITE 27 | } DisplayVgaColors; 28 | 29 | bool all_child_exited = false; 30 | 31 | static void s_printString (U32 row, U32 col, U32 bgcolor, U32 fgcolor, char* text); 32 | static void s_progressbar (UINT iterPerStep, char* title, UINT row, UINT color); 33 | static void thread0(); 34 | static void thread1(); 35 | 36 | static void s_printString (U32 row, U32 col, U32 bgcolor, U32 fgcolor, char* text) 37 | { 38 | syscall (OSIF_SYSCALL_CONSOLE_SETCOLOR, bgcolor, fgcolor, 0, 0, 0); 39 | syscall (OSIF_SYSCALL_CONSOLE_SETCURSORPOS, row, col, 0, 0, 0); 40 | cm_putstr (text); 41 | } 42 | 43 | static void s_progressbar (UINT delay_ms, char* title, UINT row, UINT color) 44 | { 45 | s_printString (row, 0, BLACK, DARK_GRAY, title); 46 | 47 | UINT max = MAX_VGA_COLUMNS; 48 | 49 | for (UINT i = 0; i < max; i++) { 50 | s_printString (row + 2, i, color, DARK_GRAY, " "); 51 | cm_delay (delay_ms); 52 | } 53 | } 54 | 55 | static void count_child_exits (OSIF_ProcessEvent const* const e) 56 | { 57 | (void)e; 58 | static int count = 0; 59 | 60 | CM_DBG_INFO ("Child process exited."); 61 | if (++count == 2) { 62 | CM_DBG_INFO ("Every child process exited."); 63 | all_child_exited = true; 64 | } 65 | } 66 | 67 | static void wait_for_all_child_exit() 68 | { 69 | while (!all_child_exited) { 70 | cm_process_handle_events(); 71 | } 72 | } 73 | 74 | void proc_main() 75 | { 76 | cm_thread_create (thread0, false); 77 | cm_thread_create (thread1, false); 78 | 79 | cm_process_register_event_handler (OSIF_PROCESS_EVENT_PROCCESS_CHILD_KILLED, 80 | count_child_exits); 81 | 82 | s_progressbar (5, "Process 0:\n", 26, RED); 83 | 84 | wait_for_all_child_exit(); 85 | 86 | cm_process_kill(1); 87 | } 88 | 89 | void thread0() 90 | { 91 | s_progressbar (10, "Thread 0:\n", 30, GREEN); 92 | cm_process_kill(2); 93 | } 94 | 95 | void thread1() 96 | { 97 | s_progressbar (2, "Thread 1:\n", 34, YELLOW); 98 | cm_process_kill(3); 99 | } 100 | -------------------------------------------------------------------------------- /src/apps/proc1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void another_thread(); 5 | 6 | void proc_main() 7 | { 8 | cm_putstr("\n Process 0 - Running"); 9 | cm_putstr("\n Process 0 - Creating Thread 1"); 10 | cm_thread_create(another_thread, false); 11 | 12 | for (int i = 0; i < 2; i++) { 13 | cm_putstr("\n Process 0 - Yielding"); 14 | cm_process_yield(); 15 | cm_putstr("\n Process 0 - Running"); 16 | } 17 | 18 | cm_putstr("\n Process 0 - Exiting"); 19 | cm_process_kill(1); 20 | cm_putstr("\n Process 0 - Not exited. Its is the only one."); 21 | } 22 | 23 | void another_thread() 24 | { 25 | cm_putstr("\n Thread 1 - Running"); 26 | cm_putstr("\n Thread 1 - Yielding"); 27 | cm_process_yield(); 28 | 29 | cm_putstr("\n Thread 1 - Running"); 30 | cm_putstr("\n Thread 1 - Exiting"); 31 | cm_process_kill(2); 32 | } 33 | -------------------------------------------------------------------------------- /src/bootloader/x86/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${PROJECT_SOURCE_DIR}/cmake/${ARCH}/kernelflags.cmake) 2 | 3 | assemble_and_copy_bin( 4 | NAME boot0.flt 5 | SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/boot0/boot.s 6 | FLAGS ${MOS_KERNEL_NASM_BIN_MODE_FLAGS} 7 | DEFINITIONS ${MOS_KERNEL_GCC_DEFINITIONS} 8 | INCLUDE_DIRECTORIES 9 | ${CMAKE_CURRENT_SOURCE_DIR}/boot0 10 | ${MOS_KERNEL_ASM_INCLUDE_DIRS} 11 | ) 12 | 13 | assemble_and_copy_bin( 14 | NAME boot1.flt 15 | SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/boot1/boot1.s 16 | FLAGS ${MOS_KERNEL_NASM_BIN_MODE_FLAGS} 17 | DEFINITIONS ${MOS_KERNEL_GCC_DEFINITIONS} 18 | INCLUDE_DIRECTORIES 19 | ${CMAKE_CURRENT_SOURCE_DIR}/boot1 20 | ${MOS_KERNEL_ASM_INCLUDE_DIRS} 21 | ) 22 | 23 | #--------------------------------------------------------------------------- 24 | # Add to the global 'build-all' target 25 | #--------------------------------------------------------------------------- 26 | add_dependencies(build-all boot0.flt boot1.flt) 27 | -------------------------------------------------------------------------------- /src/bootloader/x86/boot1/a20gate.s: -------------------------------------------------------------------------------- 1 | ; 2 | ; Megha Operating System V2 - x86 A20 Routines 3 | ; --------------------------------------------------------------------------- 4 | ; This file houses routines that deals with detection and enabling of the A20 5 | ; Gate in x86 architecture. 6 | ; 7 | ; Note: The loader is a transient program, so no Interrupt routine, System 8 | ; calls must be placed in the loader. 9 | ; 10 | ; Dated: 3rd September 2020 11 | ; --------------------------------------------------------------------------- 12 | ; Change Log 13 | ; --------------------------------------------------------------------------- 14 | ; Version 20200903 15 | ; - Initial version 16 | ; --------------------------------------------------------------------------- 17 | 18 | ; Enables A20 line using FAST A20 method 19 | ; Input: None 20 | ; Output: None 21 | __enable_a20_fast: 22 | push eax 23 | in al, 0x92 24 | or al, 2 25 | out 0x92, al 26 | pop eax 27 | ret 28 | 29 | ; Enables A20 line using BIOS INT 15 routine 30 | ; Input: None 31 | ; Output: None 32 | __enable_a20gate_bios: 33 | push eax 34 | mov eax, 0x2401 35 | int 0x15 36 | pop eax 37 | ret 38 | 39 | ; If the PIN 20 (Bit 21) is disabled, then address from 40 | ; 1 0000 0000 0000 0000 - 1 1111 1111 1111 1111, has the same meaning as 41 | ; 0 0000 0000 0000 0000 - 0 1111 1111 1111 1111. 42 | ; Address 0x500 is chosen, because that address is not used by BIOS 43 | ; and not part of BDA. 44 | ; We will write byte 0x00 at location 0 0000 0000 0101 0000 0000 45 | ; and 0x01 at location 1 0000 0000 0101 0000 0000. 46 | ; When read back, if both the bytes are the same, then A20 line is disabled, 47 | ; else enabled. 48 | ; Input: 49 | ; None 50 | ; Output: 51 | ; Carry - 1 (enabled), 0 (disabled) 52 | __is_a20gate_enabled: 53 | pusha 54 | 55 | mov ax, 0xFFFF 56 | mov es, ax 57 | 58 | xor ax, ax 59 | mov ds, ax 60 | 61 | ; Need to preserve what we are overwritting. 62 | push word [ds:0x500] 63 | push word [es:0x510] 64 | 65 | ; Write word 0x0000 at 0x0000:0x500 and 66 | ; 0x0001 at 0xFFFF:0x510 67 | mov [ds:0x500], byte 0 68 | mov [es:0x510], byte 1 69 | 70 | ; Check if word written at location 0x0000:500 is still zero. 71 | cmp [ds:0x500], byte 0 72 | je .enabled 73 | 74 | .disabled: 75 | clc 76 | jmp .end 77 | .enabled: 78 | stc 79 | .end: 80 | ; Need to preserve what we are overwritting. 81 | pop word [es:0x510] 82 | pop word [ds:0x500] 83 | popa 84 | ret 85 | 86 | ; If A20 gate is not enabled, then this routine will call the different methods 87 | ; and try to enable A20 Gate. 88 | ; Input: 89 | ; None 90 | ; Output: 91 | ; Carry - 1 (A20 is enabled in the end) 92 | ; - 0 (A20 is disabled in the end) 93 | enable_a20: 94 | 95 | call __is_a20gate_enabled 96 | jc .enabled 97 | 98 | ; Method 1: BIOS method 99 | call __enable_a20gate_bios 100 | call __is_a20gate_enabled 101 | jc .enabled 102 | printString msg_failed 103 | 104 | ; Method 2: Fast Boot 105 | call __enable_a20_fast 106 | call __is_a20gate_enabled 107 | jc .enabled 108 | printString msg_failed 109 | 110 | ; Method 3: Keyboard controller 111 | 112 | ; Failed to enable 113 | .failed: 114 | clc 115 | ret 116 | 117 | .enabled: 118 | stc 119 | ret 120 | -------------------------------------------------------------------------------- /src/cm/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${PROJECT_SOURCE_DIR}/cmake/${ARCH}/kernelflags.cmake) 2 | 3 | #--------------------------------------------------------------------------- 4 | # LIBCM macro is only present when building libcm, and absent when building applications. Thus this 5 | # macro can be used by a libcm header to determine if its being included by an application or by CM 6 | # library. 7 | #--------------------------------------------------------------------------- 8 | set(MOS_LIBCM_GCC_DEFINITIONS 9 | ${MOS_KERNEL_GCC_DEFINITIONS} 10 | LIBCM 11 | ) 12 | 13 | #--------------------------------------------------------------------------- 14 | # Generate header file 15 | #--------------------------------------------------------------------------- 16 | set(LIBCM_BUILD_CONFIG_HEADER_FILE ${PROJECT_SOURCE_DIR}/include/cm/cmbuild.h) 17 | set(LIBCM_BUILD_CONFIG_HEADER_TEMPLATE_FILE ${PROJECT_SOURCE_DIR}/include/cm/cmbuild.h.in) 18 | 19 | add_custom_target(gen-build-config-header 20 | BYPRODUCTS ${LIBCM_BUILD_CONFIG_HEADER_FILE} 21 | COMMAND ${CMAKE_COMMAND} 22 | -DGenHeader=1 23 | -DDefinitions="${MOS_KERNEL_GCC_DEFINITIONS}" 24 | -DHeaderFileDestinationPath=${LIBCM_BUILD_CONFIG_HEADER_FILE} 25 | -DHeaderFileTemplatePath=${LIBCM_BUILD_CONFIG_HEADER_TEMPLATE_FILE} 26 | -P ${PROJECT_SOURCE_DIR}/cmake/GenConfigHeaderFile.cmake 27 | ) 28 | 29 | # ------------------------------------------------------------------------ 30 | # C Runtime Library for Applications 31 | # Application C Runtime is analogous to the CRT in Linux, it provides prologue & epilogue code for 32 | # application programs to run and exit gracefully. 33 | # ------------------------------------------------------------------------ 34 | set(APPS_CRT_SOURCES 35 | ${CMAKE_CURRENT_SOURCE_DIR}/${ARCH}/crta.c 36 | ) 37 | 38 | compile_lib( 39 | NAME crta 40 | SOURCES ${APPS_CRT_SOURCES} 41 | FLAGS ${MOS_KERNEL_GCC_FLAGS} 42 | DEFINITIONS ${MOS_LIBCM_GCC_DEFINITIONS} 43 | INCLUDE_DIRECTORIES ${MOS_KERNEL_GCC_INCLUDE_DIRS} 44 | ) 45 | # ------------------------------------------------------------------------ 46 | # MOS C Library 47 | # C library to talk to the OS and helpful/common functions for use by application programs. 48 | # ------------------------------------------------------------------------ 49 | 50 | set(APPLIB_SOURCES 51 | ${CMAKE_CURRENT_SOURCE_DIR}/process.c 52 | ${CMAKE_CURRENT_SOURCE_DIR}/syscalls.c 53 | ${CMAKE_CURRENT_SOURCE_DIR}/printf.c 54 | ${CMAKE_CURRENT_SOURCE_DIR}/debug.c 55 | ${CMAKE_CURRENT_SOURCE_DIR}/cm.c 56 | ${CMAKE_CURRENT_SOURCE_DIR}/string.c 57 | ${CMAKE_CURRENT_SOURCE_DIR}/malloc.c 58 | ) 59 | 60 | if (MOS_GRAPHICS_ENABLED) 61 | LIST(APPEND APPLIB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/graphics.c) 62 | endif() 63 | 64 | compile_lib( 65 | NAME cm 66 | SOURCES ${APPLIB_SOURCES} 67 | FLAGS ${MOS_KERNEL_GCC_FLAGS} 68 | DEFINITIONS ${MOS_LIBCM_GCC_DEFINITIONS} 69 | DEPENDS gen-build-config-header 70 | INCLUDE_DIRECTORIES ${MOS_KERNEL_GCC_INCLUDE_DIRS} 71 | STATIC_LIB 72 | ) 73 | 74 | target_link_libraries(cm PUBLIC gcc) 75 | # ------------------------------------------------------------------------ 76 | -------------------------------------------------------------------------------- /src/cm/cm.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------- 3 | * Megha Operating System V2 - App Library - General functions 4 | * ------------------------------------------------------------------------------------------------- 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | /* Variable to store Library error*/ 14 | uint32_t cm_error_num; 15 | 16 | #define cm_MICRODEC_TO_TICK_COUNT(us) ((us) / cm_get_tick_period_us()) 17 | 18 | /*************************************************************************************************** 19 | * Halts thread for 'ms' miliseconds 20 | * 21 | * @return Nothing 22 | **************************************************************************************************/ 23 | void cm_delay (UINT ms) 24 | { 25 | UINT us = ms * 1000; 26 | 27 | U32 start_tick = cm_get_tickcount(); 28 | U32 end_tick = start_tick + cm_MICRODEC_TO_TICK_COUNT (us); 29 | 30 | while (cm_get_tickcount() < end_tick) { 31 | cm_process_handle_events(); 32 | } 33 | } 34 | 35 | /*************************************************************************************************** 36 | * Return the last library error 37 | * 38 | * @return Last libcm error 39 | **************************************************************************************************/ 40 | uint32_t cm_get_lib_error() 41 | { 42 | return cm_error_num; 43 | } 44 | -------------------------------------------------------------------------------- /src/cm/debug.c: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - x86 Kernel - Debug console 4 | * 5 | * Uses the port 0xE9 hack to output characters to the linux Qemu console. 6 | * --------------------------------------------------------------------------- 7 | * 8 | * Dated: 8th June 2021 9 | */ 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #if defined(DEBUG) && defined(PORT_E9_ENABLED) 17 | 18 | #define MAX_PRINTABLE_STRING_LENGTH 100 19 | #define ARRAY_LENGTH(ar) (sizeof ((ar)) / sizeof ((ar)[0])) 20 | 21 | #define ANSI_COL_GRAY "\x1b[90m" 22 | #define ANSI_COL_YELLOW "\x1b[93m" 23 | #define ANSI_COL_RED "\x1b[31m" 24 | #define ANSI_COL_GREEN "\x1b[32m" 25 | #define ANSI_COL_RESET "\x1b[0m" 26 | 27 | static void qemu_putString (const CHAR* string) 28 | { 29 | CHAR c; 30 | while ((c = *string++)) { 31 | #if ARCH == x86 32 | cm_debug_x86_outb (0xE9, c); 33 | #else 34 | #error "Not implemented" 35 | #endif 36 | } 37 | } 38 | 39 | /*************************************************************************************************** 40 | * Prints log to the host console in a new line. When DEBUG is defined also prints the function name 41 | * and line number. 42 | * 43 | * @return Nothing 44 | **************************************************************************************************/ 45 | void cm_debug_log_ndu (CM_DebugLogType type, const char* func, UINT line, char* fmt, ...) 46 | { 47 | int len = 0; 48 | char buffer[MAX_PRINTABLE_STRING_LENGTH]; 49 | char* message = NULL; 50 | char* logColor = ANSI_COL_RESET; 51 | 52 | switch (type) { 53 | case CM_DEBUG_LOG_TYPE_INFO: { 54 | message = "\n %s[%u][MLC][ INFO ]%s %s:%u %s|"; 55 | logColor = ANSI_COL_GREEN; 56 | } break; 57 | case CM_DEBUG_LOG_TYPE_FUNC: { 58 | message = "\n%s[%u][MLC]%s[ %s:%u ]%s|"; 59 | logColor = ANSI_COL_YELLOW; 60 | } break; 61 | case CM_DEBUG_LOG_TYPE_ERROR: { 62 | message = "\n %s[%u][MLC][ ERROR ]%s %s:%u %s|"; 63 | logColor = ANSI_COL_RED; 64 | } break; 65 | case CM_DEBUG_LOG_TYPE_WARN: { 66 | message = "\n %s[%u][MLC][ WARN ]%s %s:%u %s|"; 67 | logColor = ANSI_COL_YELLOW; 68 | } break; 69 | } 70 | 71 | UINT tick_count = cm_get_tickcount(); 72 | len = cm_snprintf (buffer, ARRAY_LENGTH (buffer), message, logColor, tick_count, ANSI_COL_GRAY, 73 | func, line, ANSI_COL_RESET); 74 | 75 | va_list l; 76 | va_start (l, fmt); 77 | cm_vsnprintf (buffer + len, ARRAY_LENGTH (buffer), fmt, l); 78 | va_end (l); 79 | 80 | qemu_putString (buffer); 81 | } 82 | #endif // DEBUG 83 | -------------------------------------------------------------------------------- /src/cm/string.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------- 3 | * Megha Operating System V2 - App Library - String/Memory functions 4 | * ------------------------------------------------------------------------------------------------- 5 | */ 6 | 7 | #include 8 | 9 | /*************************************************************************************************** 10 | * Copies n bytes from src to dest. Can handle overlaps. 11 | * 12 | * @Input dest Pointer to the destination. Should not be NULL. 13 | * @Input src Pointer to the source. Should not be NULL. 14 | * @Input n Number of bytes to copy. 15 | * @return Pointer to the start of the destination. 16 | ***************************************************************************************************/ 17 | void* cm_memcpy (void* dest, const void* src, size_t n) 18 | { 19 | U8* cdest = (U8*)dest; 20 | U8* csrc = (U8*)src; 21 | 22 | // This handles the scenario where destination overlaps the source. 23 | cdest += n - 1; 24 | csrc += n - 1; 25 | 26 | while (n--) 27 | *cdest-- = *csrc--; 28 | 29 | return (CHAR*)dest; 30 | } 31 | 32 | /*************************************************************************************************** 33 | * Gets lenght of a NULL terminated string. 34 | * 35 | * @Input s Pointer to NULL terminated string 36 | * @return Length of the string not including the NULL character. 37 | * TODO: Make the implementation mode efficient 38 | ***************************************************************************************************/ 39 | UINT cm_strlen (const char* s) 40 | { 41 | UINT len = 0; 42 | for (; *s != '\0'; len++, s++) 43 | ; 44 | 45 | return len; 46 | } 47 | 48 | /*************************************************************************************************** 49 | * Copies at most 'n' characters from one string to another. 50 | * 51 | * @Input d Destination 52 | * @Input s Source 53 | * @Input n Number of characters (bytes) to copy from destination to source. 54 | * @return Pointer to destination 55 | ***************************************************************************************************/ 56 | char* cm_strncpy (char* d, const char* s, SIZE n) 57 | { 58 | char* dh = d; 59 | for (; n > 0 && (*d = *s) != '\0'; s++, d++, n--) 60 | ; 61 | 62 | return dh; 63 | } 64 | 65 | /*************************************************************************************************** 66 | * Fills memory with constant byte 67 | * 68 | * @Input s Pointer to the destination. Should not be NULL. 69 | * @Input c Byte to fill the destination with. 70 | * @Input n Number of bytes to fill. 71 | * @return Pointer to the start of the destination. 72 | ***************************************************************************************************/ 73 | void* cm_memset (void* const s, U8 c, size_t n) 74 | { 75 | return __builtin_memset (s, c, n); 76 | } 77 | -------------------------------------------------------------------------------- /src/cm/syscalls.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------- 3 | * Megha Operating System V2 - User Library - System calls 4 | * ------------------------------------------------------------------------------------------------- 5 | */ 6 | 7 | /* Note: 8 | * This library talks to the OS and needs to make sense of the result the OS provides. In order to 9 | * do these the library may require the configurations of the Kernel itself (for example to convert 10 | * tick count to micro seconds etc). Due to this tight coupling is between this library and the 11 | * kernel it makes sense to simply use the definations in kernel headers. However no public function 12 | * of this library should expose OS details, like data structures to application space. This library 13 | * (and its headers) whould act as the abstraction between the Kernel and the application programs. 14 | * This library should change with OS in order to shield the applications from the changes. 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | S32 syscall (OSIF_SYSCALLS fn, U32 arg1, U32 arg2, U32 arg3, U32 arg4, U32 arg5) 21 | { 22 | S32 retval = 0; 23 | __asm__ volatile("int 0x50" 24 | : "=a"(retval) // This is required. Otherwise compiler will not know that eax 25 | // will be changed after this instruction. 26 | : "a"(fn), "b"(arg1), "c"(arg2), "d"(arg3), "S"(arg4), "D"(arg5) 27 | :); 28 | return retval; 29 | } 30 | 31 | UINT cm_get_tick_period_us() 32 | { 33 | return CONFIG_TICK_PERIOD_MICROSEC; 34 | } 35 | -------------------------------------------------------------------------------- /src/cm/x86/crta.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------- 3 | * Megha Operating System V2 - User Library - Application Prologue 4 | * ------------------------------------------------------------------------------------------------- 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | // This is the entry point for all application processes. 13 | __attribute__ ((section (".entry.text"))) 14 | void proc_start() 15 | { 16 | __asm__("call proc_main;"); 17 | while (1) 18 | ; 19 | } 20 | -------------------------------------------------------------------------------- /src/kernel/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${PROJECT_SOURCE_DIR}/cmake/${ARCH}/kernelflags.cmake) 2 | 3 | #--------------------------------------------------------------------------- 4 | # Build Arch independent kernel 5 | #--------------------------------------------------------------------------- 6 | set(KERNEL_SOURCES 7 | ${CMAKE_CURRENT_SOURCE_DIR}/kpanic.c 8 | ${CMAKE_CURRENT_SOURCE_DIR}/kmalloc.c 9 | ${CMAKE_CURRENT_SOURCE_DIR}/kstdlib.c 10 | ${CMAKE_CURRENT_SOURCE_DIR}/pmm.c 11 | ${CMAKE_CURRENT_SOURCE_DIR}/printk.c 12 | ${CMAKE_CURRENT_SOURCE_DIR}/salloc.c 13 | ${CMAKE_CURRENT_SOURCE_DIR}/vmm.c 14 | ${CMAKE_CURRENT_SOURCE_DIR}/handle.c 15 | ${CMAKE_CURRENT_SOURCE_DIR}/bitmap.c 16 | ) 17 | 18 | if (MOS_GRAPHICS_ENABLED) 19 | LIST(APPEND KERNEL_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/kgraphics.c) 20 | LIST(APPEND KERNEL_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/compositor.c) 21 | endif() 22 | 23 | if (MOS_BUILD_MODE STREQUAL "DEBUG") 24 | LIST(APPEND KERNEL_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/printk.c) 25 | if (MOS_PORT_E9_ENABLED) 26 | LIST(APPEND KERNEL_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/kdebug.c) 27 | endif() 28 | endif() 29 | 30 | compile_lib( 31 | NAME kernel 32 | SOURCES ${KERNEL_SOURCES} 33 | FLAGS ${MOS_KERNEL_GCC_FLAGS} 34 | DEFINITIONS ${MOS_KERNEL_GCC_DEFINITIONS} 35 | INCLUDE_DIRECTORIES ${MOS_KERNEL_GCC_INCLUDE_DIRS} 36 | ) 37 | 38 | #--------------------------------------------------------------------------- 39 | # Build Arch dependent kernel & drivers 40 | #--------------------------------------------------------------------------- 41 | add_subdirectory(${ARCH}) 42 | add_subdirectory(drivers/${ARCH}/${MARCH}) 43 | 44 | set(KERNEL_RESOURCE_FILES) 45 | 46 | #--------------------------------------------------------------------------- 47 | # Link the kernel 48 | #--------------------------------------------------------------------------- 49 | if (MOS_GRAPHICS_ENABLED) 50 | list (APPEND KERNEL_RESOURCE_FILES ${PROJECT_SOURCE_DIR}/docs/images/mos.rbm) 51 | endif() 52 | 53 | link( 54 | FLATTEN 55 | NAME kernel.flt 56 | DEPENDS 57 | kernel 58 | kernel_entry 59 | kernel_X86 60 | kernel_drivers 61 | RESOURCES ${KERNEL_RESOURCE_FILES} 62 | FLAGS ${MOS_LINKER_OPTIONS} 63 | LINKER_FILE ${MOS_KERNEL_LINKER_SCRIPT_FILE} 64 | LINK_LIBRARIES gcc 65 | ) 66 | 67 | #--------------------------------------------------------------------------- 68 | # Add to the global 'build-all' target 69 | #--------------------------------------------------------------------------- 70 | add_dependencies(build-all kernel.flt) 71 | -------------------------------------------------------------------------------- /src/kernel/drivers/x86/pc/8254_pit.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------- 3 | * Megha Operating System V2 - x86, PC Kernel - 8254 PIT dirver 4 | * 5 | * Note: 6 | * - Channel 1 cannot be programmed 7 | * - Mode 2 and 3 are the only ones that are supported 8 | * - Read-Back and 2 bytes for programming is the only mode R/W mode supported. 9 | * ------------------------------------------------------------------------------------------------- 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define COUNTER0_PORT 0x40 20 | #define COUNTER2_PORT 0x42 21 | #define CONTROLWORD_PORT 0x43 22 | 23 | #define CONTROLWORD_RW_TWO_BYTES (3U) 24 | 25 | #define CONTROLWORD(cntr, rw, mode) (((cntr) << 6U) | ((rw) << 4U) | ((mode) << 1U)) 26 | 27 | #define CONTROLWORD_READBACK_COMMAND (3U) 28 | #define READBACK(cntr) ((CONTROLWORD_READBACK_COMMAND << 6U) | (1 << ((cntr + 1)))) 29 | #define READBACK_STATUS_MODE_MASK (0xEU) 30 | 31 | void pit_set_counter (PITCounters cntr, PITCounterModes mode, U16 value) 32 | { 33 | FUNC_ENTRY ("counter: %x, mode: %x, value: %x", cntr, mode, value); 34 | 35 | k_assert (cntr == PIT_COUNTER_0 || cntr == PIT_COUNTER_2, "Invalid counter"); 36 | k_assert (mode == PIT_COUNTER_MODE_2 || mode == PIT_COUNTER_MODE_3, "Invalid counter"); 37 | 38 | UINT port = (cntr == PIT_COUNTER_0) ? COUNTER0_PORT : COUNTER2_PORT; 39 | U8 byteLow = (value & 0xFFU), byteHigh = ((value >> 8U) & 0xFFU); 40 | 41 | // Write control word 42 | UINT cw = CONTROLWORD (cntr, CONTROLWORD_RW_TWO_BYTES, mode); 43 | outb (CONTROLWORD_PORT, cw); 44 | // Write initial count 45 | outb (port, byteLow); 46 | outb (port, byteHigh); 47 | } 48 | 49 | void pit_get_counter (PITCounters cntr, U8* status, U16* value) 50 | { 51 | FUNC_ENTRY ("counter: %x, status: %px, value: %px", cntr, status, value); 52 | 53 | k_assert (status != NULL && value != NULL, "Invalid input"); 54 | k_assert (cntr == PIT_COUNTER_0 || cntr == PIT_COUNTER_2, "Invalid counter"); 55 | UINT port = (cntr == PIT_COUNTER_0) ? COUNTER0_PORT : COUNTER2_PORT; 56 | 57 | //// Send controlword readback command 58 | UINT cw = READBACK (cntr); 59 | outb (CONTROLWORD_PORT, cw); 60 | 61 | //// First byte is the status 62 | U8 byteLow, byteHigh; 63 | inb (port, *status); 64 | inb (port, byteLow); 65 | inb (port, byteHigh); 66 | 67 | *value = (U16)((byteHigh << 8U) | byteLow); 68 | } 69 | 70 | void pit_get_interrupt_counter (PITCounterModes* mode, U16* value) 71 | { 72 | FUNC_ENTRY ("mode: %px, value: %px", mode, value); 73 | 74 | U8 status; 75 | pit_get_counter (PIT_COUNTER_0, &status, value); 76 | *mode = (status & READBACK_STATUS_MODE_MASK) >> 1; 77 | } 78 | -------------------------------------------------------------------------------- /src/kernel/drivers/x86/pc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${PROJECT_SOURCE_DIR}/cmake/${ARCH}/kernelflags.cmake) 2 | 3 | set(DRIVER_SOUCES 4 | ${CMAKE_CURRENT_SOURCE_DIR}/8259_pic.c 5 | ${CMAKE_CURRENT_SOURCE_DIR}/8254_pit.c 6 | ${CMAKE_CURRENT_SOURCE_DIR}/8042_ps2.c 7 | ${CMAKE_CURRENT_SOURCE_DIR}/ps2kb.c 8 | ${CMAKE_CURRENT_SOURCE_DIR}/ps2mouse.c 9 | ${CMAKE_CURRENT_SOURCE_DIR}/pcspeaker.c 10 | ) 11 | 12 | compile_lib( 13 | NAME kernel_drivers 14 | SOURCES ${DRIVER_SOUCES} 15 | FLAGS ${MOS_KERNEL_GCC_FLAGS} 16 | DEFINITIONS ${MOS_KERNEL_GCC_DEFINITIONS} 17 | INCLUDE_DIRECTORIES ${MOS_KERNEL_GCC_INCLUDE_DIRS} 18 | ) 19 | -------------------------------------------------------------------------------- /src/kernel/drivers/x86/pc/pcspeaker.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------- 3 | * Megha Operating System V2 - x86, PC Kernel - PC Speaker 4 | * ------------------------------------------------------------------------------------------------- 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | void pcspeaker_set_freq (UINT freq) 14 | { 15 | FUNC_ENTRY ("frequency Hz: %x", freq); 16 | pit_set_speaker_counter (freq); 17 | } 18 | 19 | void pcspeaker_turnon() 20 | { 21 | FUNC_ENTRY(); 22 | 23 | U8 data = ps2_no_wait_read (PS2_SPEAKER_PORT); 24 | data |= 3U; 25 | ps2_wait_write (PS2_SPEAKER_PORT, data); 26 | } 27 | 28 | void pcspeaker_turnoff() 29 | { 30 | FUNC_ENTRY(); 31 | U8 data = ps2_no_wait_read (PS2_SPEAKER_PORT); 32 | data |= 3U; 33 | ps2_wait_write (PS2_SPEAKER_PORT, data); 34 | } 35 | -------------------------------------------------------------------------------- /src/kernel/drivers/x86/pc/ps2kb.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------- 3 | * Megha Operating System V2 - x86, PC Kernel - PS/2 Keyboard Driver 4 | * ------------------------------------------------------------------------------------------------- 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | void kb_interrupt_asm_handler(); 19 | 20 | static bool iskeyboard() 21 | { 22 | INT type = 0; 23 | if ((type = ps2_identify_device (PS2_FIRST_DEVICE)) < 0) { 24 | RETURN_ERROR (ERROR_PASSTHROUGH, false); 25 | } 26 | 27 | switch (type) { 28 | case 0x83AB: 29 | case 0x41AB: 30 | case 0xC1AB: 31 | case 0x84AB: 32 | case 0x54AB: 33 | // Valid keyboard identity. Continue 34 | break; 35 | default: 36 | RETURN_ERROR (ERR_DEVICE_INIT_FAILED, false); 37 | } 38 | return true; 39 | } 40 | 41 | bool ps2_kb_init() 42 | { 43 | FUNC_ENTRY(); 44 | 45 | // Disable Keyboard IRQ before the initialization is complete 46 | pic_enable_disable_irq (PIC_IRQ_KEYBOARD, false); 47 | 48 | // Check if PS2 port1 is Keyboard. 49 | if (!iskeyboard()) { 50 | RETURN_ERROR (ERROR_PASSTHROUGH, false); 51 | } 52 | 53 | // Set defaults 54 | if (!ps2_write_device_data_wait_ack (PS2_FIRST_DEVICE, PS2_DEV_CMD_SET_TO_DEFAULT)) { 55 | RETURN_ERROR (ERROR_PASSTHROUGH, false); 56 | } 57 | 58 | // Interrupt when keys are pressed 59 | if (!ps2_write_device_data_wait_ack (PS2_FIRST_DEVICE, PS2_DEV_CMD_ENABLE_SCANNING)) { 60 | RETURN_ERROR (ERROR_PASSTHROUGH, false); 61 | } 62 | 63 | // Setup PS2 configuration to enable interrupts from port 1 and disable translation 64 | ps2_configuration (PS2_CONFIG_FIRST_PORT_INTERRUPT_ENABLE | 65 | PS2_CONFIG_FIRST_PORT_TRANSLATION_ENABLE, 66 | 0, NULL); 67 | 68 | // Add handlers for keyboard interrupts 69 | kidt_edit (0x21, kb_interrupt_asm_handler, GDT_SELECTOR_KCODE, IDT_DES_TYPE_32_INTERRUPT_GATE, 70 | 0); 71 | 72 | // Enable Keyboard IRQ 73 | pic_enable_disable_irq (PIC_IRQ_KEYBOARD, true); 74 | 75 | return true; 76 | } 77 | 78 | INTERRUPT_HANDLER (kb_interrupt) 79 | void kb_interrupt_handler (InterruptFrame* frame) 80 | { 81 | (void)frame; 82 | 83 | #if defined(DEBUG) 84 | U8 scancode = (U8)ps2_no_wait_read (PS2_DATA_PORT); 85 | kearly_println ("Keyboard ISR: Scancode: %x", scancode); 86 | #endif 87 | pic_send_eoi (PIC_IRQ_KEYBOARD); 88 | } 89 | -------------------------------------------------------------------------------- /src/kernel/handle.c: -------------------------------------------------------------------------------- 1 | /* 2 | * -------------------------------------------------------------------------------------------------- 3 | * Megha Operating System V2 - Cross Platform Kernel - Kernel Object Handle management 4 | * 5 | * Handles identify objects in the kernel and can safely be passed to applications as well. 6 | * -------------------------------------------------------------------------------------------------- 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | static void** handles = NULL; 20 | 21 | static void** getObjectPtr (Handle h) 22 | { 23 | k_assert (handles != NULL, "Handles not initialized"); 24 | 25 | if (h >= CONFIG_HANDLES_ARRAY_ITEM_COUNT) { 26 | RETURN_ERROR (ERR_INVALID_HANDLE, NULL); 27 | } 28 | 29 | if (handles[h] == NULL) { 30 | RETURN_ERROR (ERR_INVALID_HANDLE, NULL); 31 | } 32 | 33 | return &handles[h]; 34 | } 35 | 36 | void khandle_init() 37 | { 38 | FUNC_ENTRY(); 39 | 40 | KERNEL_PHASE_VALIDATE (KERNEL_PHASE_STATE_SALLOC_READY); 41 | if (!(handles = kscalloc (CONFIG_HANDLES_ARRAY_ITEM_COUNT * sizeof (handles)))) { 42 | FATAL_BUG(); // Should not fail. 43 | } 44 | } 45 | 46 | Handle khandle_createHandle (void* obj) 47 | { 48 | FUNC_ENTRY ("Object ptr: %px", obj); 49 | 50 | k_assert (handles != NULL, "Handles not initialized"); 51 | 52 | if (obj == NULL) { 53 | RETURN_ERROR (ERR_INVALID_ARGUMENT, INVALID_HANDLE); 54 | } 55 | 56 | // Find free location 57 | for (INT i = 0; i < CONFIG_HANDLES_ARRAY_ITEM_COUNT; i++) { 58 | if (handles[i] == NULL) { 59 | // Found a free slot in the handles array. Place the object ptr there. 60 | handles[i] = obj; 61 | // The index into the Handles array where the object was put is the Handle for it. 62 | return i; 63 | } 64 | } 65 | 66 | // No free slot found. 67 | RETURN_ERROR (ERR_OUT_OF_MEM, INVALID_HANDLE); 68 | } 69 | 70 | bool khandle_freeHandle (Handle h) 71 | { 72 | FUNC_ENTRY ("Handle: %x", h); 73 | 74 | void** objptr = getObjectPtr (h); 75 | if (objptr == NULL) { 76 | RETURN_ERROR (ERROR_PASSTHROUGH, false); 77 | } 78 | *objptr = NULL; 79 | return true; 80 | } 81 | 82 | void* khandle_getObject (Handle h) 83 | { 84 | FUNC_ENTRY ("Handle: %x", h); 85 | 86 | void** objptr = getObjectPtr (h); 87 | if (objptr == NULL) { 88 | RETURN_ERROR (ERROR_PASSTHROUGH, false); 89 | } 90 | return *objptr; 91 | } 92 | -------------------------------------------------------------------------------- /src/kernel/kdebug.c: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - Cross Platform Kernel - Debug console 4 | * 5 | * Uses the port 0xE9 hack to output characters to the linux Qemu console. 6 | * --------------------------------------------------------------------------- 7 | */ 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #if ARCH == x86 14 | #include 15 | #endif 16 | 17 | #define ANSI_COL_GRAY "\x1b[90m" 18 | #define ANSI_COL_YELLOW "\x1b[93m" 19 | #define ANSI_COL_RED "\x1b[31m" 20 | #define ANSI_COL_GREEN "\x1b[32m" 21 | #define ANSI_COL_RESET "\x1b[0m" 22 | 23 | #if defined(DEBUG) && defined(PORT_E9_ENABLED) 24 | static void s_qemu_debugPutString (const CHAR* string) 25 | { 26 | CHAR c; 27 | while ((c = *string++)) 28 | outb (0xE9, c); 29 | } 30 | 31 | /*************************************************************************************************** 32 | * Prints log to the host console in a new line. When DEBUG is defined also prints the function name 33 | * and line number. 34 | * 35 | * @return Nothing 36 | **************************************************************************************************/ 37 | void kdebug_log_ndu (KernelDebugLogType type, const char* func, UINT line, char* fmt, ...) 38 | { 39 | int len = 0; 40 | char buffer[MAX_PRINTABLE_STRING_LENGTH]; 41 | char* message = NULL; 42 | char* logColor = ANSI_COL_RESET; 43 | 44 | switch (type) { 45 | case KDEBUG_LOG_TYPE_INFO: { 46 | message = "\n %s[%u][ INFO ]%s %s:%u %s|"; 47 | logColor = ANSI_COL_GREEN; 48 | } break; 49 | case KDEBUG_LOG_TYPE_FUNC: { 50 | message = "\n%s[%u]%s[ %s:%u ]%s|"; 51 | logColor = ANSI_COL_YELLOW; 52 | } break; 53 | case KDEBUG_LOG_TYPE_ERROR: { 54 | message = "\n %s[%u][ ERROR ]%s %s:%u %s|"; 55 | logColor = ANSI_COL_RED; 56 | } break; 57 | case KDEBUG_LOG_TYPE_WARN: { 58 | message = "\n %s[%u][ WARN ]%s %s:%u %s|"; 59 | logColor = ANSI_COL_YELLOW; 60 | } break; 61 | } 62 | 63 | len = kearly_snprintf (buffer, ARRAY_LENGTH (buffer), message, logColor, g_kstate.tick_count, 64 | ANSI_COL_GRAY, func, line, ANSI_COL_RESET); 65 | 66 | va_list l; 67 | va_start (l, fmt); 68 | kearly_vsnprintf (buffer + len, ARRAY_LENGTH (buffer), fmt, l); 69 | va_end (l); 70 | 71 | s_qemu_debugPutString (buffer); 72 | } 73 | #endif // DEBUG && PORT_E9_ENABLED 74 | -------------------------------------------------------------------------------- /src/kernel/kpanic.c: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - Cross Platform Kernel - Panic 4 | * --------------------------------------------------------------------------- 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #ifdef GRAPHICS_MODE_ENABLED 15 | #include 16 | #include 17 | #endif 18 | 19 | static void arch_dump_call_trace (PTR* raddrs, INT count); 20 | #ifdef GRAPHICS_MODE_ENABLED 21 | static void kpanic_gx_ui (const char* buffer); 22 | #endif 23 | 24 | #ifdef GRAPHICS_MODE_ENABLED 25 | static void kpanic_gx_ui (const char* buffer) 26 | { 27 | if (KERNEL_PHASE_CHECK (KERNEL_PHASE_STATE_GRAPHICS_READY)) { 28 | KGraphicsArea* ga = (KGraphicsArea*)&g_kstate.gx_hwfb; 29 | kgraphics_rect (ga, 0, 0, ga->width_px, ga->height_px, COLOR_BG_BSOD); 30 | kgraphics_drawstring (ga, 0, 0, buffer, COLOR_WHITE, COLOR_BG_BSOD); 31 | } else { 32 | // This has to be a failure very early on. 33 | // Not sure what can we do here!! 34 | } 35 | } 36 | #endif 37 | 38 | void kpanic_ndu (UINT line, const CHAR* file, const CHAR* fmt, ...) 39 | { 40 | CHAR buffer[MAX_PRINTABLE_STRING_LENGTH]; 41 | va_list l; 42 | 43 | PTR raddrs[CONFIG_MAX_CALL_TRACE_DEPTH] = { 0 }; 44 | arch_dump_call_trace (raddrs, ARRAY_LENGTH (raddrs)); 45 | 46 | INT len = 0; 47 | 48 | len = kearly_snprintf (buffer, ARRAY_LENGTH (buffer), "\n\nKernel Panic:"); 49 | len += kearly_snprintf (buffer + len, ARRAY_LENGTH (buffer), "\nAt: %s: %u", file, line); 50 | len += kearly_snprintf (buffer + len, ARRAY_LENGTH (buffer), "\nKernel error: %x\n\n", 51 | g_kstate.errorNumber); 52 | 53 | va_start (l, fmt); 54 | len += kearly_vsnprintf (buffer + len, ARRAY_LENGTH (buffer), fmt, l); 55 | va_end (l); 56 | 57 | len += kearly_snprintf (buffer + len, ARRAY_LENGTH (buffer), "\n\nCall stack:\n-"); 58 | for (UINT i = 0; i < ARRAY_LENGTH (raddrs) && raddrs[i] > 0; i++) { 59 | len += kearly_snprintf (buffer + len, ARRAY_LENGTH (buffer), " %x", raddrs[i]); 60 | } 61 | len += kearly_snprintf (buffer + len, ARRAY_LENGTH (buffer), "\n------------\n"); 62 | 63 | #ifdef GRAPHICS_MODE_ENABLED 64 | kpanic_gx_ui (buffer); 65 | #endif 66 | 67 | #ifdef DEBUG 68 | ERROR ("%s", buffer); 69 | kearly_printf (buffer); 70 | #endif 71 | 72 | k_halt(); 73 | } 74 | 75 | #if ARCH == x86 76 | // Would be present for every CPU arch 77 | static void arch_dump_call_trace (PTR* raddrs, INT count) 78 | { 79 | typedef struct stack_frame { 80 | struct stack_frame* ebp; 81 | unsigned int eip; 82 | } stack_frame; 83 | 84 | stack_frame* frame; 85 | __asm__ volatile("mov %0, ebp;" : "=m"(frame)); 86 | 87 | for (; count && frame->ebp; count--, frame = frame->ebp) 88 | *(raddrs++) = frame->eip; 89 | } 90 | #endif 91 | -------------------------------------------------------------------------------- /src/kernel/x86/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${PROJECT_SOURCE_DIR}/cmake/${ARCH}/kernelflags.cmake) 2 | 3 | set(KERNEL_X86_SOURCES 4 | ${CMAKE_CURRENT_SOURCE_DIR}/boot.c 5 | ${CMAKE_CURRENT_SOURCE_DIR}/gdt.c 6 | ${CMAKE_CURRENT_SOURCE_DIR}/idt.c 7 | ${CMAKE_CURRENT_SOURCE_DIR}/interrupts.c 8 | ${CMAKE_CURRENT_SOURCE_DIR}/kernel.c 9 | ${CMAKE_CURRENT_SOURCE_DIR}/paging.c 10 | ${CMAKE_CURRENT_SOURCE_DIR}/pmm.c 11 | ${CMAKE_CURRENT_SOURCE_DIR}/process.c 12 | ${CMAKE_CURRENT_SOURCE_DIR}/syscalls.c 13 | ${CMAKE_CURRENT_SOURCE_DIR}/tss.c 14 | ) 15 | 16 | if (MOS_BUILD_MODE STREQUAL "DEBUG" AND NOT MOS_GRAPHICS_ENABLED) 17 | LIST(APPEND KERNEL_X86_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/vgatext.c) 18 | endif() 19 | 20 | compile_lib( 21 | NAME kernel_X86 22 | SOURCES ${KERNEL_X86_SOURCES} 23 | FLAGS ${MOS_KERNEL_GCC_FLAGS} 24 | DEFINITIONS ${MOS_KERNEL_GCC_DEFINITIONS} 25 | INCLUDE_DIRECTORIES ${MOS_KERNEL_GCC_INCLUDE_DIRS} 26 | ) 27 | 28 | compile_lib( 29 | NAME kernel_entry 30 | SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/entry.s 31 | FLAGS ${MOS_KERNEL_NASM_ELF_MODE_FLAGS} 32 | DEFINITIONS ${MOS_KERNEL_GCC_DEFINITIONS} 33 | INCLUDE_DIRECTORIES ${MOS_KERNEL_ASM_INCLUDE_DIRS} 34 | ) 35 | -------------------------------------------------------------------------------- /src/kernel/x86/_gas_paging.s: -------------------------------------------------------------------------------- 1 | /* 2 | * Megha Operating System V2 - x86 Kernel - Paging 3 | * --------------------------------------------------------------------------- 4 | * Paging structure initialization and setting up of Higher-half kernel. 5 | * 6 | * Dated: 18th December 2020 7 | * --------------------------------------------------------------------------- 8 | * Change Log 9 | * --------------------------------------------------------------------------- 10 | * Build - 20201218 11 | * - Intiial version. Identity paging implementation 12 | * --------------------------------------------------------------------------- 13 | */ 14 | .global __kernel_entry 15 | .extern __kernel_main 16 | .global __page_dir 17 | .global __page_table 18 | 19 | .section .before_paging 20 | .section .bss, "aw", @nobits 21 | 22 | .align 4096 23 | __page_dir: 24 | .skip 4096 25 | __page_table: 26 | .skip 4096 27 | 28 | .section .text 29 | __kernel_entry: 30 | call fill_pd 31 | call fill_pt 32 | 33 | mov eax, __page_dir 34 | xchg bx, bx 35 | and eax, 0xFFFFF000 //0b11111111_11111111_11110000_00000000 36 | mov cr3, eax 37 | 38 | mov eax, cr4 39 | and eax, 0xFFFFFFEF //0b11111111_11111111_11111111_11101111 40 | mov cr4, eax 41 | 42 | mov eax, cr0 43 | or eax, 0x80000000 44 | mov cr0, eax 45 | 46 | xchg bx, bx 47 | 48 | jmp __kernel_main 49 | hlt 50 | 51 | fill_pd: 52 | pushad 53 | mov edi, __page_dir 54 | mov eax, __page_table 55 | and eax, 0xFFFFF000 //0b11111111_11111111_11110000_00000000 56 | or eax, 7 57 | mov [edi],eax 58 | popad 59 | ret 60 | 61 | fill_pt: 62 | pushad 63 | mov edi, __page_table 64 | mov eax, 0 65 | mov ecx, 4096 /*__page_table.size*/ 66 | .write_next_pte: 67 | push eax 68 | and eax, 0xFFFFF000 //0b11111111_11111111_11110000_00000000 69 | or eax, 7 70 | mov [edi],eax 71 | pop eax 72 | add edi, 4 73 | add eax, 4096 74 | loop .write_next_pte 75 | popad 76 | ret 77 | .section .after_paging 78 | -------------------------------------------------------------------------------- /src/kernel/x86/boot.c: -------------------------------------------------------------------------------- 1 | /* 2 | * -------------------------------------------------------------------------------------------------- 3 | * Megha Operating System V2 - x86 Kernel - Methods to access structures passed by the bootloader. 4 | * -------------------------------------------------------------------------------------------------- 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | static BootLoaderInfo* kboot_getCurrentBootLoaderInfo() 14 | { 15 | k_assert (MEM_START_BOOT_INFO, "BOOT INFO LOCATION is invalid"); 16 | BootLoaderInfo* mi = (BootLoaderInfo*)MEM_START_BOOT_INFO; 17 | return mi; 18 | } 19 | 20 | static void convert_to_f12_filename (const char* fn, char* out) 21 | { 22 | int di = 0; 23 | for (char c = *fn; c != '\0' && di < 11; di++, c = *(++fn)) { 24 | if (c == '.') { 25 | for (; di < 8; di++) { 26 | *out++ = ' '; 27 | } 28 | di--; 29 | } else { 30 | *out++ = c; 31 | } 32 | } 33 | 34 | while (di++ < 11) { 35 | *out++ = ' '; 36 | } 37 | } 38 | 39 | U16 kboot_getBootFileItemCount() 40 | { 41 | return kboot_getCurrentBootLoaderInfo()->filecount; 42 | } 43 | 44 | BootFileItem kboot_getBootFileItem (INT index) 45 | { 46 | BootLoaderInfo* bli = kboot_getCurrentBootLoaderInfo(); 47 | k_assert (index >= 0, "Index Invalid"); 48 | k_assert (index < bli->filecount, "Index invalid"); 49 | 50 | return bli->files[index]; 51 | } 52 | 53 | BootFileItem kboot_findBootFileItem (const CHAR* const filename) 54 | { 55 | CHAR fat12FileName[CONFIG_BOOT_FILENAME_LEN_CHARS] = { 0 }; 56 | convert_to_f12_filename (filename, fat12FileName); 57 | k_assert (k_strlen (fat12FileName) == 11, "Invalid file name"); 58 | 59 | const BootFileItem* bfi = NULL; 60 | BootLoaderInfo* bli = kboot_getCurrentBootLoaderInfo(); 61 | for (int i = 0; i < bli->filecount; i++) { 62 | bfi = &bli->files[i]; 63 | if (k_memcmp (bfi->name, fat12FileName, CONFIG_BOOT_FILENAME_LEN_CHARS)) { 64 | return *bfi; 65 | } 66 | } 67 | k_assert (false, "Invalid file name"); 68 | NORETURN(); 69 | } 70 | 71 | U16 kboot_getBootMemoryMapItemCount() 72 | { 73 | return kboot_getCurrentBootLoaderInfo()->count; 74 | } 75 | 76 | BootMemoryMapItem kboot_getBootMemoryMapItem (INT index) 77 | { 78 | BootLoaderInfo* bli = kboot_getCurrentBootLoaderInfo(); 79 | 80 | k_assert (index >= 0, "Index Invalid"); 81 | k_assert (index < bli->count, "Index invalid"); 82 | 83 | return bli->items[index]; 84 | } 85 | 86 | ULLONG kboot_calculateInstalledMemory() 87 | { 88 | BootLoaderInfo* bli = kboot_getCurrentBootLoaderInfo(); 89 | 90 | INT mapCount = bli->count; 91 | U64 length_bytes = 0; 92 | 93 | for (INT i = 0; i < mapCount; i++) 94 | length_bytes += bli->items[i].length; 95 | 96 | return length_bytes; 97 | } 98 | 99 | BootGraphicsModeInfo kboot_getGraphicsModeInfo() 100 | { 101 | return kboot_getCurrentBootLoaderInfo()->gxInfo; 102 | } 103 | 104 | const U8* kboot_getFontData() 105 | { 106 | return kboot_getCurrentBootLoaderInfo()->font_data; 107 | } 108 | -------------------------------------------------------------------------------- /src/kernel/x86/gdt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - x86 Kernel - GDT 4 | * 5 | * The GDT will reside in the kernel space and will be represented by the 6 | * structure. 7 | * --------------------------------------------------------------------------- 8 | * Dated: 6th October 2020 9 | ; --------------------------------------------------------------------------- 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | /* -------------------------------------------------------------------------*/ 22 | /* Variables */ 23 | static volatile GdtDescriptor *s_gdt; 24 | static U16 s_gdt_count = MIN_GDT_INDEX; 25 | /* -------------------------------------------------------------------------*/ 26 | 27 | /* -------------------------------------------------------------------------*/ 28 | /* Function definations */ 29 | 30 | /* Writes the GDT structure address and length to the GDTR register. */ 31 | void 32 | kgdt_write () 33 | { 34 | FUNC_ENTRY(); 35 | 36 | volatile GdtMeta gdt_size_and_loc = 37 | { 38 | .size = (U16)(sizeof (GdtDescriptor) * s_gdt_count - 1), 39 | .location = (U32)s_gdt 40 | }; 41 | 42 | INFO ("GDT {size = %x, location = %x}", gdt_size_and_loc.size, gdt_size_and_loc.location); 43 | 44 | // NOTE: No need to load the SS, DS, ES or CS registers, as it already 45 | // contains the values needs (from boo1) 46 | __asm__ ( "lgdt [%0]" 47 | : 48 | :"a" (&gdt_size_and_loc)); 49 | } 50 | 51 | /* Edits a GDT descriptor in the GDT table. 52 | * Note: If gdt_index < 3 or > s_gdt_count or > GDT_MAX_COUNT then an panic is 53 | * generated. 54 | */ 55 | void 56 | kgdt_edit (U16 gdt_index, 57 | U32 base, 58 | U32 limit, 59 | U8 access, 60 | U8 flags) 61 | { 62 | FUNC_ENTRY ("index: %x, base: %x, limit: %x, access: %x, flags: %x", gdt_index, base, 63 | limit, access, flags); 64 | 65 | k_staticAssert(sizeof(GdtDescriptor) * MAX_GDT_DESC_COUNT <= MEM_LEN_BYTES_GDT); 66 | 67 | s_gdt = (GdtDescriptor *)MEM_START_GDT; 68 | 69 | // Valid range is MIN_INDEX < index < s_gdt_count < GDT_MAX_COUNT 70 | if (!(gdt_index >= MIN_GDT_INDEX && 71 | gdt_index <= s_gdt_count && 72 | gdt_index <= MAX_GDT_DESC_COUNT)) 73 | k_panic ("Invalid gdt_index: %u",gdt_index); 74 | 75 | s_gdt[gdt_index].limit_low = limit & 0xFFFF; 76 | s_gdt[gdt_index].limit_high = (limit >> 16) & 0xF; 77 | s_gdt[gdt_index].base_low = base & 0xFFFF; 78 | s_gdt[gdt_index].base_middle = (U8)(base >> 16) & 0xFF; 79 | s_gdt[gdt_index].base_high = (U8)(base >> 24) & 0xFF; 80 | s_gdt[gdt_index].access = access; 81 | s_gdt[gdt_index].flags = (U8)(flags & 0xF); 82 | 83 | // Check if a new GDT entry has been added or an old one is editted. 84 | // On next kgdt_write, gdtr.size will be increase. 85 | if (gdt_index == s_gdt_count) 86 | s_gdt_count++; 87 | } 88 | /* -------------------------------------------------------------------------*/ 89 | -------------------------------------------------------------------------------- /src/kernel/x86/idt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - x86 Kernel - IDT 4 | * 5 | * The IDT will reside in the kernel space and will be represented by the 6 | * structure. 7 | * --------------------------------------------------------------------------- 8 | * Dated: 27th November 2020 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | /* -------------------------------------------------------------------------*/ 19 | /* Variables */ 20 | 21 | #define IDT_BYTES sizeof(IdtDescriptor) * MAX_IDT_DESC_COUNT 22 | static IdtDescriptor *s_idt; 23 | /* -------------------------------------------------------------------------*/ 24 | 25 | /* -------------------------------------------------------------------------*/ 26 | /* Local Function */ 27 | static void s_idt_write (); 28 | /* -------------------------------------------------------------------------*/ 29 | 30 | /* Set all bytes to zero, for all the 256 IDT entries */ 31 | void 32 | kidt_init () 33 | { 34 | FUNC_ENTRY(); 35 | 36 | k_staticAssert(IDT_BYTES <= MEM_LEN_BYTES_IDT); 37 | 38 | s_idt = (IdtDescriptor *)MEM_START_IDT; 39 | k_memset ((void *)s_idt, 0, IDT_BYTES); 40 | s_idt_write (); 41 | } 42 | 43 | /* Edits an IDT descriptor */ 44 | void 45 | kidt_edit (INT index, 46 | void (*func)(), 47 | U16 seg_selector, 48 | IDTDescriptorTypes type, 49 | U8 dpl) 50 | { 51 | FUNC_ENTRY ("index: %x, func: %px, seg_sel: %x, type: %x, dpl: %x", index, func, 52 | seg_selector, type, dpl); 53 | 54 | U32 offset = (U32)func; 55 | 56 | s_idt[index].offset_low = offset & 0xFFFF; 57 | s_idt[index].offset_high = (U16)(offset >> 16) & 0xFFFF; 58 | s_idt[index].segment_selector = seg_selector; 59 | s_idt[index].type = type; 60 | s_idt[index].dpl = (U8)(dpl & 0x3); 61 | s_idt[index].p = 1; 62 | s_idt[index].zeros = 0; 63 | } 64 | 65 | /* Writes the IDT structure address and length to the IDTR register. */ 66 | static void 67 | s_idt_write () 68 | { 69 | volatile IdtMeta idt_size_and_loc = 70 | { 71 | .limit = IDT_BYTES - 1, 72 | .location = (U32)s_idt 73 | }; 74 | 75 | INFO ("IDT {limit = %x, location = %x}", idt_size_and_loc.limit, idt_size_and_loc.location); 76 | 77 | __asm__ ( "lidt [%0]" 78 | : 79 | :"a" (&idt_size_and_loc)); 80 | } 81 | -------------------------------------------------------------------------------- /src/kernel/x86/kernel.ld: -------------------------------------------------------------------------------- 1 | 2 | SECTIONS 3 | { 4 | . = 0x100000; /* Kernel is loaded at 100000 */ 5 | .prepage.text : 6 | { 7 | *(.prepage.text); 8 | } 9 | . += 0xC0000000; 10 | 11 | .text : AT( ADDR(.text) - 0xC0000000) 12 | { 13 | *(.text); 14 | } 15 | .data : ALIGN(8) 16 | { 17 | *(.data); 18 | 19 | . = ALIGN(8); 20 | *(.rodata*); 21 | 22 | . = ALIGN(8); 23 | *(.bss); 24 | *(COMMON); 25 | } 26 | 27 | /DISCARD/ : 28 | { 29 | *(.eh_frame); 30 | *(.comment); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/kernel/x86/process.ld: -------------------------------------------------------------------------------- 1 | 2 | SECTIONS 3 | { 4 | . = 0x00010000; 5 | 6 | .text : ALIGN(8) 7 | { 8 | /* '.entry.text' section must be at the top. 9 | * _start must have the address 0x00010000. */ 10 | KEEP(*(.entry.text)); 11 | *(.entry.text); 12 | *(.text); 13 | } 14 | .data : ALIGN(8) 15 | { 16 | *(.data); 17 | 18 | . = ALIGN(8); 19 | *(.rodata*); 20 | 21 | . = ALIGN(8); 22 | *(.bss); 23 | *(COMMON); 24 | } 25 | 26 | /DISCARD/ : 27 | { 28 | *(.eh_frame); 29 | *(.comment); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/kernel/x86/tss.c: -------------------------------------------------------------------------------- 1 | /* 2 | * --------------------------------------------------------------------------- 3 | * Megha Operating System V2 - x86 Kernel - TSS structure 4 | * 5 | * This is a test kernel to demostrate that the 'boot1' loader can actually load 6 | * the kernel and jump to it. 7 | * On successful execution, 'Kernel ready..' will be displayed on the top of the 8 | * screen. 9 | * --------------------------------------------------------------------------- 10 | * 11 | * Dated: 20th September 2020 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #define IOMAP_SIZE 0x100 // Covers VGA ports and normal IO ports. 24 | 25 | struct tss { 26 | U32 prevtask; 27 | U32 esp0; 28 | U32 ss0; 29 | U32 esp1; 30 | U32 ss1; 31 | U32 esp2; 32 | U32 ss2; 33 | U32 cr3; 34 | U32 eip; 35 | U32 eflags; 36 | U32 eax; 37 | U32 ecx; 38 | U32 edx; 39 | U32 ebx; 40 | U32 esp; 41 | U32 ebp; 42 | U32 esi; 43 | U32 edi; 44 | U32 es; 45 | U32 cs; 46 | U32 ss; 47 | U32 ds; 48 | U32 fs; 49 | U32 gs; 50 | U32 ldt_seg; 51 | U16 trap; 52 | U16 iomap_base; 53 | U32 ssp; 54 | U8 iomap[IOMAP_SIZE]; 55 | } __attribute__ ((packed)); 56 | 57 | static struct tss *tss_entry = NULL; 58 | 59 | /* Initializes the tss_entry structure, 60 | * installs a tss segment in GDT and writes to the Task Register*/ 61 | void ktss_init () 62 | { 63 | FUNC_ENTRY(); 64 | 65 | if ((tss_entry = ksalloc(sizeof(struct tss))) == NULL) 66 | { 67 | k_panic("Memory allocation failed for TSS"); 68 | } 69 | 70 | // Deny permissions to all IO ports by setting all the bits 71 | k_memset (tss_entry->iomap, 0xFF, IOMAP_SIZE - 1); 72 | tss_entry->iomap[29] &=0xFD; // E9 Debug port 73 | tss_entry->iomap[122] &=0xcf; // VGA 3D4 and 3D5 ports 74 | 75 | // IOMAP area determines the io port permissions when CPL > IOPL. 76 | // If the corresponding bit is set, access to that port is denied. 77 | // iomap area starts at an offset from the start of tss. 78 | // In ourcase it starts right at the end of tss_entry. 79 | tss_entry->iomap_base = offsetOf (struct tss,iomap); 80 | // Setup defaults to TSS, so that we can return to kernel mode. 81 | // Setup a proper place for the kernel stack. This is the location the 82 | // ESP will have when returning to kernel mode from user mode. On a cross 83 | // privilate level INT instruction, the stack will have the 84 | // user mode CS, EIP, EFLAGS, SS, ESP. 85 | tss_entry->ss0 = GDT_SELECTOR_KDATA; 86 | tss_entry->esp0 = MEM_KSTACK_TOP; 87 | 88 | // Install a TSS Segment 89 | kgdt_edit (GDT_INDEX_KTSS, 90 | (U32)tss_entry, // Base in the Physical Linear space. 91 | sizeof (struct tss) -1, // Size of the Segemnt = sizeof (tss)-1 92 | 0xE9, 0x1); // DPL = 3, Scaling is not required. 93 | kgdt_write (); 94 | 95 | // Write to TS register 96 | // The Busy word will get set to indicate that it is the task that is 97 | // running at the point. 98 | U16 tss_seg_selector = GDT_SELECTOR_KTSS; 99 | __asm__ volatile ("ltr %0;" 100 | : /* no output */ 101 | : "m" (tss_seg_selector)); 102 | } 103 | -------------------------------------------------------------------------------- /src/mock/cm/cm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | DEFINE_FUNC (void*, cm_memset, void*, U8, size_t); 5 | DEFINE_FUNC (char*, cm_strncpy, char*, const char*, size_t); 6 | DEFINE_FUNC (S32, syscall, U32, U32, U32, U32, U32, U32); 7 | 8 | void resetCMFake() 9 | { 10 | RESET_FAKE(cm_memset); 11 | RESET_FAKE(cm_strncpy); 12 | RESET_FAKE(syscall); 13 | } 14 | -------------------------------------------------------------------------------- /src/mock/kernel/bitmap.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | DEFINE_FUNC(BitmapState, bitmap_get, Bitmap*, UINT); 5 | DEFINE_FUNC(bool, bitmap_setContinous, Bitmap *, UINT, UINT, BitmapState); 6 | DEFINE_FUNC(INT, bitmap_findContinous, Bitmap *, BitmapState, UINT); 7 | DEFINE_FUNC(bool, bitmap_findContinousAt, Bitmap *, BitmapState, UINT, UINT); 8 | 9 | void resetBitmapFake() 10 | { 11 | RESET_FAKE(bitmap_get); 12 | RESET_FAKE(bitmap_setContinous); 13 | RESET_FAKE(bitmap_findContinous); 14 | RESET_FAKE(bitmap_findContinousAt); 15 | } 16 | -------------------------------------------------------------------------------- /src/mock/kernel/kstdlib.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | DEFINE_FUNC(void *, k_memcpy, void *, const void *, size_t); 5 | DEFINE_FUNC(void *, k_memset, void *, U8, size_t); 6 | 7 | void resetStdLibFake() 8 | { 9 | RESET_FAKE(k_memcpy); 10 | RESET_FAKE(k_memset); 11 | } 12 | -------------------------------------------------------------------------------- /src/mock/kernel/paging.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | DEFINE_FUNC (void *, kpg_temporaryMap, Physical); 5 | DEFINE_FUNC_VOID (kpg_temporaryUnmap); 6 | 7 | void resetPagingFake() 8 | { 9 | RESET_FAKE (kpg_temporaryMap); 10 | RESET_FAKE (kpg_temporaryUnmap); 11 | } 12 | -------------------------------------------------------------------------------- /src/mock/kernel/pmm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | DEFINE_FUNC_VOID(kpmm_init); 5 | DEFINE_FUNC(bool, kpmm_free, Physical, UINT); 6 | DEFINE_FUNC(bool, kpmm_alloc, Physical*, UINT, KernelPhysicalMemoryRegions); 7 | DEFINE_FUNC(bool, kpmm_allocAt, Physical, UINT, KernelPhysicalMemoryRegions); 8 | DEFINE_FUNC(size_t, kpmm_getFreeMemorySize); 9 | DEFINE_FUNC(USYSINT, kpmm_getUsableMemorySize, KernelPhysicalMemoryRegions); 10 | 11 | void resetPmm() 12 | { 13 | RESET_FAKE(kpmm_init); 14 | RESET_FAKE(kpmm_free); 15 | RESET_FAKE(kpmm_alloc); 16 | RESET_FAKE(kpmm_allocAt); 17 | RESET_FAKE(kpmm_getFreeMemorySize); 18 | RESET_FAKE(kpmm_getUsableMemorySize); 19 | } 20 | -------------------------------------------------------------------------------- /src/mock/kernel/salloc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | DEFINE_FUNC(void*, ksalloc,UINT); 5 | DEFINE_FUNC(void*, kscalloc,UINT); 6 | void reset_sallocFake() 7 | { 8 | RESET_FAKE(ksalloc); 9 | RESET_FAKE(kscalloc); 10 | } 11 | -------------------------------------------------------------------------------- /src/mock/kernel/vmm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | DEFINE_FUNC (PTR, kvmm_memmap, VMemoryManager* , PTR , Physical const* const, SIZE, 5 | VMemoryMemMapFlags , Physical* const ); 6 | 7 | void resetVMMFake() 8 | { 9 | RESET_FAKE(kvmm_memmap); 10 | } 11 | -------------------------------------------------------------------------------- /src/mock/kernel/x86/boot.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | DEFINE_FUNC (U16,kboot_getBootFileItemCount); 5 | DEFINE_FUNC (BootFileItem,kboot_getBootFileItem, INT); 6 | DEFINE_FUNC (BootMemoryMapItem,kboot_getBootMemoryMapItem, INT); 7 | DEFINE_FUNC (U16,kboot_getBootMemoryMapItemCount); 8 | DEFINE_FUNC (ULLONG,kboot_calculateInstalledMemory); 9 | DEFINE_FUNC (BootGraphicsModeInfo,kboot_getGraphicsModeInfo); 10 | 11 | void resetBootFake() 12 | { 13 | RESET_FAKE (kboot_getBootFileItemCount); 14 | RESET_FAKE (kboot_getBootFileItem); 15 | RESET_FAKE (kboot_getBootMemoryMapItem); 16 | RESET_FAKE (kboot_getBootMemoryMapItemCount); 17 | RESET_FAKE (kboot_calculateInstalledMemory); 18 | RESET_FAKE (kboot_getGraphicsModeInfo); 19 | } 20 | -------------------------------------------------------------------------------- /src/mock/kernel/x86/paging.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | DEFINE_FUNC (ArchPageDirectoryEntry *, s_getPdeFromCurrentPd, UINT); 5 | DEFINE_FUNC (ArchPageTableEntry *, s_getPteFromCurrentPd, UINT); 6 | DEFINE_FUNC (void *, s_getLinearAddress, UINT, UINT, UINT); 7 | 8 | void resetPagingFake() 9 | { 10 | RESET_FAKE (s_getPteFromCurrentPd); 11 | RESET_FAKE (s_getPdeFromCurrentPd); 12 | RESET_FAKE (s_getLinearAddress); 13 | } 14 | -------------------------------------------------------------------------------- /src/mock/kernel/x86/pmm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | DEFINE_FUNC_VOID(kpmm_arch_init, Bitmap *); 5 | DEFINE_FUNC(U64, kpmm_arch_getInstalledMemoryByteCount); 6 | 7 | void resetX86Pmm() 8 | { 9 | RESET_FAKE(kpmm_arch_init); 10 | RESET_FAKE(kpmm_arch_getInstalledMemoryByteCount); 11 | } 12 | -------------------------------------------------------------------------------- /src/mock/kernel/x86/vgatext.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | DEFINE_FUNC_VOID(kdisp_putc, CHAR); 5 | DEFINE_FUNC_VOID(kdisp_scrollDown); 6 | DEFINE_FUNC_VOID(kdisp_init); 7 | 8 | /* kdisp_ioctl has a veridac parameter. There is no way to define such a 9 | * function in fake.h*/ 10 | 11 | void resetVgaDisp() 12 | { 13 | RESET_FAKE(kdisp_putc); 14 | RESET_FAKE(kdisp_scrollDown); 15 | RESET_FAKE(kdisp_init); 16 | } 17 | -------------------------------------------------------------------------------- /src/mock/mockfortests_x86.cmake: -------------------------------------------------------------------------------- 1 | 2 | set(pmm_mock_sources 3 | ${PROJECT_SOURCE_DIR}/src/mock/kernel/x86/pmm.c 4 | ) 5 | 6 | set(kmalloc_mock_sources 7 | ${PROJECT_SOURCE_DIR}/src/mock/kernel/vmm.c 8 | ${PROJECT_SOURCE_DIR}/src/mock/kernel/kstdlib.c 9 | ) 10 | 11 | set(salloc_mock_sources 12 | ${PROJECT_SOURCE_DIR}/src/mock/kernel/kstdlib.c 13 | ) 14 | 15 | set(kstdlib_mock_sources 16 | ${PROJECT_SOURCE_DIR}/src/mock/kernel/paging.c 17 | ) 18 | 19 | set(handles_mock_sources 20 | ${PROJECT_SOURCE_DIR}/src/mock/kernel/salloc.c 21 | ) 22 | 23 | set(cm_malloc_mock_sources 24 | ${PROJECT_SOURCE_DIR}/src/mock/cm/cm.c 25 | ) 26 | -------------------------------------------------------------------------------- /src/unittests/cm/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${PROJECT_SOURCE_DIR}/src/mock/mockfortests_${ARCH}.cmake) 2 | 3 | test( 4 | NAME cm_printf_test 5 | DEPENDENT_FOR build-all 6 | DEFINITIONS LIBCM 7 | SOURCES 8 | ${PROJECT_SOURCE_DIR}/src/cm/printf.c 9 | ${PROJECT_SOURCE_DIR}/src/unittests/unittest.c 10 | ${CMAKE_CURRENT_SOURCE_DIR}/printf_test.c 11 | ) 12 | 13 | test( 14 | NAME cm_string_test 15 | DEPENDENT_FOR build-all 16 | DEFINITIONS LIBCM 17 | SOURCES 18 | ${PROJECT_SOURCE_DIR}/src/cm/string.c 19 | ${PROJECT_SOURCE_DIR}/src/unittests/unittest.c 20 | ${CMAKE_CURRENT_SOURCE_DIR}/string_test.c 21 | ) 22 | 23 | test( 24 | NAME cm_malloc_test 25 | DEPENDENT_FOR build-all 26 | DEFINITIONS LIBCM 27 | SOURCES 28 | ${PROJECT_SOURCE_DIR}/src/cm/malloc.c 29 | ${CMAKE_CURRENT_SOURCE_DIR}/malloc_test.c 30 | ${PROJECT_SOURCE_DIR}/src/unittests/unittest.c 31 | ${CMAKE_CURRENT_SOURCE_DIR}/common.c 32 | ${cm_malloc_mock_sources} 33 | ) 34 | -------------------------------------------------------------------------------- /src/unittests/cm/common.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ---------------------------------------------------------------------------- 3 | * Common functions to for use in MeghaOS LibCM unitests 4 | * ---------------------------------------------------------------------------- 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | /* MOS Unittest Macro mock global structure */ 15 | MockedMacro g_utmm = { 0 }; 16 | 17 | /* Error number */ 18 | uint32_t cm_error_num; 19 | 20 | /* Panic handler */ 21 | bool cm_panic_invoked; 22 | void cm_unittest_panic_handler() 23 | { 24 | cm_panic_invoked = true; 25 | } 26 | -------------------------------------------------------------------------------- /src/unittests/cm/malloc_test.c: -------------------------------------------------------------------------------- 1 | ../kernel/kmalloc_test.c -------------------------------------------------------------------------------- /src/unittests/cm/printf_test.c: -------------------------------------------------------------------------------- 1 | ../kernel/printk_test.c -------------------------------------------------------------------------------- /src/unittests/cm/string_test.c: -------------------------------------------------------------------------------- 1 | ../kernel/kstdlib_test.c -------------------------------------------------------------------------------- /src/unittests/kernel/c99_conformance_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | TEST(types.h, size_t_conformance) 5 | { 6 | /* Required because: 7 | * 1. kearly_vsnprintf casts difference of two size_t to an INT.*/ 8 | EQ_SCALAR(sizeof(size_t), sizeof(INT)); 9 | 10 | /* Required because: 11 | * 1. According to C99 standard, size_t must be atleast the size of long int. */ 12 | GEQ_SCALAR(sizeof(size_t), sizeof(LONG)); 13 | END(); 14 | } 15 | 16 | TEST(types.h, type_sizes) 17 | { 18 | EQ_SCALAR(sizeof(U8), 1); 19 | EQ_SCALAR(sizeof(U16), 2); 20 | EQ_SCALAR(sizeof(U32), 4); 21 | EQ_SCALAR(sizeof(U64), 8); 22 | 23 | EQ_SCALAR(sizeof(S32), 4); 24 | EQ_SCALAR(sizeof(S64), 8); 25 | 26 | END(); 27 | } 28 | 29 | void reset() 30 | { 31 | } 32 | 33 | int main() 34 | { 35 | type_sizes(); 36 | size_t_conformance(); 37 | } 38 | -------------------------------------------------------------------------------- /src/unittests/kernel/common.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ---------------------------------------------------------------------------- 3 | * Common functions to for use in MeghaOS unitests 4 | * ---------------------------------------------------------------------------- 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | /* MOS Unittest Macro mock global structure */ 15 | MockedMacro g_utmm = { 0 }; 16 | 17 | /* Panic handler */ 18 | volatile KernelStateInfo g_kstate; 19 | bool panic_invoked; 20 | void unittest_panic_handler(const CHAR *s,...) 21 | { 22 | panic_invoked = true; 23 | 24 | va_list l; 25 | va_start (l, s); 26 | 27 | printf ("%s", COL_GRAY); 28 | vprintf (s, l); 29 | printf ("%s", COL_RESET); 30 | 31 | va_end(l); 32 | } 33 | -------------------------------------------------------------------------------- /src/unittests/kernel/paging_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | TEST (paging, pageframe_to_physical) { 5 | EQ_SCALAR(PAGEFRAME_TO_PHYSICAL(0x3), 0x3 * CONFIG_PAGE_FRAME_SIZE_BYTES); 6 | EQ_SCALAR(PAGEFRAME_TO_PHYSICAL(0x0), 0x0); 7 | END(); 8 | } 9 | 10 | TEST (paging, physical_to_pageframe) { 11 | EQ_SCALAR(PHYSICAL_TO_PAGEFRAME(0x0), 0x0); 12 | EQ_SCALAR(PHYSICAL_TO_PAGEFRAME(4 * CONFIG_PAGE_FRAME_SIZE_BYTES), 0x4); 13 | END(); 14 | } 15 | 16 | void reset() { 17 | } 18 | 19 | int main() { 20 | pageframe_to_physical(); 21 | physical_to_pageframe(); 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /src/unittests/kernel/x86/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | test( 3 | NAME pmm_x86_test 4 | DEPENDENT_FOR build-all 5 | SOURCES 6 | ${PROJECT_SOURCE_DIR}/src/kernel/x86/pmm.c 7 | ${CMAKE_CURRENT_SOURCE_DIR}/pmm_test.c 8 | ${COMMON_KERNEL_UT_SOURCE_FILES} 9 | # Mock sources 10 | ${PROJECT_SOURCE_DIR}/src/mock/kernel/kstdlib.c 11 | ${PROJECT_SOURCE_DIR}/src/mock/kernel/bitmap.c 12 | ${PROJECT_SOURCE_DIR}/src/mock/kernel/pmm.c 13 | ${PROJECT_SOURCE_DIR}/src/mock/kernel/x86/boot.c 14 | ) 15 | 16 | test( 17 | NAME paging_x86_test 18 | DEPENDENT_FOR build-all 19 | SOURCES 20 | ${PROJECT_SOURCE_DIR}/src/kernel/x86/paging.c 21 | ${CMAKE_CURRENT_SOURCE_DIR}/paging_test.c 22 | ${COMMON_KERNEL_UT_SOURCE_FILES} 23 | # Mock sources 24 | ${PROJECT_SOURCE_DIR}/src/mock/kernel/kstdlib.c 25 | ${PROJECT_SOURCE_DIR}/src/mock/kernel/pmm.c 26 | ${PROJECT_SOURCE_DIR}/src/mock/kernel/x86/paging.c 27 | ) 28 | -------------------------------------------------------------------------------- /src/unittests/kernel/x86/pmm_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | TEST(PMM, actual_accessable_ram) 8 | { 9 | kboot_calculateInstalledMemory_fake.ret = 5 * MB; 10 | size_t available_ram = kpmm_arch_getInstalledMemoryByteCount(); 11 | EQ_SCALAR (available_ram, 5 * MB); 12 | 13 | kboot_calculateInstalledMemory_fake.ret = 16 * GB; 14 | available_ram = kpmm_arch_getInstalledMemoryByteCount(); 15 | EQ_SCALAR (available_ram, 16 * GB); 16 | 17 | END(); 18 | } 19 | 20 | void reset() 21 | { 22 | resetBootFake(); 23 | } 24 | 25 | int main() 26 | { 27 | actual_accessable_ram(); 28 | } 29 | -------------------------------------------------------------------------------- /src/unittests/unittest.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ---------------------------------------------------------------------------- 3 | * Functions for equality and negation checks. 4 | * 5 | * Author: arjobmukherjee@gmail.com (Arjob Mukherjee) 6 | * Dated : 26 April 2022 7 | * ---------------------------------------------------------------------------- 8 | */ 9 | #include 10 | #include 11 | 12 | typedef uint8_t byte; 13 | 14 | int ut_equal_string (const char *a, const char *b, int *i) 15 | { 16 | *i = 0; 17 | while (*a && *b && *a == *b) { 18 | a++; 19 | b++; 20 | (*i)++; 21 | } 22 | 23 | return *a == *b; 24 | } 25 | 26 | int ut_equal_mem (const void *a, const void *b, unsigned long size, int *i) 27 | { 28 | *i = 0; 29 | while (size-- && *(byte *)a++ == *(byte *)b++) 30 | (*i)++ ; 31 | 32 | return *(byte *)--a == *(byte *)--b; 33 | } 34 | -------------------------------------------------------------------------------- /tools/build_i686_gcc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # :: Constants :: 4 | BINUTILS_VER='2.35.1' 5 | GCC_VER='10.2.0' 6 | 7 | if [ "$1" == "--gen-id" ]; then 8 | # :: Generate ID (a constant string) to be used in GitHub Actions :: 9 | # This ID would change when we are targetting a different binutils or GCC 10 | # version. 11 | 12 | # The UNIQUE_ID can be used to force change the ID when the rest remains the 13 | # same. 14 | UNIQUE_ID="1" 15 | echo "binutils_${BINUTILS_VER}_gcc_${GCC_VER}-${UNIQUE_ID}" 16 | exit 17 | elif [ "$1" == "--install-dep" ]; then 18 | # :: gcc and make and other dependencies :: 19 | apt-get install -y build-essential || exit 1 20 | apt-get install -y bison flex libgmp3-dev \ 21 | libmpc-dev libmpfr-dev texinfo || exit 1 22 | echo "Dependencies installed. Run script again." 23 | exit 24 | fi 25 | 26 | # :: Download binutils and gcc :: 27 | wget https://ftp.gnu.org/gnu/binutils/binutils-$BINUTILS_VER.tar.xz \ 28 | https://ftp.gnu.org/gnu/gcc/gcc-$GCC_VER/gcc-$GCC_VER.tar.xz || exit 1 29 | 30 | # :: Extract :: 31 | tar -xf ./binutils-$BINUTILS_VER.tar.xz || exit 1 32 | tar -xf ./gcc-$GCC_VER.tar.xz || exit 1 33 | 34 | # :: Building and Installation :: 35 | if [ -z "$PREFIX" ]; then 36 | export PREFIX="$HOME/.local/opt/i686-cross" 37 | fi 38 | export TARGET=i686-elf 39 | export PATH="$PREFIX/bin:$PATH" 40 | 41 | # :: Build and install binutls :: 42 | mkdir build-binutils || exit 1 43 | pushd build-binutils 44 | ../binutils-$BINUTILS_VER/configure --target=$TARGET --prefix="$PREFIX" --with-sysroot \ 45 | --disable-nls --disable-werror || exit 1 46 | make -j4 || exit 1 47 | make install || exit 1 48 | popd 49 | 50 | # :: Build and install gcc :: 51 | # The $PREFIX/bin dir _must_ be in the PATH. We did that above. 52 | which -- $TARGET-as || echo $TARGET-as is not in the PATH 53 | 54 | mkdir build-gcc || exit 1 55 | pushd build-gcc 56 | ../gcc-$GCC_VER/configure --target=$TARGET --prefix="$PREFIX" --disable-nls \ 57 | --enable-languages=c,c++ --without-headers || exit 1 58 | make all-gcc -j4 || exit 1 59 | make all-target-libgcc -j4 || exit 1 60 | make install-gcc || exit 1 61 | make install-target-libgcc || exit 1 62 | popd 63 | 64 | # :: Cleanup :: 65 | rm -rf build-gcc 66 | rm -rf build-binutils 67 | rm -rf binutils-$BINUTILS_VER* 68 | rm -rf gcc-$GCC_VER* 69 | 70 | echo "Installation at $PREFIX complete" 71 | # :: Done :: 72 | -------------------------------------------------------------------------------- /tools/indent.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | pushd ~/meghaos-v2/ 4 | 5 | # -------------------------------------------------------------------------- 6 | # Space before every ( 7 | # Note however this rule, does not apply to macro definations. 8 | # There should be no space between macro name and '('. This will be fixed 9 | # later in the 'fix'. 10 | # --------------------------------------------------------------------------- 11 | E="\(\w\)\((\)/\1\ (" 12 | find -type f \( -name "*.c" -o -name "*.h" \) \ 13 | -exec sed -i "s/$E/g" {} \; 14 | 15 | # ---- Appy Fix for Macros 16 | # There should be no space between macro name and '('. 17 | # '#define macro (..)' fixed to 'define macro(..)' 18 | 19 | E="\(\W*#\W*define\W\+\w\+\)\ (/\1(" 20 | find -type f \( -name "*.c" -o -name "*.h" \) \ 21 | -exec sed -i "s/$E/g" {} \; 22 | # ---- 23 | 24 | # -------------------------------------------------------------------------- 25 | # Space around binary and ternary operators. 26 | # `= + - < > * / % | & ^ <= >= == != ? :` 27 | # --------------------------------------------------------------------------- 28 | 29 | # Operators `= + - < > % | & ^ <= >= == != ? :` 30 | AR=("= + - < > % | & ^ <= >= == != ? :") 31 | for op in ${AR[@]}; do 32 | E="\(\w\)\($op\)\(\w\)/\1\ \2\ \3" 33 | find -type f \( -name "*.c" -o -name "*.h" \) \ 34 | -exec sed -i "s/${E}/g" {} \; 35 | done 36 | 37 | # Operators `*` 38 | E="\(\w\)\(*\)\(\w\)/\1\ \2\ \3" 39 | find -type f \( -name "*.c" -o -name "*.h" \) \ 40 | -exec sed -i "s/$E/g" {} \; 41 | 42 | # ---- Appy Fix for (%x, %llx -> % x, % llx) 43 | E="\(%\ \)\(x\|llx\)/%\2" 44 | find -type f \( -name "*.c" -o -name "*.h" \) \ 45 | -exec sed -i "s/$E/g" {} \; 46 | # ---- 47 | # -------------------------------------------------------------------------- 48 | popd 49 | -------------------------------------------------------------------------------- /tools/toolchain-i686-elf-pc.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_SYSTEM_NAME Generic) 2 | set(CMAKE_SYSTEM_PROCESSOR i686) 3 | 4 | set(ARCH x86) 5 | set(MARCH pc) 6 | 7 | set(CMAKE_C_COMPILER i686-elf-gcc) 8 | 9 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 10 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 11 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 12 | set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) 13 | --------------------------------------------------------------------------------