├── .gitignore ├── .gitmodules ├── LICENSE ├── Makefile ├── README.md ├── bochs ├── kernel ├── config.inc ├── data.asm ├── driver │ ├── ps2.asm │ ├── ps2.inc │ ├── rtc.asm │ ├── rtc.inc │ ├── serial.asm │ └── serial.inc ├── exec.asm ├── exec.inc ├── gdt.inc ├── idt.asm ├── idt.inc ├── init.asm ├── init │ ├── acpi.asm │ ├── acpi.inc │ ├── ap.asm │ ├── ap.inc │ ├── cmd.asm │ ├── daemon.asm │ ├── data.asm │ ├── environment.asm │ ├── exec.asm │ ├── free.asm │ ├── gdt.asm │ ├── idt.asm │ ├── ipc.asm │ ├── library.asm │ ├── limine.asm │ ├── limine.inc │ ├── memory.asm │ ├── page.asm │ ├── smp.asm │ ├── storage.asm │ ├── stream.asm │ ├── task.asm │ └── vfs.asm ├── io_apic.asm ├── io_apic.inc ├── ipc.inc ├── lapic.asm ├── lapic.inc ├── library.asm ├── library.inc ├── log.asm ├── memory.asm ├── page.asm ├── page.inc ├── service.asm ├── storage.asm ├── storage.inc ├── stream.asm ├── stream.inc ├── syscall.asm ├── task.asm ├── task.inc └── tss.inc ├── library ├── elf.asm ├── elf.inc ├── macro.inc ├── std.inc ├── string │ ├── compare.asm │ ├── length.asm │ └── word.asm ├── sys.asm ├── sys.inc ├── vfs.asm └── vfs.inc ├── make ├── qemu └── tools ├── bochs.rc ├── configure.sh ├── kernel.ld ├── limine.conf └── linux.bxrc /.gitignore: -------------------------------------------------------------------------------- 1 | *.ini 2 | serial.log 3 | iso 4 | build 5 | limine 6 | vfs 7 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "limine"] 2 | path = limine 3 | url = https://github.com/limine-bootloader/limine 4 | [submodule "fern-night"] 5 | path = fern-night 6 | url = https://github.com/corruptedbycpu/fern-night 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) Blackdev.org by Andrzej Adamczyk 2 | 3 | You are allowed to: 4 | 5 | Share — official binaries and source code. The licensor cannot revoke these freedoms as long as you follow the license terms. 6 | 7 | Under the following terms: 8 | 9 | Attribution — You must give appropriate credit, provide a link to the license. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. 10 | 11 | No Commercial — You may not use the binaries or source code for commercial purposes. 12 | 13 | No Derivatives — If you modify the binaries or source code, you may not distribute the modified version. 14 | 15 | No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. 16 | 17 | **THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.** -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #================================================================================= 2 | # Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | #================================================================================= 4 | 5 | Foton: 6 | @ ./make || true -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Info 2 | 3 | Cyjon is fully compatible with ![Fern-Night](https://github.com/CorruptedByCPU/Fern-Night/). Any modification to either repository will be reflected in the other. 4 | 5 | Every comment, label is now in English. 6 | 7 | Old version of Cyjon is still available at **[old 0.1440](https://github.com/CorruptedByCPU/Cyjon/tree/old)** branch and **[eldest 0.674](https://github.com/CorruptedByCPU/Cyjon/tree/eldest)** branch. 8 | 9 | # Cyjon v0.2165 (workname) 10 | 11 | A simple, clean, multi-tasking operating system written in pure assembly (kernel) language for 64-bit processors from the AMD64 family. 12 | 13 | ![Cyjon 0.2128](https://blackdev.org/shot/2128.png?) 14 | 15 | ## Hey! 16 | 17 | So... the code is optimized for readability, not speed. 18 | 19 | ### Software (if you want to build and run your own ISO): 20 | 21 | - qemu-system-x86_64 22 | - nasm 23 | - ld.lld 24 | - xorriso 25 | 26 | ### Compilation/Exec (GNU/Linux): 27 | 28 | user@hostname ~ $ make 29 | user@hostname ~ $ ./qemu -------------------------------------------------------------------------------- /bochs: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #================================================================================= 3 | # Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 4 | #================================================================================= 5 | 6 | # default CPU count: 2 7 | SMP="${1}" 8 | if [ -z "${SMP}" ]; then SMP="2"; fi 9 | 10 | # default Memory amount: 64 MiB 11 | MEM="${2}" 12 | if [ -z "${MEM}" ]; then MEM="64"; fi 13 | 14 | # generate Bochs configuration file 15 | cp -f tools/linux.bxrc build/linux.bxrc 16 | sed -e "s|SMP|${SMP}|g" -i build/linux.bxrc 17 | sed -e "s|MEM|${MEM}|g" -i build/linux.bxrc 18 | 19 | # start Bochs Debugger with predefinied configuration file 20 | /opt/bochs-dbg/bin/bochs -f build/linux.bxrc -q -rc tools/bochs.rc 21 | 22 | # show debug output 23 | cat serial.log 24 | -------------------------------------------------------------------------------- /kernel/config.inc: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | %define KERNEL_name "Cyjon" 6 | %define KERNEL_version "0" 7 | %define KERNEL_revision "2167" 8 | %define KERNEL_architecture "x86_64" 9 | %define KERNEL_language "Assembly" 10 | 11 | %define KERNEL_BASE_address 0xFFFFFFFF80000000 ; higher half 12 | 13 | %define KERNEL_STACK_page 2 14 | %define KERNEL_STACK_address -(KERNEL_STACK_page << STD_SHIFT_PAGE) ; minimal size 15 | %define KERNEL_STACK_pointer 0xFFFFFFFFFFFFF000 16 | 17 | %ifndef KERNEL_GDT 18 | %include "./kernel/gdt.inc" 19 | %endif 20 | 21 | %ifndef KERNEL_TSS 22 | %include "./kernel/tss.inc" 23 | %endif 24 | 25 | %ifndef KERNEL_IDT 26 | %include "./kernel/idt.inc" 27 | %endif 28 | 29 | struc KERNEL 30 | ; variables of Kernel management functions 31 | .cpu_count resq 1 32 | 33 | ; variables of Input devices 34 | .device_mouse_status resb 1 35 | .device_mouse_x resw 1 36 | .device_mouse_y resw 1 37 | .device_keyboard resw 8 ; cache size of 8 keys 38 | 39 | ; variables of Framebuffer management functions 40 | .framebuffer_base_address resq 1 41 | .framebuffer_width_pixel resw 1 42 | .framebuffer_height_pixel resw 1 43 | .framebuffer_pitch_byte resd 1 44 | .framebuffer_pid resq 1 45 | 46 | ; variables of GDT management functions 47 | .gdt_header resb KERNEL_STRUCTURE_GDT_HEADER.SIZE 48 | 49 | ; variables of IDT management functions 50 | .idt_header resb KERNEL_STRUCTURE_IDT_HEADER.SIZE 51 | ; functions of IDT management 52 | .idt_mount resq 1 53 | 54 | ; variables of I/O APIC management functions 55 | .io_apic_base_address resq 1 56 | .io_apic_irq_lines resd 1 57 | .io_apic_semaphore resb 1 58 | 59 | ; variables of IPC management functions 60 | .ipc_base_address resq 1 61 | .ipc_semaphore resb 1 62 | 63 | ; variables of LAPIC management functions 64 | .lapic_base_address resq 1 65 | .lapic_last_id resd 1 66 | 67 | ; variables of Library management functions 68 | .library_base_address resq 1 69 | .library_memory_map_address resq 1 70 | 71 | ; pointers of Log management functions 72 | .log resq 1 73 | 74 | ; variables of Memory management functions 75 | .memory_base_address resq 1 76 | .memory_semaphore resb 1 77 | ; pointers of Memory management functions 78 | .memory_release resq 1 79 | 80 | ; variables of Page management functions 81 | .page_base_address resq 1 82 | .page_total resq 1 83 | .page_available resq 1 84 | .page_limit resq 1 85 | .page_array resq 1 86 | ; pointers of Page management functions 87 | .page_deconstruction resq 1 88 | 89 | ; variables of Storage management functions 90 | .storage_base_address resq 1 91 | .storage_root_id resb 1 92 | .storage_semaphore resb 1 93 | 94 | ; variables of Stream management functions 95 | .stream_base_address resq 1 96 | .stream_semaphore resb 1 97 | ; pointers of Stream management functions 98 | .stream_release resq 1 99 | 100 | ; variables of Task management functions 101 | .task_base_address resq 1 102 | .task_cpu_address resq 1 103 | .task_cpu_semaphore resb 1 104 | .task_semaphore resb 1 105 | .task_limit resq 1 106 | .task_count resq 1 107 | .task_id resq 1 108 | 109 | ; variables of Time management functions 110 | .time_rdtsc resq 1 111 | .time_rtc resq 1 112 | 113 | ; variables of TSS management functions 114 | .tss_table resb KERNEL_STRUCTURE_TSS.SIZE 115 | 116 | ; length of this structure in Bytes 117 | .SIZE: 118 | endstruc 119 | -------------------------------------------------------------------------------- /kernel/data.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | kernel dq EMPTY 6 | 7 | kernel_library_base_address dq KERNEL_LIBRARY_base_address 8 | 9 | ; often necessary 10 | kernel_page_mirror dq KERNEL_PAGE_mirror 11 | 12 | kernel_idt_exception_string_unknown db STD_ASCII_NEW_LINE, "{UNKNOWN CPU EXCEPTION}", STD_ASCII_TERMINATOR 13 | kernel_idt_exception_string_divide_by_zero_error db STD_ASCII_NEW_LINE, "Divide-by-zero Error", " at 0x", STD_ASCII_TERMINATOR 14 | kernel_idt_exception_string_debug db STD_ASCII_NEW_LINE, "Debug", " at 0x", STD_ASCII_TERMINATOR 15 | kernel_idt_exception_string_breakpoint db STD_ASCII_NEW_LINE, "Breakpoint", " at 0x", STD_ASCII_TERMINATOR 16 | kernel_idt_exception_string_overflow db STD_ASCII_NEW_LINE, "Overflow", " at 0x", STD_ASCII_TERMINATOR 17 | kernel_idt_exception_string_boud_range_exceeded db STD_ASCII_NEW_LINE, "Bound Range Exceeded", " at 0x", STD_ASCII_TERMINATOR 18 | kernel_idt_exception_string_invalid_opcode db STD_ASCII_NEW_LINE, "Invalid Opcode", " at 0x", STD_ASCII_TERMINATOR 19 | kernel_idt_exception_string_device_not_available db STD_ASCII_NEW_LINE, "Device Not Available", " at 0x", STD_ASCII_TERMINATOR 20 | kernel_idt_exception_string_double_fault db STD_ASCII_NEW_LINE, "Double Fault", " at 0x", STD_ASCII_TERMINATOR 21 | kernel_idt_exception_string_coprocessor_sefment_overrun db STD_ASCII_NEW_LINE, "Coprocessor Segment Overrun", " at 0x", STD_ASCII_TERMINATOR 22 | kernel_idt_exception_string_invalid_tss db STD_ASCII_NEW_LINE, "Invalid TSS", " at 0x", STD_ASCII_TERMINATOR 23 | kernel_idt_exception_string_segment_not_present db STD_ASCII_NEW_LINE, "Segment Not Present", " at 0x", STD_ASCII_TERMINATOR 24 | kernel_idt_exception_string_stack_segment_fault db STD_ASCII_NEW_LINE, "Stack-Segment Fault", " at 0x", STD_ASCII_TERMINATOR 25 | kernel_idt_exception_string_general_protection_fault db STD_ASCII_NEW_LINE, "General Protection Fault", " at 0x", STD_ASCII_TERMINATOR 26 | kernel_idt_exception_string_page_fault db STD_ASCII_NEW_LINE, "Page Fault", " at 0x", STD_ASCII_TERMINATOR 27 | kernel_idt_exception_string_x87_floating_point db STD_ASCII_NEW_LINE, "x87 Floating-Point", " at 0x", STD_ASCII_TERMINATOR 28 | kernel_idt_exception_string_alignment_check db STD_ASCII_NEW_LINE, "Alignment Check", " at 0x", STD_ASCII_TERMINATOR 29 | kernel_idt_exception_string_machine_check db STD_ASCII_NEW_LINE, "Machine Check", " at 0x", STD_ASCII_TERMINATOR 30 | kernel_idt_exception_string_simd_floating_point db STD_ASCII_NEW_LINE, "SIMD Floating-Point", " at 0x", STD_ASCII_TERMINATOR 31 | kernel_idt_exception_string_virtualization db STD_ASCII_NEW_LINE, "Virtualization", " at 0x", STD_ASCII_TERMINATOR 32 | kernel_idt_exception_string_control_protection db STD_ASCII_NEW_LINE, "Control Protection", " at 0x", STD_ASCII_TERMINATOR 33 | kernel_idt_exception_string_hypervisor_injection db STD_ASCII_NEW_LINE, "Hypervisor Injection", " at 0x", STD_ASCII_TERMINATOR 34 | kernel_idt_exception_string_vmm_communication db STD_ASCII_NEW_LINE, "VMM Communication", " at 0x", STD_ASCII_TERMINATOR 35 | kernel_idt_exception_string_security db STD_ASCII_NEW_LINE, "Security", " at 0x", STD_ASCII_TERMINATOR 36 | 37 | ; align table 38 | align 0x08, db 0x00 39 | kernel_idt_exception_string: 40 | dq kernel_idt_exception_string_divide_by_zero_error 41 | dq kernel_idt_exception_string_debug 42 | dq kernel_idt_exception_string_unknown 43 | dq kernel_idt_exception_string_breakpoint 44 | dq kernel_idt_exception_string_overflow 45 | dq kernel_idt_exception_string_boud_range_exceeded 46 | dq kernel_idt_exception_string_invalid_opcode 47 | dq kernel_idt_exception_string_device_not_available 48 | dq kernel_idt_exception_string_double_fault 49 | dq kernel_idt_exception_string_coprocessor_sefment_overrun 50 | dq kernel_idt_exception_string_invalid_tss 51 | dq kernel_idt_exception_string_segment_not_present 52 | dq kernel_idt_exception_string_stack_segment_fault 53 | dq kernel_idt_exception_string_general_protection_fault 54 | dq kernel_idt_exception_string_page_fault 55 | dq kernel_idt_exception_string_unknown 56 | dq kernel_idt_exception_string_x87_floating_point 57 | dq kernel_idt_exception_string_alignment_check 58 | dq kernel_idt_exception_string_machine_check 59 | dq kernel_idt_exception_string_simd_floating_point 60 | dq kernel_idt_exception_string_virtualization 61 | dq kernel_idt_exception_string_control_protection 62 | dq kernel_idt_exception_string_unknown 63 | dq kernel_idt_exception_string_unknown 64 | dq kernel_idt_exception_string_unknown 65 | dq kernel_idt_exception_string_unknown 66 | dq kernel_idt_exception_string_unknown 67 | dq kernel_idt_exception_string_unknown 68 | dq kernel_idt_exception_string_hypervisor_injection 69 | dq kernel_idt_exception_string_vmm_communication 70 | dq kernel_idt_exception_string_security 71 | dq kernel_idt_exception_string_unknown -------------------------------------------------------------------------------- /kernel/driver/ps2.inc: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | %define DRIVER_PS2_KEYBOARD_CACHE_limit 7 6 | 7 | %define DRIVER_PS2_KEYBOARD_IRQ_number 0x01 8 | %define DRIVER_PS2_KEYBOARD_IO_APIC_register KERNEL_IO_APIC_iowin + (DRIVER_PS2_KEYBOARD_IRQ_number * 0x02) 9 | 10 | %define DRIVER_PS2_MOUSE_IRQ_number 0x0C 11 | %define DRIVER_PS2_MOUSE_IO_APIC_register KERNEL_IO_APIC_iowin + (DRIVER_PS2_MOUSE_IRQ_number * 0x02) 12 | 13 | %define DRIVER_PS2_PORT_DATA 0x0060 14 | %define DRIVER_PS2_PORT_COMMAND_OR_STATUS 0x0064 15 | 16 | %define DRIVER_PS2_COMMAND_CONFIGURATION_GET 0x20 17 | %define DRIVER_PS2_COMMAND_CONFIGURATION_SET 0x60 18 | %define DRIVER_PS2_COMMAND_PORT_SECOND 0xD4 19 | 20 | %define DRIVER_PS2_DEVICE_MOUSE_PACKET_LMB 0b00000001 21 | %define DRIVER_PS2_DEVICE_MOUSE_PACKET_RMB 0b00000010 22 | %define DRIVER_PS2_DEVICE_MOUSE_PACKET_MMB 0b00000100 23 | %define DRIVER_PS2_DEVICE_MOUSE_PACKET_ALWAYS_ONE 0b00001000 24 | %define DRIVER_PS2_DEVICE_MOUSE_PACKET_X_SIGNED 0b00010000 25 | %define DRIVER_PS2_DEVICE_MOUSE_PACKET_Y_SIGNED 0b00100000 26 | %define DRIVER_PS2_DEVICE_MOUSE_PACKET_OVERFLOW_x 0b01000000 27 | %define DRIVER_PS2_DEVICE_MOUSE_PACKET_OVERFLOW_y 0b10000000 28 | 29 | %define DRIVER_PS2_DEVICE_PACKETS_ENABLE 0xF4 30 | %define DRIVER_PS2_DEVICE_SET_DEFAULT 0xF6 31 | %define DRIVER_PS2_DEVICE_reset 0xFF 32 | 33 | %define DRIVER_PS2_ANSWER_ACKNOWLEDGED 0xFA 34 | %define DRIVER_PS2_ANSWER_SELF_TEST_SUCCESS 0xAA 35 | 36 | %define DRIVER_PS2_STATUS_output 0b00000001 37 | %define DRIVER_PS2_STATUS_input 0b00000010 38 | %define DRIVER_PS2_STATUS_output_second 0b00100000 39 | 40 | %define DRIVER_PS2_CONFIGURATION_PORT_SECOND_INTERRUPT 0b00000010 41 | %define DRIVER_PS2_CONFIGURATION_PORT_SECOND_CLOCK 0b00100000 42 | 43 | %define DRIVER_PS2_KEYBOARD_sequence 0xE0 44 | %define DRIVER_PS2_KEYBOARD_sequence_alternative 0xE1 45 | 46 | %define DRIVER_PS2_KEYBOARD_PRESS_BACKSPACE 0x0008 47 | %define DRIVER_PS2_KEYBOARD_PRESS_TAB 0x0009 48 | %define DRIVER_PS2_KEYBOARD_PRESS_ENTER 0x000D 49 | %define DRIVER_PS2_KEYBOARD_PRESS_ESC 0x001B 50 | %define DRIVER_PS2_KEYBOARD_PRESS_CTRL_LEFT 0x001D 51 | %define DRIVER_PS2_KEYBOARD_PRESS_SPACE 0x0020 52 | %define DRIVER_PS2_KEYBOARD_PRESS_SHIFT_LEFT 0xE02A 53 | %define DRIVER_PS2_KEYBOARD_PRESS_SHIFT_RIGHT 0xE036 54 | %define DRIVER_PS2_KEYBOARD_PRESS_NUMLOCK_MULTIPLY 0xE037 55 | %define DRIVER_PS2_KEYBOARD_PRESS_ALT_LEFT 0xE038 56 | %define DRIVER_PS2_KEYBOARD_PRESS_CAPSLOCK 0xE03A 57 | %define DRIVER_PS2_KEYBOARD_PRESS_F1 0xE03B 58 | %define DRIVER_PS2_KEYBOARD_PRESS_F2 0xE03C 59 | %define DRIVER_PS2_KEYBOARD_PRESS_F3 0xE03D 60 | %define DRIVER_PS2_KEYBOARD_PRESS_F4 0xE03E 61 | %define DRIVER_PS2_KEYBOARD_PRESS_F5 0xE03F 62 | %define DRIVER_PS2_KEYBOARD_PRESS_F6 0xE040 63 | %define DRIVER_PS2_KEYBOARD_PRESS_F7 0xE041 64 | %define DRIVER_PS2_KEYBOARD_PRESS_F8 0xE042 65 | %define DRIVER_PS2_KEYBOARD_PRESS_F9 0xE043 66 | %define DRIVER_PS2_KEYBOARD_PRESS_F10 0xE044 67 | %define DRIVER_PS2_KEYBOARD_PRESS_NUMLOCK 0xE045 68 | %define DRIVER_PS2_KEYBOARD_PRESS_SCROLL_LOCK 0xE046 69 | %define DRIVER_PS2_KEYBOARD_PRESS_NUMLOCK_MINUS 0xE04A 70 | %define DRIVER_PS2_KEYBOARD_PRESS_NUMLOCK_4 0xE14B 71 | %define DRIVER_PS2_KEYBOARD_PRESS_NUMLOCK_5 0xE04C 72 | %define DRIVER_PS2_KEYBOARD_PRESS_NUMLOCK_6 0xE14D 73 | %define DRIVER_PS2_KEYBOARD_PRESS_NUMLOCK_PLUS 0xE04E 74 | %define DRIVER_PS2_KEYBOARD_PRESS_NUMLOCK_7 0xE047 75 | %define DRIVER_PS2_KEYBOARD_PRESS_NUMLOCK_8 0xE048 76 | %define DRIVER_PS2_KEYBOARD_PRESS_NUMLOCK_9 0xE049 77 | %define DRIVER_PS2_KEYBOARD_PRESS_NUMLOCK_1 0xE14F 78 | %define DRIVER_PS2_KEYBOARD_PRESS_NUMLOCK_2 0xE150 79 | %define DRIVER_PS2_KEYBOARD_PRESS_NUMLOCK_3 0xE151 80 | %define DRIVER_PS2_KEYBOARD_PRESS_NUMLOCK_0 0xE152 81 | %define DRIVER_PS2_KEYBOARD_PRESS_NUMLOCK_DOT 0xE153 82 | %define DRIVER_PS2_KEYBOARD_PRESS_F11 0xE057 83 | %define DRIVER_PS2_KEYBOARD_PRESS_F12 0xE158 84 | %define DRIVER_PS2_KEYBOARD_PRESS_CTRL_RIGHT 0xE01D 85 | %define DRIVER_PS2_KEYBOARD_PRESS_NUMLOCK_DIVIDE 0xE035 86 | %define DRIVER_PS2_KEYBOARD_PRESS_ALT_RIGHT 0xE038 87 | %define DRIVER_PS2_KEYBOARD_PRESS_HOME 0xE047 88 | %define DRIVER_PS2_KEYBOARD_PRESS_ARROW_UP 0xE048 89 | %define DRIVER_PS2_KEYBOARD_PRESS_PAGE_UP 0xE049 90 | %define DRIVER_PS2_KEYBOARD_PRESS_ARROW_LEFT 0xE04B 91 | %define DRIVER_PS2_KEYBOARD_PRESS_ARROW_RIGHT 0xE04D 92 | %define DRIVER_PS2_KEYBOARD_PRESS_END 0xE04F 93 | %define DRIVER_PS2_KEYBOARD_PRESS_ARROW_DOWN 0xE050 94 | %define DRIVER_PS2_KEYBOARD_PRESS_PAGE_DOWN 0xE051 95 | %define DRIVER_PS2_KEYBOARD_PRESS_INSERT 0xE052 96 | %define DRIVER_PS2_KEYBOARD_PRESS_DELETE 0xE053 97 | %define DRIVER_PS2_KEYBOARD_PRESS_WIN_LEFT 0xE058 98 | %define DRIVER_PS2_KEYBOARD_PRESS_MOUSE_RIGHT 0xE05D 99 | 100 | %define DRIVER_PS2_KEYBOARD_key_release 0x0080 101 | 102 | %define DRIVER_PS2_KEYBOARD_RELEASE_BACKSPACE DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_BACKSPACE 103 | %define DRIVER_PS2_KEYBOARD_RELEASE_TAB DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_TAB 104 | %define DRIVER_PS2_KEYBOARD_RELEASE_ENTER DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_ENTER 105 | %define DRIVER_PS2_KEYBOARD_RELEASE_ESC DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_ESC 106 | %define DRIVER_PS2_KEYBOARD_RELEASE_CTRL_LEFT DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_CTRL_LEFT 107 | %define DRIVER_PS2_KEYBOARD_RELEASE_SHIFT_LEFT DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_SHIFT_LEFT 108 | %define DRIVER_PS2_KEYBOARD_RELEASE_SHIFT_RIGHT DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_SHIFT_RIGHT 109 | %define DRIVER_PS2_KEYBOARD_RELEASE_NUMLOCK_MULTIPLY DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_NUMLOCK_MULTIPLY 110 | %define DRIVER_PS2_KEYBOARD_RELEASE_ALT_LEFT DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_ALT_LEFT 111 | %define DRIVER_PS2_KEYBOARD_RELEASE_CAPSLOCK DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_CAPSLOCK 112 | %define DRIVER_PS2_KEYBOARD_RELEASE_F1 DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_F1 113 | %define DRIVER_PS2_KEYBOARD_RELEASE_F2 DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_F2 114 | %define DRIVER_PS2_KEYBOARD_RELEASE_F3 DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_F3 115 | %define DRIVER_PS2_KEYBOARD_RELEASE_F4 DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_F4 116 | %define DRIVER_PS2_KEYBOARD_RELEASE_F5 DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_F5 117 | %define DRIVER_PS2_KEYBOARD_RELEASE_F6 DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_F6 118 | %define DRIVER_PS2_KEYBOARD_RELEASE_F7 DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_F7 119 | %define DRIVER_PS2_KEYBOARD_RELEASE_F8 DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_F8 120 | %define DRIVER_PS2_KEYBOARD_RELEASE_F9 DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_F9 121 | %define DRIVER_PS2_KEYBOARD_RELEASE_F10 DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_F10 122 | %define DRIVER_PS2_KEYBOARD_RELEASE_NUMLOCK DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_NUMLOCK 123 | %define DRIVER_PS2_KEYBOARD_RELEASE_SCROLL_LOCK DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_SCROLL_LOCK 124 | %define DRIVER_PS2_KEYBOARD_RELEASE_NUMLOCK_MINUS DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_NUMLOCK_MINUS 125 | %define DRIVER_PS2_KEYBOARD_RELEASE_NUMLOCK_4 DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_NUMLOCK_4 126 | %define DRIVER_PS2_KEYBOARD_RELEASE_NUMLOCK_5 DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_NUMLOCK_5 127 | %define DRIVER_PS2_KEYBOARD_RELEASE_NUMLOCK_6 DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_NUMLOCK_6 128 | %define DRIVER_PS2_KEYBOARD_RELEASE_NUMLOCK_PLUS DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_NUMLOCK_PLUS 129 | %define DRIVER_PS2_KEYBOARD_RELEASE_NUMLOCK_1 DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_NUMLOCK_1 130 | %define DRIVER_PS2_KEYBOARD_RELEASE_NUMLOCK_2 DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_NUMLOCK_2 131 | %define DRIVER_PS2_KEYBOARD_RELEASE_NUMLOCK_3 DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_NUMLOCK_3 132 | %define DRIVER_PS2_KEYBOARD_RELEASE_NUMLOCK_0 DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_NUMLOCK_0 133 | %define DRIVER_PS2_KEYBOARD_RELEASE_NUMLOCK_DOT DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_NUMLOCK_DOT 134 | %define DRIVER_PS2_KEYBOARD_RELEASE_F11 DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_F11 135 | %define DRIVER_PS2_KEYBOARD_RELEASE_F12 DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_F12 136 | %define DRIVER_PS2_KEYBOARD_RELEASE_CTRL_RIGHT DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_CTRL_RIGHT 137 | %define DRIVER_PS2_KEYBOARD_RELEASE_NUMLOCK_DIVIDE DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_NUMLOCK_DIVIDE 138 | %define DRIVER_PS2_KEYBOARD_RELEASE_ALT_RIGHT DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_ALT_RIGHT 139 | %define DRIVER_PS2_KEYBOARD_RELEASE_HOME DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_HOME 140 | %define DRIVER_PS2_KEYBOARD_RELEASE_ARROW_UP DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_ARROW_UP 141 | %define DRIVER_PS2_KEYBOARD_RELEASE_PAGE_UP DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_PAGE_UP 142 | %define DRIVER_PS2_KEYBOARD_RELEASE_ARROW_LEFT DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_ARROW_LEFT 143 | %define DRIVER_PS2_KEYBOARD_RELEASE_ARROW_RIGHT DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_ARROW_RIGHT 144 | %define DRIVER_PS2_KEYBOARD_RELEASE_END DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_END 145 | %define DRIVER_PS2_KEYBOARD_RELEASE_ARROW_DOWN DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_ARROW_DOWN 146 | %define DRIVER_PS2_KEYBOARD_RELEASE_PAGE_DOWN DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_PAGE_DOWN 147 | %define DRIVER_PS2_KEYBOARD_RELEASE_INSERT DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_INSERT 148 | %define DRIVER_PS2_KEYBOARD_RELEASE_DELETE DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_DELETE 149 | %define DRIVER_PS2_KEYBOARD_RELEASE_WIN_LEFT DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_WIN_LEFT 150 | %define DRIVER_PS2_KEYBOARD_RELEASE_MOUSE_RIGHT DRIVER_PS2_KEYBOARD_key_release + DRIVER_PS2_KEYBOARD_PRESS_MOUSE_RIGHT -------------------------------------------------------------------------------- /kernel/driver/rtc.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;--------------------------------------------------------------------------------- 6 | ; void 7 | driver_rtc: 8 | ; turn off Direction Flag 9 | cld 10 | 11 | ; preserve original registers 12 | push rax 13 | 14 | .loop: 15 | ; get state of register C 16 | mov al, DRIVER_RTC_STATUS_REGISTER_C 17 | out DRIVER_RTC_PORT_command, al 18 | in al, DRIVER_RTC_PORT_data 19 | 20 | ; no more interrupts? 21 | test al, al 22 | jz .done ; yes 23 | 24 | ; periodic interrupt? 25 | test al, DRIVER_RTC_STATUS_REGISTER_C_interrupt_periodic 26 | jz .loop ; no 27 | 28 | ; global kernel environment variables/functions 29 | mov rax, qword [kernel] 30 | 31 | ; increase the real-time controller invocation count 32 | inc qword [rax + KERNEL.time_rtc] 33 | 34 | ; continue 35 | jmp .loop 36 | 37 | .done: 38 | ; accept current interrupt call 39 | call kernel_lapic_accept 40 | 41 | ; restore ogirinal registers 42 | pop rax 43 | 44 | ; return from routine 45 | iretq 46 | 47 | ;------------------------------------------------------------------------------- 48 | ; void 49 | driver_rtc_init: 50 | ; preserve original register 51 | push rax 52 | push rbx 53 | push rcx 54 | 55 | ; connect real-time controller interrupt handler 56 | mov rax, driver_rtc 57 | mov bx, KERNEL_IDT_TYPE_irq 58 | mov ecx, KERNEL_IDT_IRQ_offset + DRIVER_RTC_IRQ_number 59 | call kernel_idt_mount 60 | 61 | ; connect interrupt vector from IDT table in IOAPIC controller 62 | mov eax, KERNEL_IDT_IRQ_offset + DRIVER_RTC_IRQ_number 63 | mov ebx, DRIVER_RTC_IO_APIC_register 64 | call kernel_io_apic_connect 65 | 66 | ;---------------------------------------------------------------------- 67 | ; set RTC interrupt rate at 1024 Hz (even if set by default) 68 | ;---------------------------------------------------------------------- 69 | 70 | .wait_for_A: 71 | ; get state of register A 72 | mov al, DRIVER_RTC_STATUS_REGISTER_A 73 | out DRIVER_RTC_PORT_command, al 74 | in al, DRIVER_RTC_PORT_data 75 | 76 | ; controller is idle? 77 | test al, DRIVER_RTC_STATUS_REGISTER_A_update_in_progress 78 | jne .wait_for_A ; no, wait a little bit longer 79 | 80 | ; preserve register A status 81 | push rax 82 | 83 | ; put controller into modification mode of register A 84 | mov al, DRIVER_RTC_STATUS_REGISTER_A | DRIVER_RTC_STATUS_REGISTER_A_update_in_progress 85 | out DRIVER_RTC_PORT_command, al 86 | 87 | ; set calling frequency to 1024 Hz 88 | mov al, DRIVER_RTC_STATUS_REGISTER_A 89 | out DRIVER_RTC_PORT_command, al 90 | 91 | ; restore register A status 92 | pop rax 93 | and al, 0xF0 94 | or al, DRIVER_RTC_STATUS_REGISTER_A_rate 95 | out DRIVER_RTC_PORT_data, al 96 | 97 | ;---------------------------------------------------------------------- 98 | ; turn on interrupts and change clock range to 24h instead of 12h 99 | ;---------------------------------------------------------------------- 100 | 101 | .wait_for_B: 102 | ; get state of register B 103 | mov al, DRIVER_RTC_STATUS_REGISTER_B 104 | out DRIVER_RTC_PORT_command, al 105 | in al, DRIVER_RTC_PORT_data 106 | 107 | ; controller is idle? 108 | test al, DRIVER_RTC_STATUS_REGISTER_B_update_in_progress 109 | jne .wait_for_B ; no, wait a little bit longer 110 | 111 | ; preserve register B status 112 | push rax 113 | 114 | ; put controller into modification mode of register B 115 | mov al, DRIVER_RTC_STATUS_REGISTER_B | DRIVER_RTC_STATUS_REGISTER_B_update_in_progress 116 | out DRIVER_RTC_PORT_command, al 117 | 118 | ; restore register B status 119 | pop rax 120 | 121 | ; set registry flags 122 | or al, DRIVER_RTC_STATUS_REGISTER_B_24_hour_mode 123 | or al, DRIVER_RTC_STATUS_REGISTER_B_data_mode_binary 124 | or al, DRIVER_RTC_STATUS_REGISTER_B_periodic_interrupt 125 | out DRIVER_RTC_PORT_data, al 126 | 127 | ;---------------------------------------------------------------------- 128 | ; remove overdue interrupts 129 | ;---------------------------------------------------------------------- 130 | 131 | ; retrieve pending interrupt of real-time controller 132 | mov al, DRIVER_RTC_STATUS_REGISTER_C 133 | out DRIVER_RTC_PORT_command, al 134 | in al, DRIVER_RTC_PORT_data 135 | 136 | ; restore original register 137 | pop rcx 138 | pop rbx 139 | pop rax 140 | 141 | ; return from routine 142 | ret 143 | 144 | ;------------------------------------------------------------------------------- 145 | ; out: 146 | ; rax - 0x00wwyymmddHHMMSS 147 | ; 148 | ; ww - Weekday (Sunday 1, Monday 2, etc.) 149 | ; yy - 20YY 150 | ; mm - Month 151 | ; dd - Day (1..31) 152 | ; HH - Hour (0..23) 153 | ; MM - Minute (0..59) 154 | ; SS - Second (0..59) 155 | driver_rtc_time: 156 | ; clear time register 157 | xor eax, eax 158 | 159 | ; request weekday 160 | mov al, DRIVER_RTC_REGISTER_weekday 161 | out DRIVER_RTC_PORT_command, al 162 | ; retrieve and set in place 163 | in al, DRIVER_RTC_PORT_data 164 | shl rax, STD_MOVE_BYTE 165 | 166 | ; request year 167 | mov al, DRIVER_RTC_REGISTER_year 168 | out DRIVER_RTC_PORT_command, al 169 | ; retrieve and set in place 170 | in al, DRIVER_RTC_PORT_data 171 | shl rax, STD_MOVE_BYTE 172 | 173 | ; request month 174 | mov al, DRIVER_RTC_REGISTER_month 175 | out DRIVER_RTC_PORT_command, al 176 | ; retrieve and set in place 177 | in al, DRIVER_RTC_PORT_data 178 | shl rax, STD_MOVE_BYTE 179 | 180 | ; request day 181 | mov al, DRIVER_RTC_REGISTER_day_of_month 182 | out DRIVER_RTC_PORT_command, al 183 | ; retrieve and set in place 184 | in al, DRIVER_RTC_PORT_data 185 | shl rax, STD_MOVE_BYTE 186 | 187 | ; request hour 188 | mov al, DRIVER_RTC_REGISTER_hour 189 | out DRIVER_RTC_PORT_command, al 190 | ; retrieve and set in place 191 | in al, DRIVER_RTC_PORT_data 192 | shl rax, STD_MOVE_BYTE 193 | 194 | ; request minutes 195 | mov al, DRIVER_RTC_REGISTER_minutes 196 | out DRIVER_RTC_PORT_command, al 197 | ; retrieve and set in place 198 | in al, DRIVER_RTC_PORT_data 199 | shl rax, STD_MOVE_BYTE 200 | 201 | ; request seconds 202 | mov al, DRIVER_RTC_REGISTER_seconds 203 | out DRIVER_RTC_PORT_command, al 204 | ; retrieve, already in place 205 | in al, DRIVER_RTC_PORT_data 206 | 207 | ; return from routine 208 | ret -------------------------------------------------------------------------------- /kernel/driver/rtc.inc: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | %ifndef DRIVER_RTC 6 | %define DRIVER_RTC 7 | 8 | %define DRIVER_RTC_IRQ_number 0x08 9 | %define DRIVER_RTC_IO_APIC_register KERNEL_IO_APIC_iowin + (DRIVER_RTC_IRQ_number << STD_SHIFT_2) 10 | 11 | %define DRIVER_RTC_Hz 1024 12 | 13 | %define DRIVER_RTC_PORT_command 0x0070 14 | %define DRIVER_RTC_PORT_data 0x0071 15 | 16 | %define DRIVER_RTC_REGISTER_seconds 0x00 17 | %define DRIVER_RTC_REGISTER_minutes 0x02 18 | %define DRIVER_RTC_REGISTER_hour 0x04 19 | %define DRIVER_RTC_REGISTER_weekday 0x06 20 | %define DRIVER_RTC_REGISTER_day_of_month 0x07 21 | %define DRIVER_RTC_REGISTER_month 0x08 22 | %define DRIVER_RTC_REGISTER_year 0x09 23 | 24 | %define DRIVER_RTC_STATUS_REGISTER_A 0x0A 25 | %define DRIVER_RTC_STATUS_REGISTER_B 0x0B 26 | %define DRIVER_RTC_STATUS_REGISTER_C 0x0C 27 | 28 | %define DRIVER_RTC_STATUS_REGISTER_A_rate 00000101b ; 1024 Hz (32768 >> (0b00000110 - 1)) 29 | %define DRIVER_RTC_STATUS_REGISTER_A_update_in_progress 10000000b 30 | 31 | %define DRIVER_RTC_STATUS_REGISTER_B_24_hour_mode 00000010b 32 | %define DRIVER_RTC_STATUS_REGISTER_B_data_mode_binary 00000100b 33 | %define DRIVER_RTC_STATUS_REGISTER_B_periodic_interrupt 01000000b 34 | %define DRIVER_RTC_STATUS_REGISTER_B_update_in_progress 10000000b 35 | 36 | %define DRIVER_RTC_STATUS_REGISTER_C_interrupt_periodic 01000000b 37 | %endif -------------------------------------------------------------------------------- /kernel/driver/serial.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;---------------------------------------------------------------------- 6 | ; variables, structures, definitions of driver 7 | ;---------------------------------------------------------------------- 8 | %ifndef DRIVER_SERIAL 9 | %include "./kernel/driver/serial.inc" 10 | %endif 11 | 12 | ;------------------------------------------------------------------------------- 13 | ; void 14 | driver_serial_init: 15 | ; preserve original registers 16 | push rax 17 | push rdx 18 | 19 | ; disable interrupt generation 20 | mov al, 0x00 21 | mov dx, DRIVER_SERIAL_PORT_COM1 + DRIVER_SERIAL_REGISTER_interrupt_enable_or_divisor_high 22 | out dx, al 23 | 24 | ; enable DLAB (frequency divider) 25 | mov al, 0x80 26 | mov dx, DRIVER_SERIAL_PORT_COM1 + DRIVER_SERIAL_REGISTER_line_control_or_dlab 27 | out dx, al 28 | 29 | ; communication frequency: 38400 30 | mov al, 0x03 31 | mov dx, DRIVER_SERIAL_PORT_COM1 + DRIVER_SERIAL_REGISTER_data_or_divisor_low 32 | out dx, al 33 | mov al, 0x00 34 | mov dx, DRIVER_SERIAL_PORT_COM1 + DRIVER_SERIAL_REGISTER_interrupt_enable_or_divisor_high 35 | out dx, al 36 | 37 | ; 8 bits per sign, no parity, 1 stop bit 38 | mov al, 0x03 39 | mov dx, DRIVER_SERIAL_PORT_COM1 + DRIVER_SERIAL_REGISTER_line_control_or_dlab 40 | out dx, al 41 | 42 | ; enable FIFO, clear with 14 byte threshold 43 | mov al, 0xC7 44 | mov dx, DRIVER_SERIAL_PORT_COM1 + DRIVER_SERIAL_REGISTER_interrupt_identification_or_fifo 45 | out dx, al 46 | 47 | ; not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled 48 | mov al, 0x0F 49 | mov dx, DRIVER_SERIAL_PORT_COM1 + DRIVER_SERIAL_REGISTER_modem_control 50 | out dx, al 51 | 52 | ; restore original registers 53 | pop rdx 54 | pop rax 55 | 56 | ; return from routine 57 | ret 58 | 59 | 60 | ;------------------------------------------------------------------------------- 61 | ; in: 62 | ; al - ASCII of character 63 | driver_serial_char: 64 | ; preserve original register 65 | push rdx 66 | 67 | ; wait for controller to be ready 68 | call driver_serial_pool 69 | 70 | ; send character 71 | mov dx, DRIVER_SERIAL_PORT_COM1 + DRIVER_SERIAL_REGISTER_data_or_divisor_low 72 | out dx, al 73 | 74 | ; restore original register 75 | pop rdx 76 | 77 | ; return from routine 78 | ret 79 | 80 | 81 | ;------------------------------------------------------------------------------- 82 | ; void 83 | driver_serial_pool: 84 | ; preserve original registers 85 | push rax 86 | push rdx 87 | 88 | ; line status port 89 | mov dx, DRIVER_SERIAL_PORT_COM1 + DRIVER_SERIAL_REGISTER_line_status 90 | 91 | .loop: 92 | ; retrieve controller status 93 | in al, dx 94 | 95 | ; cache empty? 96 | test al, 00100000b 97 | jz .loop ; no, wait longer 98 | 99 | ; regoster original registers 100 | pop rdx 101 | pop rax 102 | 103 | ; return from routine 104 | ret 105 | 106 | ;------------------------------------------------------------------------------- 107 | ; in: 108 | ; rax - value 109 | ; rbx - base 110 | ; rcx - prefix 111 | ; dl - character 112 | ; out: 113 | ; rcx - amount of digits 114 | driver_serial_value: 115 | ; preserve original registers 116 | push rax 117 | push rbp 118 | push rdx 119 | push rcx 120 | 121 | ; stack of digits 122 | mov rbp, rsp 123 | 124 | ; value length in digits 125 | xor ecx, ecx 126 | 127 | .loop: 128 | ; division result 129 | xor edx, edx 130 | 131 | ; modulo 132 | div rbx 133 | 134 | ; convert digit to ASCII 135 | add dl, STD_ASCII_DIGIT_0 136 | 137 | ; digit greater than base of 10 138 | cmp dl, STD_ASCII_DIGIT_9 139 | jb .store ; no 140 | 141 | ; correction to A..Z 142 | add dl, 0x07 143 | 144 | .store: 145 | ; and keep on stack 146 | push rdx 147 | 148 | ; first digit 149 | inc rcx 150 | 151 | ; keep parsing? 152 | test rax, rax 153 | jnz .loop ; yes 154 | 155 | .prefix: 156 | ; prefix with correct length? 157 | cmp rcx, qword [rbp] 158 | jae .print ; yes 159 | 160 | ; add "character" 161 | push dx 162 | 163 | ; next digit 164 | inc rcx 165 | jmp .prefix 166 | 167 | .print: 168 | ; show all digits 169 | 170 | ; something left? 171 | cmp rsp, rbp 172 | je .end ; no 173 | 174 | ; get a digit 175 | pop rax 176 | 177 | ; show digit 178 | call driver_serial_char 179 | 180 | ; next digit 181 | jmp .print 182 | 183 | .end: 184 | ; restore original registers 185 | add rsp, 0x08 ; remove RCX from stack 186 | pop rdx 187 | pop rbp 188 | pop rax 189 | 190 | ; return from routine 191 | ret -------------------------------------------------------------------------------- /kernel/driver/serial.inc: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | %ifndef DRIVER_SERIAL 6 | %define DRIVER_SERIAL 7 | 8 | %define DRIVER_SERIAL_PORT_COM1 0x03F8 9 | 10 | %define DRIVER_SERIAL_REGISTER_data_or_divisor_low 0x00 11 | %define DRIVER_SERIAL_REGISTER_interrupt_enable_or_divisor_high 0x01 12 | %define DRIVER_SERIAL_REGISTER_interrupt_identification_or_fifo 0x02 13 | %define DRIVER_SERIAL_REGISTER_line_control_or_dlab 0x03 14 | %define DRIVER_SERIAL_REGISTER_modem_control 0x04 15 | %define DRIVER_SERIAL_REGISTER_line_status 0x05 16 | %define DRIVER_SERIAL_REGISTER_modem_status 0x06 17 | %define DRIVER_SERIAL_REGISTER_scratch 0x07 18 | %endif -------------------------------------------------------------------------------- /kernel/exec.inc: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | %define KERNEL_EXEC_DESCRIPTOR_offset 0x78 6 | 7 | %define KERNEL_EXEC_BASE_address 0x0000000000100000 8 | 9 | ; whole 223th entry of PML4 table, for easier thread closing 10 | %define KERNEL_EXEC_STACK_SIZE_page 1 11 | %define KERNEL_EXEC_STACK_pointer 0x0000700000000000 12 | %define KERNEL_EXEC_STACK_address KERNEL_EXEC_STACK_pointer - (KERNEL_EXEC_STACK_SIZE_page << STD_SHIFT_PAGE) 13 | 14 | %define KERNEL_EXEC_STACK_OFFSET_registers 0x78 15 | 16 | struc KERNEL_EXEC_STRUCTURE 17 | .pid resq 1 18 | .task_or_status resq 1 19 | .SIZE: 20 | endstruc 21 | 22 | struc KERNEL_EXEC_STRUCTURE_RETURN 23 | .rip resq 1 24 | .cs resq 1 25 | .eflags resq 1 26 | .rsp resq 1 27 | .ss resq 1 28 | .SIZE: 29 | endstruc 30 | -------------------------------------------------------------------------------- /kernel/gdt.inc: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | %ifndef KERNEL_GDT 6 | %define KERNEL_GDT 7 | 8 | %define KERNEL_GDT_FIELD_ACCESS_read_or_write (1 << 1) 9 | %define KERNEL_GDT_FIELD_ACCESS_executable (1 << 3) 10 | %define KERNEL_GDT_FIELD_ACCESS_code_or_data (1 << 4) 11 | %define KERNEL_GDT_FIELD_ACCESS_level_1 (1 << 5) 12 | %define KERNEL_GDT_FIELD_ACCESS_level_2 (1 << 6) 13 | %define KERNEL_GDT_FIELD_ACCESS_level_3 (KERNEL_GDT_FIELD_ACCESS_level_1 | KERNEL_GDT_FIELD_ACCESS_level_2) 14 | %define KERNEL_GDT_FIELD_ACCESS_present (1 << 7) 15 | 16 | %define KERNEL_GDT_FIELD_FLAGS_long_mode (1 << 1) 17 | 18 | struc KERNEL_STRUCTURE_GDT 19 | .null resq 1 20 | .cs_ring0 resq 1 21 | .ss_ring0 resq 1 22 | .empty resq 1 23 | .ss_ring3 resq 1 24 | .cs_ring3 resq 1 25 | .tss: 26 | endstruc 27 | 28 | struc KERNEL_STRUCTURE_GDT_ENTRY 29 | .limit_low resw 1 30 | .base_low resw 1 31 | .base_middle resb 1 32 | .access resb 1 33 | .flags_and_limit_high resb 1 34 | .base_high resb 1 35 | endstruc 36 | 37 | struc KERNEL_STRUCTURE_GDT_HEADER 38 | .limit resw 1 39 | .base_address resq 1 40 | .SIZE: 41 | endstruc 42 | %endif -------------------------------------------------------------------------------- /kernel/idt.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;------------------------------------------------------------------------------ 6 | ; in: 7 | ; on stack: 8 | ; - qword [rsp] exception id 9 | ; - qword [rsp + 0x08] error code 10 | kernel_idt_exception: 11 | ; debug 12 | xchg bx, bx 13 | 14 | ; hold the door 15 | jmp $ 16 | 17 | ; return from routine 18 | ret 19 | 20 | ; align routine to full address 21 | align 0x08, db 0x00 22 | kernel_idt_exception_divide_by_zero: 23 | ; no Error Code 24 | push 0 25 | ; exception id 26 | push 0 27 | 28 | ; continue 29 | jmp kernel_idt_exception_entry 30 | 31 | ; align routine to full address 32 | align 0x08, db 0x00 33 | kernel_idt_exception_debug: 34 | ; no Error Code 35 | push 0 36 | ; exception id 37 | push 1 38 | 39 | ; continue 40 | jmp kernel_idt_exception_entry 41 | 42 | ; align routine to full address 43 | align 0x08, db 0x00 44 | kernel_idt_exception_breakpoint: 45 | ; no Error Code 46 | push 0 47 | ; exception id 48 | push 3 49 | 50 | ; continue 51 | jmp kernel_idt_exception_entry 52 | 53 | ; align routine to full address 54 | align 0x08, db 0x00 55 | kernel_idt_exception_overflow: 56 | ; no Error Code 57 | push 0 58 | ; exception id 59 | push 4 60 | 61 | ; continue 62 | jmp kernel_idt_exception_entry 63 | 64 | ; align routine to full address 65 | align 0x08, db 0x00 66 | kernel_idt_exception_boud_range_exceeded: 67 | ; no Error Code 68 | push 0 69 | ; exception id 70 | push 5 71 | 72 | ; continue 73 | jmp kernel_idt_exception_entry 74 | 75 | ; align routine to full address 76 | align 0x08, db 0x00 77 | kernel_idt_exception_invalid_opcode: 78 | ; no Error Code 79 | push 0 80 | ; exception id 81 | push 6 82 | 83 | ; continue 84 | jmp kernel_idt_exception_entry 85 | 86 | ; align routine to full address 87 | align 0x08, db 0x00 88 | kernel_idt_exception_device_not_available: 89 | ; no Error Code 90 | push 0 91 | ; exception id 92 | push 7 93 | 94 | ; continue 95 | jmp kernel_idt_exception_entry 96 | 97 | ; align routine to full address 98 | align 0x08, db 0x00 99 | kernel_idt_exception_double_fault: 100 | ; set exception id 101 | push 8 102 | 103 | ; continue 104 | jmp kernel_idt_exception_entry 105 | 106 | ; align routine to full address 107 | align 0x08, db 0x00 108 | kernel_idt_exception_coprocessor_segment_overrun: 109 | ; no Error Code 110 | push 0 111 | ; exception id 112 | push 9 113 | 114 | ; continue 115 | jmp kernel_idt_exception_entry 116 | 117 | ; align routine to full address 118 | align 0x08, db 0x00 119 | kernel_idt_exception_invalid_tss: 120 | ; set exception id 121 | push 10 122 | 123 | ; continue 124 | jmp kernel_idt_exception_entry 125 | 126 | ; align routine to full address 127 | align 0x08, db 0x00 128 | kernel_idt_exception_segment_not_present: 129 | ; set exception id 130 | push 11 131 | 132 | ; continue 133 | jmp kernel_idt_exception_entry 134 | 135 | ; align routine to full address 136 | align 0x08, db 0x00 137 | kernel_idt_exception_stack_segment_fault: 138 | ; set exception id 139 | push 12 140 | 141 | ; continue 142 | jmp kernel_idt_exception_entry 143 | 144 | ; align routine to full address 145 | align 0x08, db 0x00 146 | kernel_idt_exception_general_protection_fault: 147 | ; set exception id 148 | push 13 149 | 150 | ; continue 151 | jmp kernel_idt_exception_entry 152 | 153 | ; align routine to full address 154 | align 0x08, db 0x00 155 | kernel_idt_exception_page_fault: 156 | ; set exception id 157 | push 14 158 | 159 | ; continue 160 | jmp kernel_idt_exception_entry 161 | 162 | ; align routine to full address 163 | align 0x08, db 0x00 164 | kernel_idt_exception_x87_floating_point: 165 | ; no Error Code 166 | push 0 167 | ; exception id 168 | push 16 169 | 170 | ; continue 171 | jmp kernel_idt_exception_entry 172 | 173 | ; align routine to full address 174 | align 0x08, db 0x00 175 | kernel_idt_exception_alignment_check: 176 | ; exception id 177 | push 17 178 | 179 | ; continue 180 | jmp kernel_idt_exception_entry 181 | 182 | ; align routine to full address 183 | align 0x08, db 0x00 184 | kernel_idt_exception_machine_check: 185 | ; no Error Code 186 | push 0 187 | ; exception id 188 | push 18 189 | 190 | ; continue 191 | jmp kernel_idt_exception_entry 192 | 193 | ; align routine to full address 194 | align 0x08, db 0x00 195 | kernel_idt_exception_simd_floating_point: 196 | ; no Error Code 197 | push 0 198 | ; exception id 199 | push 19 200 | 201 | ; continue 202 | jmp kernel_idt_exception_entry 203 | 204 | ; align routine to full address 205 | align 0x08, db 0x00 206 | kernel_idt_exception_virtualization: 207 | ; no Error Code 208 | push 0 209 | ; exception id 210 | push 20 211 | 212 | ; continue 213 | jmp kernel_idt_exception_entry 214 | 215 | ; align routine to full address 216 | align 0x08, db 0x00 217 | kernel_idt_exception_control_protection: 218 | ; exception id 219 | push 21 220 | 221 | ; continue 222 | jmp kernel_idt_exception_entry 223 | 224 | ; align routine to full address 225 | align 0x08, db 0x00 226 | kernel_idt_exception_hypervisor_injection: 227 | ; no Error Code 228 | push 0 229 | ; exception id 230 | push 28 231 | 232 | ; continue 233 | jmp kernel_idt_exception_entry 234 | 235 | ; align routine to full address 236 | align 0x08, db 0x00 237 | kernel_idt_exception_vmm_communication: 238 | ; exception id 239 | push 29 240 | 241 | ; continue 242 | jmp kernel_idt_exception_entry 243 | 244 | ; align routine to full address 245 | align 0x08, db 0x00 246 | kernel_idt_exception_security: 247 | ; exception id 248 | push 30 249 | 250 | ; continue 251 | jmp kernel_idt_exception_entry 252 | 253 | kernel_idt_exception_entry: 254 | ; turn off Direction Flag 255 | cld 256 | 257 | ; preserve original registers 258 | push rax 259 | push rbx 260 | push rcx 261 | push rdx 262 | push rsi 263 | push rdi 264 | push rbp 265 | push r8 266 | push r9 267 | push r10 268 | push r11 269 | push r12 270 | push r13 271 | push r14 272 | push r15 273 | 274 | ; put on the stack value of CR2 register 275 | mov rax, cr2 276 | push rax 277 | 278 | ; turn off Direction Flag 279 | cld 280 | 281 | ; execute exception handler 282 | mov rdi, rsp 283 | call kernel_idt_exception 284 | 285 | ; release value of CR2 register from stack 286 | add rsp, 0x08 287 | 288 | ; restore ogirinal registers 289 | pop r15 290 | pop r14 291 | pop r13 292 | pop r12 293 | pop r11 294 | pop r10 295 | pop r9 296 | pop r8 297 | pop rbp 298 | pop rdi 299 | pop rsi 300 | pop rdx 301 | pop rcx 302 | pop rbx 303 | pop rax 304 | 305 | ; release value of exception ID and Error Code from stack 306 | add rsp, 0x10 307 | 308 | ; return from the procedure 309 | iretq 310 | 311 | ; align routine to full address 312 | align 0x08, db 0x00 313 | kernel_idt_interrupt: 314 | ; accept current interrupt call 315 | call kernel_lapic_accept 316 | 317 | ; return from routine 318 | iretq 319 | 320 | ; align routine 321 | align 0x08, db EMPTY 322 | kernel_idt_interrupt_spurious: 323 | ; return from interrupt 324 | iretq 325 | 326 | ;------------------------------------------------------------------------------- 327 | ; in: 328 | ; rax - pointer to interrupt handler 329 | ; bx - interrupt type 330 | ; rcx - entry number 331 | kernel_idt_mount: 332 | ; preserve original registers 333 | push rax 334 | push rcx 335 | push rdi 336 | 337 | ; retirve pointer to IDT structure 338 | mov rdi, [r8 + KERNEL.idt_header + KERNEL_STRUCTURE_IDT_HEADER.base_address] 339 | 340 | ; move pointer to entry 341 | shl cx, STD_SHIFT_16 342 | or di, cx 343 | 344 | ; low bits of address (15...0) 345 | mov word [rdi + KERNEL_STRUCTURE_IDT_ENTRY.base_low], ax 346 | 347 | ; middle bits of address (31...16) 348 | shr rax, STD_MOVE_WORD 349 | mov word [rdi + KERNEL_STRUCTURE_IDT_ENTRY.base_middle], ax 350 | 351 | ; high bits of address (63...32) 352 | shr rax, STD_MOVE_WORD 353 | mov dword [rdi + KERNEL_STRUCTURE_IDT_ENTRY.base_high], eax 354 | 355 | ; code descriptor of kernel environment 356 | mov word [rdi + KERNEL_STRUCTURE_IDT_ENTRY.cs], KERNEL_STRUCTURE_GDT.cs_ring0 357 | 358 | ; type of interrupt 359 | mov word [rdi + KERNEL_STRUCTURE_IDT_ENTRY.type], bx 360 | 361 | ; restore original registers 362 | pop rdi 363 | pop rcx 364 | pop rax 365 | 366 | ; return from routine 367 | ret -------------------------------------------------------------------------------- /kernel/idt.inc: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | %ifndef KERNEL_IDT 6 | %define KERNEL_IDT 7 | 8 | %define KERNEL_IDT_IRQ_offset 0x20 9 | 10 | %define KERNEL_IDT_TYPE_gate_interrupt 0x8E00 11 | %define KERNEL_IDT_TYPE_irq 0x8F00 12 | %define KERNEL_IDT_TYPE_isr 0xEF00 13 | 14 | struc KERNEL_STRUCTURE_IDT_ENTRY 15 | .base_low resw 1 16 | .cs resw 1 17 | .type resw 1 18 | .base_middle resw 1 19 | .base_high resd 1 20 | .reserved resd 1 21 | endstruc 22 | 23 | struc KERNEL_STRUCTURE_IDT_EXCEPTION 24 | .cr2 resq 1 25 | .r15 resq 1 26 | .r14 resq 1 27 | .r13 resq 1 28 | .r12 resq 1 29 | .r11 resq 1 30 | .r10 resq 1 31 | .r9 resq 1 32 | .r8 resq 1 33 | .rbp resq 1 34 | .rdi resq 1 35 | .rsi resq 1 36 | .rdx resq 1 37 | .rcx resq 1 38 | .rbx resq 1 39 | .rax resq 1 40 | .id resq 1 41 | .error_code resq 1 42 | .rip resq 1 43 | .cs resq 1 44 | .eflags resq 1 45 | .rsp resq 1 46 | .ss resq 1 47 | endstruc 48 | 49 | struc KERNEL_STRUCTURE_IDT_HEADER 50 | .limit resw 1 51 | .base_address resq 1 52 | .SIZE: 53 | endstruc 54 | 55 | struc KERNEL_STRUCTURE_IDT_RETURN 56 | .rip resq 1 57 | .cs resq 1 58 | .eflags resq 1 59 | .rsp resq 1 60 | .ss resq 1 61 | endstruc 62 | %endif -------------------------------------------------------------------------------- /kernel/init.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;----------------------------------------------------------------------- 6 | ; structures, definitions 7 | ;----------------------------------------------------------------------- 8 | ; library -------------------------------------------------------------- 9 | %include "library/elf.inc" 10 | %include "library/vfs.inc" 11 | %include "library/sys.inc" 12 | ; driver --------------------------------------------------------------- 13 | %include "kernel/driver/ps2.inc" 14 | %include "kernel/driver/rtc.inc" 15 | ; kernel --------------------------------------------------------------- 16 | %include "kernel/config.inc" 17 | %include "kernel/exec.inc" 18 | %include "kernel/io_apic.inc" 19 | %include "kernel/ipc.inc" 20 | %include "kernel/lapic.inc" 21 | %include "kernel/library.inc" 22 | %include "kernel/page.inc" 23 | %include "kernel/storage.inc" 24 | %include "kernel/stream.inc" 25 | %include "kernel/task.inc" 26 | ; kernel environment initialization routines --------------------------- 27 | %include "kernel/init/acpi.inc" 28 | %include "kernel/init/ap.inc" 29 | %include "kernel/init/limine.inc" 30 | ;======================================================================= 31 | 32 | ; we are using Position Independed Code 33 | default rel 34 | 35 | ; main initialization procedure of kernel environment 36 | global _entry 37 | 38 | ; information for linker 39 | section .data 40 | ;----------------------------------------------------------------------- 41 | ; variables, constants 42 | ;----------------------------------------------------------------------- 43 | %include "kernel/data.asm" 44 | %include "kernel/init/data.asm" 45 | ;======================================================================= 46 | 47 | ; 64 bit code 48 | [bits 64] 49 | 50 | ; information for linker 51 | section .text 52 | ;----------------------------------------------------------------------- 53 | ; routines 54 | ;----------------------------------------------------------------------- 55 | ; library -------------------------------------------------------------- 56 | %include "library/vfs.asm" 57 | %include "library/elf.asm" 58 | %include "library/string/compare.asm" 59 | %include "library/string/length.asm" 60 | %include "library/string/word.asm" 61 | ; drivers -------------------------------------------------------------- 62 | %include "kernel/driver/ps2.asm" 63 | %include "kernel/driver/rtc.asm" 64 | %include "kernel/driver/serial.asm" 65 | ; kernel --------------------------------------------------------------- 66 | %include "kernel/exec.asm" 67 | %include "kernel/idt.asm" 68 | %include "kernel/io_apic.asm" 69 | %include "kernel/lapic.asm" 70 | %include "kernel/library.asm" 71 | %include "kernel/log.asm" 72 | %include "kernel/memory.asm" 73 | %include "kernel/page.asm" 74 | %include "kernel/service.asm" 75 | %include "kernel/storage.asm" 76 | %include "kernel/stream.asm" 77 | %include "kernel/syscall.asm" 78 | %include "kernel/task.asm" 79 | ; kernel environment initialization routines --------------------------- 80 | %include "kernel/init/environment.asm" 81 | %include "kernel/init/limine.asm" 82 | %include "kernel/init/memory.asm" 83 | %include "kernel/init/acpi.asm" 84 | %include "kernel/init/page.asm" 85 | %include "kernel/init/gdt.asm" 86 | %include "kernel/init/stream.asm" 87 | %include "kernel/init/task.asm" 88 | %include "kernel/init/ipc.asm" 89 | %include "kernel/init/idt.asm" 90 | %include "kernel/init/ap.asm" 91 | %include "kernel/init/cmd.asm" 92 | %include "kernel/init/daemon.asm" 93 | %include "kernel/init/exec.asm" 94 | %include "kernel/init/free.asm" 95 | %include "kernel/init/library.asm" 96 | %include "kernel/init/smp.asm" 97 | %include "kernel/init/storage.asm" 98 | ;======================================================================= 99 | 100 | ;------------------------------ 101 | ; ^ files for refactorization - 102 | ; ^ files already done - 103 | ;------------------------------ 104 | ; debug - 105 | ;-------- 106 | 107 | ; our mighty init 108 | _entry: 109 | ; DEBUG --------------------------------------------------------------- 110 | 111 | ; initialize default debug output 112 | call driver_serial_init 113 | 114 | ; check passed variables/structures by Limine bootloader 115 | call kernel_init_limine 116 | 117 | ; BASE ---------------------------------------------------------------- 118 | 119 | ; initialize global kernel environment variables/functions/rountines 120 | call kernel_init_environment 121 | 122 | ; from now on, register R8 will contain pointer to global kernel environment variables/functions/rountines, up to end of initialization 123 | 124 | ; create binary memory map 125 | call kernel_init_memory 126 | 127 | ; from now on, register R9 will contain pointer to binary memory map, up to end of initialization 128 | 129 | ; parse ACPI tables 130 | call kernel_init_acpi 131 | 132 | ; recreate kernel's paging structures 133 | call kernel_init_page 134 | 135 | ; reload new kernel environment paging array 136 | mov rax, ~KERNEL_PAGE_mirror ; physical address 137 | and rax, qword [r8 + KERNEL.page_base_address] 138 | mov cr3, rax 139 | 140 | ; set new stack pointer 141 | mov rsp, KERNEL_STACK_pointer 142 | 143 | ; create Global Descriptor Table 144 | call kernel_init_gdt 145 | 146 | ; create Interrupt Descriptor Table 147 | call kernel_init_idt 148 | 149 | ; ESSENTIAL ----------------------------------------------------------- 150 | 151 | ; initialize stream set 152 | call kernel_init_stream 153 | 154 | ; create Task queue and insert kernel into it 155 | call kernel_init_task 156 | 157 | ; create interprocess communication system 158 | call kernel_init_ipc 159 | 160 | ; configure RTC 161 | call driver_rtc_init 162 | 163 | ; retrieve file to execute 164 | call kernel_init_cmd 165 | 166 | ; initialize PS2 keyboard/mouse driver 167 | call driver_ps2 168 | 169 | ; register all available data carriers 170 | call kernel_init_storage 171 | 172 | ; prepare library subsystem 173 | call kernel_init_library 174 | 175 | ; execute daemons 176 | call kernel_init_daemon 177 | 178 | ; execute init process 179 | call kernel_init_exec 180 | 181 | ; below, initialization functions does not guarantee original registers preservation 182 | 183 | ; initialize other CPUs 184 | jmp kernel_init_smp 185 | -------------------------------------------------------------------------------- /kernel/init/acpi.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;------------------------------------------------------------------------------- 6 | ; void 7 | kernel_init_acpi: 8 | ; preserve original registers 9 | push rcx 10 | push rsi 11 | push rdi 12 | 13 | ; RSDP or XSDP header properties 14 | mov rsi, qword [kernel_limine_rsdp_request + LIMINE_RSDP_REQUEST.response] 15 | mov rsi, qword [rsi + LIMINE_RSDP_RESPONSE.address] 16 | 17 | ; check revision number of RSDP/XSDP header 18 | cmp byte [rsi + KERNEL_STRUCTURE_INIT_ACPI_RSDP_OR_XSDP_HEADER.revision], EMPTY 19 | jne .extended ; no 20 | 21 | ; RSDT header properties 22 | mov edi, dword [rsi + KERNEL_STRUCTURE_INIT_ACPI_RSDP_OR_XSDP_HEADER.rsdt_address] 23 | 24 | ; amount of entries 25 | mov ecx, dword [edi + KERNEL_STRUCTURE_INIT_ACPI_DEFAULT.length] 26 | sub ecx, KERNEL_STRUCTURE_INIT_ACPI_DEFAULT.SIZE 27 | shr ecx, STD_SHIFT_4 28 | 29 | ; pointer to list of RSDT entries 30 | add edi, KERNEL_STRUCTURE_INIT_ACPI_DEFAULT.SIZE 31 | 32 | .rsdt_entry: 33 | ; parse entry 34 | mov esi, dword [edi] 35 | call .parse 36 | 37 | ; next entry from RSDT table 38 | add edi, STD_SIZE_DWORD_byte 39 | 40 | ; end of table? 41 | dec ecx 42 | jnz .rsdt_entry ; no 43 | 44 | ; everything parsed 45 | jmp .acpi_end 46 | 47 | .extended: 48 | ; XSDT header properties 49 | mov rdi, qword [rsi + KERNEL_STRUCTURE_INIT_ACPI_RSDP_OR_XSDP_HEADER.xsdt_address] 50 | 51 | ; amount of entries 52 | mov ecx, dword [edi + KERNEL_STRUCTURE_INIT_ACPI_DEFAULT.length] 53 | sub ecx, KERNEL_STRUCTURE_INIT_ACPI_DEFAULT.SIZE 54 | shr ecx, STD_SHIFT_8 55 | 56 | ; pointer to list of XSDT entries 57 | add rdi, KERNEL_STRUCTURE_INIT_ACPI_DEFAULT.SIZE 58 | 59 | .xsdt_entry: 60 | ; parse entry 61 | mov rsi, qword [rdi] 62 | call .parse 63 | 64 | ; next entry from XSDT table 65 | add rdi, STD_SIZE_QWORD_byte 66 | 67 | ; end of table? 68 | dec rcx 69 | jnz .xsdt_entry ; no 70 | 71 | .acpi_end: 72 | ; restore original registers 73 | pop rdi 74 | pop rsi 75 | pop rcx 76 | 77 | ; return from routine 78 | ret 79 | 80 | ;----------------------------------------------------------------------- 81 | ; second, parse every entry to find what we need 82 | ;----------------------------------------------------------------------- 83 | 84 | .parse: 85 | ; header of MADT (Multiple APIC Description Table)? 86 | cmp dword [rsi + KERNEL_STRUCTURE_INIT_ACPI_DEFAULT.signature], KERNEL_INIT_ACPI_MADT_signature 87 | je .madt ; yes 88 | 89 | ; return from subroutine 90 | ret 91 | 92 | .madt: 93 | ; preserve original registers 94 | push rax 95 | push rcx 96 | push rsi 97 | 98 | ; store LAPIC base address 99 | mov eax, dword [rsi + KERNEL_STRUCTURE_INIT_ACPI_MADT.lapic_address] 100 | mov dword [r8 + KERNEL.lapic_base_address], eax 101 | ; under logical address 102 | mov rax, KERNEL_PAGE_mirror 103 | or qword [r8 + KERNEL.lapic_base_address], rax 104 | 105 | ; length of MADT list 106 | mov ecx, dword [rsi + KERNEL_STRUCTURE_INIT_ACPI_DEFAULT.length] 107 | sub ecx, KERNEL_STRUCTURE_INIT_ACPI_MADT.SIZE ; adjust for header size 108 | 109 | ; pointer of MADT list 110 | add rsi, KERNEL_STRUCTURE_INIT_ACPI_MADT.SIZE 111 | 112 | .madt_entry: 113 | ; we found I/O APIC? 114 | cmp byte [rsi + KERNEL_STRUCTURE_INIT_ACPI_MADT_ENTRY.type], KERNEL_INIT_ACPI_APIC_TYPE_io_apic 115 | je .madt_io_apic ; yes 116 | 117 | .madt_next: 118 | ; get size of entry being processed 119 | movzx eax, byte [rsi + KERNEL_STRUCTURE_INIT_ACPI_MADT_ENTRY.length] 120 | 121 | ; move pointer to next entry 122 | add rsi, rax 123 | 124 | ; end of table? 125 | sub rcx, rax 126 | jnz .madt_entry ; no 127 | 128 | ; restore original registers 129 | pop rsi 130 | pop rcx 131 | pop rax 132 | 133 | ; return from subroutine 134 | ret 135 | 136 | .madt_io_apic: 137 | ; I/O APIC supports interrupt vectors 0+? 138 | cmp dword [rsi + KERNEL_STRUCTURE_INIT_ACPI_IO_APIC.gsib], EMPTY 139 | jne .madt_next ; no 140 | 141 | ; store base address of I/O APIC 142 | mov eax, dword [rsi + KERNEL_STRUCTURE_INIT_ACPI_IO_APIC.base_address] 143 | mov dword [r8 + KERNEL.io_apic_base_address], eax 144 | ; under logical address 145 | mov rax, KERNEL_PAGE_mirror 146 | or qword [r8 + KERNEL.io_apic_base_address], rax 147 | 148 | ; continue 149 | jmp .madt_next -------------------------------------------------------------------------------- /kernel/init/acpi.inc: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | %ifndef KERNEL_INIT_ACPI 6 | %define KERNEL_INIT_ACPI 7 | 8 | %define KERNEL_INIT_ACPI_MADT_signature 0x43495041 9 | 10 | %define KERNEL_INIT_ACPI_APIC_TYPE_lapic 0x00 11 | %define KERNEL_INIT_ACPI_APIC_TYPE_io_apic 0x01 12 | 13 | struc KERNEL_STRUCTURE_INIT_ACPI_RSDP_OR_XSDP_HEADER 14 | .signature resq 1 15 | .checksum resb 1 16 | .oem_id resb 6 17 | .revision resb 1 18 | .rsdt_address resd 1 19 | .length resd 1 20 | .xsdt_address resq 1 21 | .extended_checksum resb 1 22 | .reserved resb 3 23 | endstruc 24 | 25 | struc KERNEL_STRUCTURE_INIT_ACPI_DEFAULT 26 | .signature resd 1 27 | .length resd 1 28 | .revision resb 1 29 | .checksum resb 1 30 | .oem_id resb 6 31 | .oem_table_id resq 1 32 | .oem_revision resd 1 33 | .creator_id resd 1 34 | .creator_revision resd 1 35 | .SIZE: 36 | endstruc 37 | 38 | struc KERNEL_STRUCTURE_INIT_ACPI_MADT 39 | .signature resd 1 40 | .length resd 1 41 | .revision resb 1 42 | .checksum resb 1 43 | .oem_id resb 6 44 | .oem_table_id resq 1 45 | .oem_revision resd 1 46 | .creator_id resd 1 47 | .creator_revision resd 1 48 | ;-------------------------------- 49 | .lapic_address resd 1 50 | .flags resd 1 51 | .SIZE: 52 | endstruc 53 | 54 | struc KERNEL_STRUCTURE_INIT_ACPI_MADT_ENTRY 55 | .type resb 1 56 | .length resb 1 57 | endstruc 58 | 59 | struc KERNEL_STRUCTURE_INIT_ACPI_IO_APIC 60 | .type resb 1 61 | .length resb 1 62 | .ioapic_id resb 1 63 | .reserved resb 1 64 | .base_address resd 1 65 | .gsib resd 1 ; Global System Interrupt Base 66 | endstruc 67 | %endif -------------------------------------------------------------------------------- /kernel/init/ap.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;------------------------------------------------------------------------------- 6 | ; void 7 | kernel_init_ap: 8 | ;----------------------------------------------------------------------- 9 | ; all that's left is the quintessential initialization of all local processors 10 | ; even the BSP processor has to go through it (because we don't want to 11 | ; duplicate the code specifically for it). 12 | ;----------------------------------------------------------------------- 13 | 14 | ; kernel environment variables/rountines base address 15 | mov r8, qword [kernel] 16 | 17 | ;-------- 18 | ; PAGE 19 | ;-------- 20 | 21 | ; switch to new kernel paging array 22 | mov rax, ~KERNEL_PAGE_mirror ; physical address 23 | and rax, qword [r8 + KERNEL.page_base_address] 24 | mov cr3, rax 25 | 26 | ;----- 27 | ; GDT 28 | ;----- 29 | 30 | ; reload Global Descriptor Table 31 | lgdt [r8 + KERNEL.gdt_header] 32 | call kernel_init_gdt_reload 33 | 34 | ;----- 35 | ; TSS 36 | ;----- 37 | 38 | ; change CPU ID to descriptor offset 39 | call kernel_lapic_id 40 | shl rax, STD_SHIFT_16 41 | add rax, KERNEL_STRUCTURE_GDT.tss 42 | 43 | ; preserve TSS offset 44 | push rax 45 | 46 | ; set pointer to TSS entry of this AP 47 | mov rdi, qword [r8 + KERNEL.gdt_header + KERNEL_STRUCTURE_GDT_HEADER.base_address] 48 | add rdi, rax 49 | 50 | ; length of TSS header 51 | mov ax, KERNEL_STRUCTURE_TSS.SIZE 52 | stosw ; save 53 | 54 | ; TSS header address 55 | mov rax, r8 56 | add rax, KERNEL.tss_table 57 | stosw ; save (bits 15..0) 58 | shr rax, 16 59 | stosb ; save (bits 23..16) 60 | 61 | ; fill Task State Segment with flags 62 | mov al, 10001001b ; P, DPL, 0, Type 63 | stosb ; zapisz 64 | xor al, al ; G, 0, 0, AVL, Limit (older part of TSS table size) 65 | stosb ; zapisz 66 | 67 | ; TSS header address 68 | shr rax, 8 69 | stosb ; save (bits 31..24) 70 | shr rax, 8 71 | stosd ; save (bits 63..32) 72 | 73 | ; reserved 32 Bytes of descriptor 74 | xor rax, rax 75 | stosd ; save 76 | 77 | ; load TSS descriptor for this AP 78 | ltr word [rsp] 79 | 80 | ;----- 81 | ; IDT 82 | ;----- 83 | 84 | ; reload Interrupt Descriptor Table 85 | lidt [r8 + KERNEL.idt_header] 86 | 87 | ;----------- 88 | ; CPU Flags 89 | ;----------- 90 | 91 | ; enable Monitor co-processor (bit 1) and disable x87 FPU Emulation (bit 2) 92 | mov rax, cr0 93 | and al, 0xFB 94 | or al, 0x02 95 | mov cr0, rax 96 | 97 | ; enable FXSAVE/FXRSTOR (bit 9), OSXMMEXCPT (bit 10) and OSXSAVE (bit 18) 98 | mov rax, cr4 99 | or rax, 1000000011000000000b 100 | mov cr4, rax 101 | 102 | ; reset FPU state 103 | fninit 104 | 105 | ; enable X87, SSE, AVX support 106 | xor ecx, ecx 107 | xgetbv 108 | or eax, 111b 109 | xsetbv 110 | 111 | ;---------------- 112 | ; SYSCALL/SYSRET 113 | ;---------------- 114 | 115 | ; enable SYSCALL/SYSRET (SCE bit) support 116 | mov ecx, 0xC0000080 117 | rdmsr 118 | or eax, 1b 119 | wrmsr 120 | 121 | ; set code/stack segments of syscall routine 122 | mov ecx, KERNEL_INIT_AP_MSR_STAR 123 | mov edx, 0x00180008 ; GDT descriptors 124 | wrmsr 125 | 126 | ; set syscall entry routine 127 | mov rax, kernel_syscall 128 | mov ecx, KERNEL_INIT_AP_MSR_LSTAR 129 | mov rdx, kernel_syscall 130 | shr rdx, STD_MOVE_DWORD 131 | wrmsr 132 | 133 | ; set EFLAGS mask of entry routine 134 | mov eax, KERNEL_TASK_EFLAGS_if | KERNEL_TASK_EFLAGS_df ; disable Direction flags 135 | mov ecx, KERNEL_INIT_AP_MSR_EFLAGS 136 | xor edx, edx 137 | wrmsr 138 | 139 | ;------ 140 | ; TASK 141 | ;------ 142 | 143 | ; set task in queue being processed by AP 144 | call kernel_lapic_id 145 | push qword [r8 + KERNEL.task_base_address] ; by default: kernel 146 | 147 | ; insert into task cpu list at AP position 148 | shl rax, STD_SHIFT_8 149 | add rax, qword [r8 + KERNEL.task_cpu_address] 150 | pop qword [rax] 151 | 152 | ;------- 153 | ; LAPIC 154 | ;------- 155 | 156 | ; initialize LAPIC of current AP 157 | call kernel_lapic_init 158 | 159 | ; reload AP cycle counter 160 | call kernel_lapic_reload 161 | 162 | ; accept pending interrupts 163 | call kernel_lapic_accept 164 | 165 | ; AP initialized 166 | inc qword [r8 + KERNEL.cpu_count] 167 | 168 | ; enable interrupt handling 169 | sti 170 | 171 | ; wait for miracle :) 172 | jmp $ 173 | -------------------------------------------------------------------------------- /kernel/init/ap.inc: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | %define KERNEL_INIT_AP_MSR_STAR 0xC0000081 6 | %define KERNEL_INIT_AP_MSR_LSTAR 0xC0000082 7 | %define KERNEL_INIT_AP_MSR_EFLAGS 0xC0000084 -------------------------------------------------------------------------------- /kernel/init/cmd.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;------------------------------------------------------------------------------- 6 | ; void 7 | kernel_init_cmd: 8 | ; kernel file available? 9 | cmp qword [kernel_limine_kernel_file_request + LIMINE_KERNEL_FILE_REQUEST.response], EMPTY 10 | je .error ; no 11 | 12 | ; properties of cmd line 13 | mov rsi, qword [kernel_limine_kernel_file_request + LIMINE_KERNEL_FILE_REQUEST.response] 14 | mov rsi, qword [rsi + LIMINE_KERNEL_FILE_RESPONSE.kernel_file] 15 | mov rsi, qword [rsi + LIMINE_FILE.cmd] 16 | 17 | ; retrieve executable name 18 | mov rdi, kernel_exec_file_init 19 | call lib_string_length 20 | mov byte [kernel_exec_file_init_length], cl 21 | rep movsb 22 | 23 | ; return from subroutine 24 | ret 25 | 26 | .error: 27 | ; storage is not available 28 | mov ecx, kernel_log_storage_end - kernel_log_storage 29 | mov rsi, kernel_log_storage 30 | call driver_serial_string 31 | 32 | ; hold the door 33 | jmp $ -------------------------------------------------------------------------------- /kernel/init/daemon.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;------------------------------------------------------------------------------- 6 | ; void 7 | kernel_init_daemon: 8 | ; preserve original registers 9 | push rax 10 | push rbx 11 | push rcx 12 | push rdx 13 | push rsi 14 | push rdi 15 | push rbp 16 | push r8 17 | push r9 18 | push r10 19 | push r11 20 | push r12 21 | push r13 22 | push r14 23 | push r15 24 | 25 | ; kernel environment variables/rountines base address 26 | mov r8, qword [kernel] 27 | 28 | ; by default there is no PID for new process 29 | xor eax, eax 30 | 31 | ;----------------------------------------------------------------------- 32 | ; locate and load file into memory 33 | ;----------------------------------------------------------------------- 34 | 35 | ; daemon "Garbage Collector" 36 | mov ecx, kernel_daemon_file_gc_end - kernel_daemon_file_gc 37 | mov rsi, kernel_daemon_file_gc 38 | 39 | ; file descriptor 40 | sub rsp, KERNEL_STORAGE_STRUCTURE_FILE.SIZE 41 | mov rbp, rsp ; pointer of file descriptor 42 | call kernel_exec_load 43 | 44 | ; file loaded? 45 | cmp qword [rbp + KERNEL_STORAGE_STRUCTURE_FILE.id], EMPTY 46 | je .end ; no 47 | 48 | ; set pointer to file content 49 | mov r13, qword [rbp + KERNEL_STORAGE_STRUCTURE_FILE.address] 50 | 51 | ;----------------------------------------------------------------------- 52 | ; prepare task for execution 53 | ;----------------------------------------------------------------------- 54 | 55 | ; register new task on queue 56 | call kernel_task_add 57 | 58 | ;----------------------------------------------------------------------- 59 | ; paging array of new process 60 | ;----------------------------------------------------------------------- 61 | 62 | ; make space for the process paging table 63 | call kernel_memory_alloc_page 64 | 65 | ; update task entry about paging array 66 | mov qword [r10 + KERNEL_STRUCTURE_TASK.cr3], rdi 67 | 68 | ;----------------------------------------------------------------------- 69 | ; context stack and return point (initialization entry) 70 | ;----------------------------------------------------------------------- 71 | 72 | ; describe the space under context stack of process 73 | mov rax, KERNEL_STACK_address 74 | mov bx, KERNEL_PAGE_FLAG_present | KERNEL_PAGE_FLAG_write | KERNEL_PAGE_FLAG_process 75 | mov ecx, KERNEL_STACK_page 76 | mov r11, rdi 77 | call kernel_page_alloc 78 | 79 | ; process memory usage 80 | add qword [r10 + KERNEL_STRUCTURE_TASK.page], rcx 81 | 82 | ; set process context stack pointer 83 | mov rsi, KERNEL_STACK_pointer - (KERNEL_EXEC_STRUCTURE_RETURN.SIZE + KERNEL_EXEC_STACK_OFFSET_registers) 84 | mov qword [r10 + KERNEL_STRUCTURE_TASK.rsp], rsi 85 | 86 | ; prepare exception exit mode on context stack of process 87 | mov rsi, KERNEL_STACK_pointer - STD_PAGE_byte 88 | call kernel_page_address 89 | 90 | ; set pointer to return descriptor 91 | and rax, STD_PAGE_mask ; drop flags 92 | add rax, qword [kernel_page_mirror] ; convert to logical address 93 | add rax, STD_PAGE_byte - KERNEL_EXEC_STRUCTURE_RETURN.SIZE 94 | 95 | ; set first instruction executed by process 96 | mov rdx, qword [r13 + LIB_ELF_STRUCTURE.entry_ptr] 97 | add rdx, r13 98 | mov qword [rax + KERNEL_EXEC_STRUCTURE_RETURN.rip], rdx 99 | 100 | ; code descriptor 101 | mov qword [rax + KERNEL_EXEC_STRUCTURE_RETURN.cs], KERNEL_STRUCTURE_GDT.cs_ring0 102 | 103 | ; default processor state flags 104 | mov qword [rax + KERNEL_EXEC_STRUCTURE_RETURN.eflags], KERNEL_TASK_EFLAGS_default 105 | 106 | ; default stack pointer 107 | mov rdx, KERNEL_STACK_pointer 108 | mov qword [rax + KERNEL_EXEC_STRUCTURE_RETURN.rsp], rdx 109 | 110 | ; stack descriptor 111 | mov qword [rax + KERNEL_EXEC_STRUCTURE_RETURN.ss], KERNEL_STRUCTURE_GDT.ss_ring0 112 | 113 | ;----------------------------------------------------------------------- 114 | ; allocate space for executable segments 115 | ;----------------------------------------------------------------------- 116 | 117 | ; size of unpacked executable 118 | call kernel_exec_size 119 | 120 | ; assign memory space for executable 121 | add rcx, ~STD_PAGE_mask 122 | shr rcx, STD_SHIFT_PAGE 123 | call kernel_memory_alloc 124 | 125 | ; process memory usage 126 | add qword [r10 + KERNEL_STRUCTURE_TASK.page], rcx 127 | 128 | ;----------------------------------------------------------------------- 129 | ; load program segments in place 130 | ;----------------------------------------------------------------------- 131 | 132 | ; number of program headers 133 | movzx ecx, word [r13 + LIB_ELF_STRUCTURE.h_entry_count] 134 | 135 | ; beginning of header section 136 | mov rdx, qword [r13 + LIB_ELF_STRUCTURE.headers_offset] 137 | add rdx, r13 138 | 139 | .elf_header: 140 | ; ignore empty headers 141 | cmp dword [rdx + LIB_ELF_STRUCTURE_HEADER.type], EMPTY 142 | je .elf_header_next ; empty one 143 | cmp qword [rdx + LIB_ELF_STRUCTURE_HEADER.memory_size], EMPTY 144 | je .elf_header_next ; this too 145 | 146 | ; load segment? 147 | cmp dword [rdx + LIB_ELF_STRUCTURE_HEADER.type], LIB_ELF_HEADER_TYPE_load 148 | jne .elf_header_next ; no 149 | 150 | ; preserve original registers 151 | push rcx 152 | push rdi 153 | 154 | ; segment destination 155 | add rdi, qword [rdx + LIB_ELF_STRUCTURE_HEADER.virtual_address] 156 | 157 | ; segment source 158 | mov rsi, r13 159 | add rsi, qword [rdx + LIB_ELF_STRUCTURE_HEADER.segment_offset] 160 | 161 | ; copy segment in place 162 | mov rcx, qword [rdx + LIB_ELF_STRUCTURE_HEADER.segment_size] 163 | rep movsb 164 | 165 | ; restore original registers 166 | pop rdi 167 | pop rcx 168 | 169 | .elf_header_next: 170 | ; move pointer to next entry 171 | add rdx, LIB_ELF_STRUCTURE_HEADER.SIZE 172 | 173 | ; end of hedaer table? 174 | dec rcx 175 | jnz .elf_header ; no 176 | 177 | ;----------------------------------------------------------------------- 178 | ; kernel environment 179 | ;----------------------------------------------------------------------- 180 | 181 | ; map kernel space to process 182 | mov r15, qword [kernel] 183 | mov r15, qword [r15 + KERNEL.page_base_address] 184 | call kernel_page_merge 185 | 186 | ;----------------------------------------------------------------------- 187 | ; standard input/output (stream) 188 | ;----------------------------------------------------------------------- 189 | 190 | ; set default input stream 191 | call kernel_stream 192 | mov qword [r10 + KERNEL_STRUCTURE_TASK.stream_in], rsi 193 | 194 | ; process memory usage 195 | inc qword [r10 + KERNEL_STRUCTURE_TASK.page] 196 | 197 | ; properties of parent task 198 | call kernel_task_active 199 | 200 | ; set default output stream 201 | mov rsi, qword [r9 + KERNEL_STRUCTURE_TASK.stream_out] 202 | mov qword [r10 + KERNEL_STRUCTURE_TASK.stream_out], rsi 203 | 204 | ; increase stream usage 205 | inc qword [rsi + KERNEL_STRUCTURE_STREAM.count] 206 | 207 | ;----------------------------------------------------------------------- 208 | ; new process initialized 209 | ;----------------------------------------------------------------------- 210 | 211 | ; mark task as ready 212 | or word [r10 + KERNEL_STRUCTURE_TASK.flags], KERNEL_TASK_FLAG_active | KERNEL_TASK_FLAG_module | KERNEL_TASK_FLAG_init 213 | 214 | .end: 215 | ; remove file descriptor from stack 216 | add rsp, KERNEL_STORAGE_STRUCTURE_FILE.SIZE 217 | 218 | ; restore original registers 219 | pop r15 220 | pop r14 221 | pop r13 222 | pop r12 223 | pop r11 224 | pop r10 225 | pop r9 226 | pop r8 227 | pop rbp 228 | pop rdi 229 | pop rsi 230 | pop rdx 231 | pop rcx 232 | pop rbx 233 | pop rax 234 | 235 | ; return from routine 236 | ret -------------------------------------------------------------------------------- /kernel/init/data.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | kernel_acpi_standard db "RSDT (Root System Description Pointer) found." 6 | kernel_acpi_standard_end: 7 | kernel_acpi_extended db "XSDT (eXtended System Descriptor Table) found." 8 | kernel_acpi_extended_end: 9 | kernel_acpi_lapic db STD_ASCII_NEW_LINE, " LAPIC base address 0x" 10 | kernel_acpi_lapic_end: 11 | kernel_acpi_io_apic db STD_ASCII_NEW_LINE, " I/O APIC base address 0x" 12 | kernel_acpi_io_apic_end: 13 | kernel_acpi_hpet db STD_ASCII_NEW_LINE, " HPET base address 0x" 14 | kernel_acpi_hpet_end: 15 | 16 | kernel_log_framebuffer db STD_ASCII_NEW_LINE, "Where are my testicles, Summer?" 17 | kernel_log_framebuffer_end: 18 | kernel_log_prefix db STD_ASCII_NEW_LINE, "+" 19 | kernel_log_prefix_end: 20 | kernel_log_free db " KiB released.", STD_ASCII_NEW_LINE 21 | kernel_log_free_end: 22 | kernel_log_kernel db STD_ASCII_NEW_LINE, "To be, or not to be, that is the question." 23 | kernel_log_kernel_end: 24 | kernel_log_memory db STD_ASCII_NEW_LINE, "Houston, we have a problem." 25 | kernel_log_memory_end: 26 | kernel_log_page db STD_ASCII_NEW_LINE, "Stuck In The Sound - Brother." 27 | kernel_log_page_end: 28 | kernel_log_rsdp db STD_ASCII_NEW_LINE, "Hello Darkness, My Old Friend." 29 | kernel_log_rsdp_end: 30 | kernel_log_smp db " AP(s) initialized." 31 | kernel_log_smp_end: 32 | kernel_log_storage db STD_ASCII_NEW_LINE, "Operation failed successfully." 33 | kernel_log_storage_end: 34 | kernel_log_system db STD_ASCII_NEW_LINE, "System disk [KiB]: " 35 | kernel_log_system_end: 36 | kernel_log_welcome db KERNEL_name, " (v", KERNEL_version, ".", KERNEL_revision, " ", KERNEL_architecture, " ", KERNEL_language, ", build on ", __DATE__, " ", __TIME__, ")", STD_ASCII_NEW_LINE 37 | kernel_log_welcome_end: 38 | 39 | kernel_smp_count dq EMPTY 40 | 41 | kernel_exec_file_init_length db EMPTY 42 | kernel_exec_file_init: 43 | times 256 db EMPTY 44 | 45 | kernel_daemon_file_gc db "gc.d" 46 | kernel_daemon_file_gc_end: 47 | 48 | ; align table 49 | align 0x08, db 0x00 50 | kernel_limine_framebuffer_request: 51 | dq LIMINE_FRAMEBUFFER_MAGIC 52 | dq 0 ; revision 53 | dq EMPTY ; response 54 | 55 | ; align table 56 | align 0x08, db 0x00 57 | kernel_limine_kernel_file_request: 58 | dq LIMINE_KERNEL_FILE_MAGIC 59 | dq 0 ; revision 60 | dq EMPTY ; response 61 | 62 | ; align table 63 | align 0x08, db 0x00 64 | kernel_limine_kernel_address_request: 65 | dq LIMINE_KERNEL_ADDRESS_MAGIC 66 | dq 0 ; revision 67 | dq EMPTY ; response 68 | 69 | ; align table 70 | align 0x08, db 0x00 71 | kernel_limine_memmap_request: 72 | dq LIMINE_MEMMAP_MAGIC 73 | dq 0 ; revision 74 | dq EMPTY ; response 75 | 76 | ; align table 77 | align 0x08, db 0x00 78 | kernel_limine_rsdp_request: 79 | dq LIMINE_RSDP_MAGIC 80 | dq 0 ; revision 81 | dq EMPTY ; response 82 | 83 | ; align table 84 | align 0x08, db 0x00 85 | kernel_limine_smp_request: 86 | dq LIMINE_SMP_MAGIC 87 | dq 0 ; revision 88 | dq EMPTY ; response 89 | dq EMPTY ; flags: do not emable X2APIC 90 | 91 | ; align table 92 | align 0x08, db 0x00 93 | kernel_limine_module_request: 94 | dq LIMINE_MODULE_MAGIC 95 | dq 0 ; revision 96 | dq EMPTY ; response 97 | -------------------------------------------------------------------------------- /kernel/init/environment.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;------------------------------------------------------------------------------- 6 | ; void 7 | kernel_init_environment: 8 | ; preserve original registers 9 | push rax 10 | push rbx 11 | push rcx 12 | push rdi 13 | push rsi 14 | 15 | ;---------------------------------------------------------------------- 16 | 17 | ; remember largest chunk of physical memory 18 | xor rbx, rbx 19 | 20 | ; properties of memory map response 21 | mov rsi, qword [kernel_limine_memmap_request + LIMINE_MEMMAP_REQUEST.response] 22 | 23 | ; amount of entries inside memory map 24 | mov rcx, qword [rsi + LIMINE_MEMMAP_RESPONSE.entry_count] 25 | 26 | ; list of memory map entires 27 | mov rsi, qword [rsi + LIMINE_MEMMAP_RESPONSE.entries] 28 | 29 | .entry: 30 | ; parse "next" entry? 31 | dec rcx 32 | js .done ; no 33 | 34 | ; retrieve entry 35 | mov rax, qword [rsi + rcx * STD_SIZE_PTR_byte] 36 | 37 | ; USABLE memory area? 38 | cmp qword [rax + LIMINE_MEMMAP_ENTRY.type], LIMINE_MEMMAP_USABLE 39 | jne .entry ; no 40 | 41 | ; this area is larger than previous one? 42 | cmp qword [rax + LIMINE_MEMMAP_ENTRY.length], rbx 43 | jng .entry ; no 44 | 45 | ; remember size for later use 46 | mov rbx, qword [rax + LIMINE_MEMMAP_ENTRY.length] 47 | 48 | ; set global kernel environment variables/functions inside largest contiguous memory area (reflected in Higher Half) 49 | mov rdi, KERNEL_PAGE_mirror 50 | or rdi, qword [rax + LIMINE_MEMMAP_ENTRY.base] 51 | mov qword [kernel], rdi 52 | 53 | ; next entry 54 | jmp .entry 55 | 56 | .done: 57 | ;---------------------------------------------------------------------- 58 | 59 | ; properties of first framebuffer 60 | mov rsi, qword [kernel_limine_framebuffer_request + LIMINE_FRAMEBUFFER_REQUEST.response] 61 | mov rsi, qword [rsi + LIMINE_FRAMEBUFFER_RESPONSE.framebuffers] 62 | mov rsi, qword [rsi + INIT] ; properties of first framebuffer 63 | 64 | ; set information about framebuffer properties 65 | 66 | ; base address 67 | mov rax, KERNEL_PAGE_mirror 68 | or rax, qword [rsi + LIMINE_FRAMEBUFFER.address] 69 | mov qword [rdi + KERNEL.framebuffer_base_address], rax 70 | 71 | ; width in pixels 72 | mov ax, word [rsi + LIMINE_FRAMEBUFFER.width] 73 | mov word [rdi + KERNEL.framebuffer_width_pixel], ax 74 | 75 | ; height in pixels 76 | mov ax, word [rsi + LIMINE_FRAMEBUFFER.height] 77 | mov word [rdi + KERNEL.framebuffer_height_pixel], ax 78 | 79 | ; pitch in Bytes 80 | mov eax, dword [rsi + LIMINE_FRAMEBUFFER.pitch] 81 | mov dword [rdi + KERNEL.framebuffer_pitch_byte], eax 82 | 83 | ; owner of framebuffer 84 | mov qword [rdi + KERNEL.framebuffer_pid], INIT ; by default: kernel 85 | 86 | ;---------------------------------------------------------------------- 87 | 88 | ; share IDT management functions 89 | mov qword [rdi + KERNEL.idt_mount], kernel_idt_mount 90 | 91 | ; share kernel early printf function 92 | mov qword [rdi + KERNEL.log], kernel_log 93 | 94 | ; share memory management functions 95 | mov qword [rdi + KERNEL.memory_release], kernel_memory_release 96 | 97 | ; share page management functions 98 | mov qword [rdi + KERNEL.page_deconstruction], kernel_page_deconstruction 99 | 100 | ; share stream management functions 101 | mov qword [rdi + KERNEL.stream_release], kernel_stream_release 102 | 103 | ; restore original registers 104 | pop rsi 105 | pop rdi 106 | pop rcx 107 | pop rbx 108 | pop rax 109 | 110 | ; return from routine 111 | ret 112 | -------------------------------------------------------------------------------- /kernel/init/exec.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;------------------------------------------------------------------------------- 6 | ; void 7 | kernel_init_exec: 8 | ; preserve original registers 9 | push rcx 10 | push rsi 11 | push rbp 12 | 13 | ; exec descriptor 14 | sub rsp, KERNEL_EXEC_STRUCTURE.SIZE 15 | mov rbp, rsp ; pointer of file descriptor 16 | 17 | ; ; execute init file 18 | movzx ecx, byte [kernel_exec_file_init_length] 19 | mov rsi, kernel_exec_file_init 20 | mov edi, LIB_SYS_STREAM_FLOW_out_to_parent_out 21 | call kernel_exec 22 | 23 | ; remove exec descriptor 24 | add rsp, KERNEL_EXEC_STRUCTURE.SIZE 25 | 26 | ; restore original registers 27 | pop rbp 28 | pop rsi 29 | pop rcx 30 | 31 | ; return from routine 32 | ret -------------------------------------------------------------------------------- /kernel/init/free.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;------------------------------------------------------------------------------- 6 | ; void 7 | kernel_init_free: 8 | ;----------------------------------------------------------------------- 9 | ; after last AP initialization, we can include bootloader memory 10 | ; to binary memory map and use it freely 11 | ;----------------------------------------------------------------------- 12 | 13 | ; memory map response structure 14 | mov rsi, qword [kernel_limine_memmap_request + LIMINE_MEMMAP_REQUEST.response] 15 | 16 | ; first entry of memory map 17 | xor ebx, ebx 18 | mov rdx, qword [rsi + LIMINE_MEMMAP_RESPONSE.entries] 19 | 20 | ; array for areas properties 21 | mov rbp, rsp 22 | 23 | .next: 24 | ; retrieve entry address 25 | mov rdi, qword [rdx + rbx * STD_SIZE_PTR_byte] 26 | 27 | ; type of LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE? 28 | cmp qword [rdi + LIMINE_MEMMAP_ENTRY.type], LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE 29 | jne .omit ; no 30 | 31 | ; remember adrea position and length 32 | push qword [rdi + LIMINE_MEMMAP_ENTRY.base] 33 | push qword [rdi + LIMINE_MEMMAP_ENTRY.length] 34 | 35 | .omit: 36 | ; next entry 37 | inc rbx 38 | 39 | ; end of entries? 40 | cmp rbx, qword [rsi + LIMINE_MEMMAP_RESPONSE.entry_count] 41 | jne .next ; no 42 | 43 | ;----------------------------------------------------------------------- 44 | ; at this point, we CANNOT use any Limine structure anymore! 45 | ; thats why we created array of RECLAIMABLE areas on stack... 46 | ;----------------------------------------------------------------------- 47 | 48 | ; amount of freed up pages 49 | xor eax, eax 50 | 51 | .area: 52 | ; end of array? 53 | cmp rsp, rbp 54 | je .end ; yes 55 | 56 | ; area size in pages 57 | pop rcx 58 | shr rcx, STD_SHIFT_PAGE 59 | 60 | ; area position 61 | mov rdi, qword [rsp] 62 | or rdi, qword [kernel_page_mirror] 63 | 64 | ; clean up 65 | call kernel_page_clean_few 66 | 67 | .lock: 68 | ; request an exclusive access 69 | mov dl, LOCK 70 | xchg byte [r8 + KERNEL.memory_semaphore], dl 71 | 72 | ; assigned? 73 | test dl, dl 74 | jnz .lock ; no 75 | 76 | ; extend binary memory map of those area pages 77 | add qword [r8 + KERNEL.page_total], rcx 78 | add qword [r8 + KERNEL.page_available], rcx 79 | 80 | ; amount of freed up pages 81 | add rax, rcx 82 | 83 | ; first page number of area 84 | pop rdx 85 | shr rdx, STD_SHIFT_PAGE 86 | 87 | .register: 88 | ; register inside binary memory map 89 | bts qword [r9], rdx 90 | 91 | ; next page 92 | inc rdx 93 | 94 | ; entire space is registered? 95 | dec rcx 96 | jnz .register ; no 97 | 98 | ; release access 99 | mov byte [r8 + KERNEL.memory_semaphore], UNLOCK 100 | 101 | ; next area from array 102 | jmp .area 103 | 104 | .end: 105 | ; prefix 106 | mov ecx, kernel_log_prefix_end - kernel_log_prefix 107 | mov rsi, kernel_log_prefix 108 | call driver_serial_string 109 | 110 | ; convert pages to KiB 111 | shl rax, STD_SHIFT_4 112 | 113 | ; show amount of released memory 114 | mov ebx, STD_NUMBER_SYSTEM_decimal 115 | xor ecx, ecx ; no prefix 116 | call driver_serial_value 117 | mov ecx, kernel_log_free_end - kernel_log_free 118 | mov rsi, kernel_log_free 119 | call driver_serial_string 120 | 121 | ; reload BSP processor 122 | jmp kernel_init_ap -------------------------------------------------------------------------------- /kernel/init/gdt.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;------------------------------------------------------------------------------- 6 | ; void 7 | kernel_init_gdt: 8 | ; preserve original registers 9 | push rcx 10 | push rdi 11 | 12 | ; prepare area for Global Descriptor Table 13 | mov ecx, TRUE 14 | call kernel_memory_alloc 15 | 16 | ; preserve pointer inside KERNEL environment 17 | mov qword [r8 + KERNEL.gdt_header + KERNEL_STRUCTURE_GDT_HEADER.base_address], rdi 18 | 19 | ; create code descriptor ring0 (CS) 20 | mov qword [rdi + KERNEL_STRUCTURE_GDT.cs_ring0 + KERNEL_STRUCTURE_GDT_ENTRY.access], KERNEL_GDT_FIELD_ACCESS_read_or_write | KERNEL_GDT_FIELD_ACCESS_executable | KERNEL_GDT_FIELD_ACCESS_code_or_data | KERNEL_GDT_FIELD_ACCESS_present 21 | mov qword [rdi + KERNEL_STRUCTURE_GDT.cs_ring0 + KERNEL_STRUCTURE_GDT_ENTRY.flags_and_limit_high], KERNEL_GDT_FIELD_FLAGS_long_mode << STD_MOVE_BYTE_half; 22 | 23 | ; create data descriptor ring0 (SS) 24 | mov qword [rdi + KERNEL_STRUCTURE_GDT.ss_ring0 + KERNEL_STRUCTURE_GDT_ENTRY.access], KERNEL_GDT_FIELD_ACCESS_read_or_write | KERNEL_GDT_FIELD_ACCESS_code_or_data | KERNEL_GDT_FIELD_ACCESS_present; 25 | mov qword [rdi + KERNEL_STRUCTURE_GDT.ss_ring0 + KERNEL_STRUCTURE_GDT_ENTRY.flags_and_limit_high], KERNEL_GDT_FIELD_FLAGS_long_mode << STD_MOVE_BYTE_half; 26 | 27 | ; create data descriptor ring3 (SS) 28 | mov qword [rdi + KERNEL_STRUCTURE_GDT.ss_ring3 + KERNEL_STRUCTURE_GDT_ENTRY.access], KERNEL_GDT_FIELD_ACCESS_read_or_write | KERNEL_GDT_FIELD_ACCESS_code_or_data | KERNEL_GDT_FIELD_ACCESS_level_3 | KERNEL_GDT_FIELD_ACCESS_present; 29 | mov qword [rdi + KERNEL_STRUCTURE_GDT.ss_ring3 + KERNEL_STRUCTURE_GDT_ENTRY.flags_and_limit_high], KERNEL_GDT_FIELD_FLAGS_long_mode << STD_MOVE_BYTE_half; 30 | 31 | ; create code descriptor ring3 (CS) 32 | mov qword [rdi + KERNEL_STRUCTURE_GDT.cs_ring3 + KERNEL_STRUCTURE_GDT_ENTRY.access], KERNEL_GDT_FIELD_ACCESS_read_or_write | KERNEL_GDT_FIELD_ACCESS_executable | KERNEL_GDT_FIELD_ACCESS_code_or_data | KERNEL_GDT_FIELD_ACCESS_level_3 | KERNEL_GDT_FIELD_ACCESS_present; 33 | mov qword [rdi + KERNEL_STRUCTURE_GDT.cs_ring3 + KERNEL_STRUCTURE_GDT_ENTRY.flags_and_limit_high], KERNEL_GDT_FIELD_FLAGS_long_mode << STD_MOVE_BYTE_half; 34 | 35 | ; configure header of Global Descriptor Table 36 | mov word [r8 + KERNEL.gdt_header + KERNEL_STRUCTURE_GDT_HEADER.limit], STD_PAGE_byte 37 | 38 | ; reload Global Descriptor Table 39 | lgdt [r8 + KERNEL.gdt_header] 40 | 41 | ; set proper descriptors 42 | call kernel_init_gdt_reload 43 | 44 | ; initialize stack pointer inside TSS table 45 | mov rdi, KERNEL_STACK_pointer 46 | mov qword [r8 + KERNEL.tss_table + KERNEL_STRUCTURE_TSS.rsp0], rdi 47 | 48 | ; restore original registers 49 | pop rdi 50 | pop rcx 51 | 52 | ; return from routine 53 | ret 54 | 55 | ;------------------------------------------------------------------------------ 56 | ; void 57 | kernel_init_gdt_reload: 58 | ; preserve original register 59 | push rax 60 | 61 | ; reload code descriptor 62 | push KERNEL_STRUCTURE_GDT.cs_ring0 63 | push .cs_reload 64 | retfq 65 | 66 | .cs_reload: 67 | ; reset unused selectors 68 | xor ax, ax 69 | mov fs, ax 70 | mov gs, ax 71 | 72 | ; reload global selectors of kernel 73 | mov ax, KERNEL_STRUCTURE_GDT.ss_ring0 74 | mov ds, ax ; data 75 | mov es, ax ; extra 76 | mov ss, ax ; stack 77 | 78 | ; restore original register 79 | pop rax 80 | 81 | ; return from routine 82 | ret -------------------------------------------------------------------------------- /kernel/init/idt.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;------------------------------------------------------------------------------- 6 | ; void 7 | kernel_init_idt: 8 | ; preserve original registers 9 | push rax 10 | push rbx 11 | push rcx 12 | push rdi 13 | 14 | ; prepare area for Interrupt Descriptor Table 15 | mov ecx, TRUE 16 | call kernel_memory_alloc 17 | 18 | ; preserve pointer inside KERNEL environment 19 | mov qword [r8 + KERNEL.idt_header + KERNEL_STRUCTURE_IDT_HEADER.base_address], rdi 20 | 21 | ; default IDT Entry type 22 | mov bx, KERNEL_IDT_TYPE_gate_interrupt 23 | 24 | ; attach CPU exception handlers 25 | mov rax, kernel_idt_exception_divide_by_zero 26 | mov ecx, 0 27 | call kernel_idt_mount 28 | mov rax, kernel_idt_exception_debug 29 | mov ecx, 1 30 | call kernel_idt_mount 31 | mov rax, kernel_idt_exception_breakpoint 32 | mov ecx, 3 33 | call kernel_idt_mount 34 | mov rax, kernel_idt_exception_overflow 35 | mov ecx, 4 36 | call kernel_idt_mount 37 | mov rax, kernel_idt_exception_boud_range_exceeded 38 | mov ecx, 5 39 | call kernel_idt_mount 40 | mov rax, kernel_idt_exception_invalid_opcode 41 | mov ecx, 6 42 | call kernel_idt_mount 43 | mov rax, kernel_idt_exception_device_not_available 44 | mov ecx, 7 45 | call kernel_idt_mount 46 | mov rax, kernel_idt_exception_double_fault 47 | mov ecx, 8 48 | call kernel_idt_mount 49 | mov rax, kernel_idt_exception_coprocessor_segment_overrun 50 | mov ecx, 9 51 | call kernel_idt_mount 52 | mov rax, kernel_idt_exception_invalid_tss 53 | mov ecx, 10 54 | call kernel_idt_mount 55 | mov rax, kernel_idt_exception_segment_not_present 56 | mov ecx, 11 57 | call kernel_idt_mount 58 | mov rax, kernel_idt_exception_stack_segment_fault 59 | mov ecx, 12 60 | call kernel_idt_mount 61 | mov rax, kernel_idt_exception_general_protection_fault 62 | mov ecx, 13 63 | call kernel_idt_mount 64 | mov rax, kernel_idt_exception_page_fault 65 | mov ecx, 14 66 | call kernel_idt_mount 67 | mov rax, kernel_idt_exception_x87_floating_point 68 | mov ecx, 16 69 | call kernel_idt_mount 70 | mov rax, kernel_idt_exception_alignment_check 71 | mov ecx, 17 72 | call kernel_idt_mount 73 | mov rax, kernel_idt_exception_machine_check 74 | mov ecx, 18 75 | call kernel_idt_mount 76 | mov rax, kernel_idt_exception_simd_floating_point 77 | mov ecx, 19 78 | call kernel_idt_mount 79 | mov rax, kernel_idt_exception_virtualization 80 | mov ecx, 20 81 | call kernel_idt_mount 82 | mov rax, kernel_idt_exception_control_protection 83 | mov ecx, 21 84 | call kernel_idt_mount 85 | mov rax, kernel_idt_exception_hypervisor_injection 86 | mov ecx, 28 87 | call kernel_idt_mount 88 | mov rax, kernel_idt_exception_vmm_communication 89 | mov ecx, 29 90 | call kernel_idt_mount 91 | mov rax, kernel_idt_exception_security 92 | mov ecx, 30 93 | call kernel_idt_mount 94 | 95 | ; attach default hardware interrupt handler 96 | mov rax, kernel_idt_interrupt 97 | 98 | ; IDT Entry type 99 | mov bx, KERNEL_IDT_TYPE_irq 100 | 101 | ; first hardware IRQ number 102 | mov cl, KERNEL_IDT_IRQ_offset 103 | 104 | .loop: 105 | ; connect 106 | call kernel_idt_mount 107 | 108 | ; next entry 109 | inc cl 110 | 111 | ; all interrputs connected? 112 | cmp cl, KERNEL_IDT_IRQ_offset + 16 113 | jb .loop ; no 114 | 115 | ; attach interrupt handler for "spurious interrupt" 116 | mov rax, kernel_idt_interrupt_spurious 117 | mov bx, KERNEL_IDT_TYPE_irq 118 | mov ecx, 255 119 | call kernel_idt_mount 120 | 121 | ; configure header of Interrupt Descriptor Table 122 | mov word [r8 + KERNEL.idt_header + KERNEL_STRUCTURE_IDT_HEADER.limit], STD_PAGE_byte 123 | 124 | ; load new Interrupt Descriptor Table 125 | lidt [r8 + KERNEL.idt_header] 126 | 127 | ; restore original registers 128 | pop rdi 129 | pop rcx 130 | pop rbx 131 | pop rax 132 | 133 | ; return from routine 134 | ret -------------------------------------------------------------------------------- /kernel/init/ipc.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;------------------------------------------------------------------------------- 6 | ; void 7 | kernel_init_ipc: 8 | ; preserve original registers 9 | push rcx 10 | push rdi 11 | 12 | ; prepare the space for the stream space 13 | mov rcx, MACRO_PAGE_ALIGN_UP( KERNEL_IPC_limit * STD_IPC_STRUCTURE.SIZE ) 14 | shr rcx, STD_SHIFT_PAGE 15 | call kernel_memory_alloc 16 | 17 | ; preserve pointer inside KERNEL environment 18 | mov qword [r8 + KERNEL.ipc_base_address], rdi 19 | 20 | ; restore original registers 21 | pop rdi 22 | pop rcx 23 | 24 | ; return from routine 25 | ret -------------------------------------------------------------------------------- /kernel/init/library.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;------------------------------------------------------------------------------- 6 | ; void 7 | kernel_init_library: 8 | ; preserve original registers 9 | push rcx 10 | push rdi 11 | 12 | ; assign space for library list 13 | mov rcx, ((KERNEL_LIBRARY_limit * KERNEL_LIBRARY_STRUCTURE.SIZE) + ~STD_PAGE_mask) >> STD_SHIFT_PAGE 14 | call kernel_memory_alloc 15 | 16 | ; save pointer to library list 17 | mov qword [r8 + KERNEL.library_base_address], rdi 18 | 19 | ; assign memory space for binary memory map with same size as kernels 20 | mov rcx, qword [r8 + KERNEL.page_limit] 21 | shr rcx, STD_SHIFT_8 ; 8 pages per Byte 22 | add rcx, ~STD_PAGE_mask ; align up to page boundaries 23 | shr rcx, STD_SHIFT_PAGE ; convert to pages 24 | call kernel_memory_alloc 25 | 26 | ; save pointer to library memory map 27 | mov qword [r8 + KERNEL.library_memory_map_address], rdi 28 | 29 | ; fill memory map with available pages 30 | mov rax, STD_MAX_unsigned 31 | shl rcx, STD_SHIFT_512 32 | rep stosq 33 | 34 | ; restore original registers 35 | pop rdi 36 | pop rcx 37 | 38 | ; return from routine 39 | ret -------------------------------------------------------------------------------- /kernel/init/limine.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | string_error_framebuffer: 6 | db "I See a Darkness.\n", STD_ASCII_TERMINATOR 7 | 8 | string_error_memmap: 9 | db "Houston, we have a problem.\n", STD_ASCII_TERMINATOR 10 | 11 | string_error_rsdp: 12 | db "Hello Darkness, My Old Friend.\n", STD_ASCII_TERMINATOR 13 | 14 | string_error_kernel: 15 | db "Whisky.\n", STD_ASCII_TERMINATOR 16 | 17 | string_error_module: 18 | db "Where Are My Testicles, Summer?\n", STD_ASCII_TERMINATOR 19 | 20 | ;------------------------------------------------------------------------------- 21 | ; void 22 | kernel_init_limine: 23 | ; preserve original registers 24 | push rdi 25 | 26 | ;---------------------------------------------------------------------- 27 | 28 | ; properties of framebuffer request 29 | mov rdi, qword [kernel_limine_framebuffer_request + LIMINE_FRAMEBUFFER_REQUEST.response] 30 | 31 | ; linear framebuffer is available? 32 | test rdi, rdi 33 | jz .error_framebuffer ; no 34 | 35 | ; at least 1 frame buffer available? 36 | cmp qword [rdi + LIMINE_FRAMEBUFFER_RESPONSE.framebuffer_count], EMPTY 37 | je .error_framebuffer ; nothing 38 | 39 | ; properties of framebuffer response 40 | mov rdi, qword [rdi + LIMINE_FRAMEBUFFER_RESPONSE.framebuffers] 41 | mov rdi, qword [rdi + INIT] ; properties of first framebuffer 42 | 43 | ; with 32 bits per pixel? 44 | cmp word [rdi + LIMINE_FRAMEBUFFER.bpp], STD_VIDEO_DEPTH_bit 45 | jne .error_framebuffer ; different 46 | 47 | ;---------------------------------------------------------------------- 48 | 49 | ; properties of memory map request 50 | mov rdi, qword [kernel_limine_memmap_request + LIMINE_MEMMAP_REQUEST.response] 51 | 52 | ; memory map provided? 53 | test rdi, rdi 54 | jz .error_memmap ; no 55 | 56 | ; no entries? 57 | cmp qword [rdi + LIMINE_MEMMAP_RESPONSE.entry_count], EMPTY 58 | je .error_memmap ; yep 59 | 60 | ;---------------------------------------------------------------------- 61 | 62 | ; properties of RSDP request 63 | mov rdi, qword [kernel_limine_rsdp_request + LIMINE_RSDP_REQUEST.response] 64 | 65 | ; RSDP pointer available? 66 | test rdi, rdi 67 | jz .error_rsdp ; no 68 | 69 | ; located? 70 | cmp qword [rdi + LIMINE_RSDP_RESPONSE.address], EMPTY 71 | je .error_rsdp ; nothing there 72 | 73 | ;---------------------------------------------------------------------- 74 | 75 | ; information about kernel? 76 | cmp qword [kernel_limine_kernel_file_request + LIMINE_KERNEL_FILE_REQUEST.response], EMPTY 77 | je .error_kernel ; no 78 | cmp qword [kernel_limine_kernel_address_request + LIMINE_KERNEL_FILE_ADDRESS_REQUEST.response], EMPTY 79 | je .error_kernel ; also no 80 | 81 | ;---------------------------------------------------------------------- 82 | 83 | ; properties of module request 84 | mov rdi, qword [kernel_limine_module_request + LIMINE_MODULE_REQUEST.response] 85 | 86 | ; modules attached? 87 | test rdi, rdi 88 | jz .error_module ; no 89 | 90 | ; at least 1? 91 | cmp qword [rdi + LIMINE_MODULE_RESPONSE.module_count], EMPTY 92 | je .error_module ; nope 93 | 94 | ; restore original registers 95 | pop rdi 96 | 97 | ; return from routine 98 | ret 99 | 100 | .error_framebuffer: 101 | ; show error 102 | mov rdi, string_error_framebuffer 103 | call kernel_log 104 | 105 | ; hold the door 106 | jmp $ 107 | 108 | .error_memmap: 109 | ; show error 110 | mov rdi, string_error_memmap 111 | call kernel_log 112 | 113 | ; hold the door 114 | jmp $ 115 | 116 | .error_rsdp: 117 | ; show error 118 | mov rdi, string_error_rsdp 119 | call kernel_log 120 | 121 | ; hold the door 122 | jmp $ 123 | 124 | .error_kernel: 125 | ; show error 126 | mov rdi, string_error_kernel 127 | call kernel_log 128 | 129 | ; hold the door 130 | jmp $ 131 | 132 | .error_module: 133 | ; show error 134 | mov rdi, string_error_module 135 | call kernel_log 136 | 137 | ; hold the door 138 | jmp $ -------------------------------------------------------------------------------- /kernel/init/limine.inc: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | %ifndef LIMINE 6 | %define LIMINE_COMMON_MAGIC 0xc7b1dd30df4c8b88, 0x0a82e883a194f07b 7 | 8 | %define LIMINE_FRAMEBUFFER_MAGIC LIMINE_COMMON_MAGIC, 0x9d5827dcd881dd75, 0xa3148604f6fab11b 9 | %define LIMINE_MEMMAP_MAGIC LIMINE_COMMON_MAGIC, 0x67cf3d9d378a806f, 0xe304acdfc50c3c62 10 | %define LIMINE_RSDP_MAGIC LIMINE_COMMON_MAGIC, 0xc5e77b6b397e7b43, 0x27637845accdcf3c 11 | %define LIMINE_KERNEL_FILE_MAGIC LIMINE_COMMON_MAGIC, 0xad97e90e83f1ed67, 0x31eb5d1c5ff23b69 12 | %define LIMINE_KERNEL_ADDRESS_MAGIC LIMINE_COMMON_MAGIC, 0x71ba76863cc55f63, 0xb2644a48c516a487 13 | %define LIMINE_SMP_MAGIC LIMINE_COMMON_MAGIC, 0x95a67b819a1b857e, 0xa0b61b723b6a73e0 14 | %define LIMINE_MODULE_MAGIC LIMINE_COMMON_MAGIC, 0x3e7e279702be32af, 0xca1c4f3bd1280cee 15 | 16 | %define LIMINE_MEMMAP_USABLE 0 17 | %define LIMINE_MEMMAP_RESERVED 1 18 | %define LIMINE_MEMMAP_ACPI_RECLAIMABLE 2 19 | %define LIMINE_MEMMAP_ACPI_NVS 3 20 | %define LIMINE_MEMMAP_BAD_MEMORY 4 21 | %define LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE 5 22 | %define LIMINE_MEMMAP_KERNEL_AND_MODULES 6 23 | %define LIMINE_MEMMAP_FRAMEBUFFER 7 24 | 25 | struc LIMINE_FILE 26 | .revision resq 1 27 | .address resq 1 28 | .size resq 1 29 | .path resq 1 30 | .cmd resq 1 31 | .unused_by_cyjon: 32 | endstruc 33 | 34 | struc LIMINE_FRAMEBUFFER 35 | .address resq 1 36 | .width resq 1 37 | .height resq 1 38 | .pitch resq 1 39 | .bpp resw 1 40 | .unused_by_cyjon: 41 | endstruc 42 | 43 | struc LIMINE_FRAMEBUFFER_RESPONSE 44 | .revision resq 1 45 | .framebuffer_count resq 1 46 | .framebuffers resq 1 47 | 48 | struc LIMINE_FRAMEBUFFER_REQUEST 49 | .id resq 4 50 | .revision resq 1 51 | .response resq 1 52 | endstruc 53 | 54 | struc LIMINE_MEMMAP_ENTRY 55 | .base resq 1 56 | .length resq 1 57 | .type resq 1 58 | .SIZE: 59 | endstruc 60 | 61 | struc LIMINE_MEMMAP_RESPONSE 62 | .revision resq 1 63 | .entry_count resq 1 64 | .entries resq 1 65 | 66 | struc LIMINE_MEMMAP_REQUEST 67 | .id resq 4 68 | .revision resq 1 69 | .response resq 1 70 | endstruc 71 | 72 | struc LIMINE_RSDP_RESPONSE 73 | .revision resq 1 74 | .address resq 1 75 | endstruc 76 | 77 | struc LIMINE_RSDP_REQUEST 78 | .id resq 4 79 | .revision resq 1 80 | .response resq 1 81 | endstruc 82 | 83 | struc LIMINE_KERNEL_FILE_RESPONSE 84 | .revision resq 1 85 | .kernel_file resq 1 86 | endstruc 87 | 88 | struc LIMINE_KERNEL_FILE_REQUEST 89 | .id resq 4 90 | .revision resq 1 91 | .response resq 1 92 | endstruc 93 | 94 | struc LIMINE_KERNEL_FILE_ADDRESS_RESPONCE 95 | .revision resq 1 96 | .physical_base resq 1 97 | .virtual_base resq 1 98 | endstruc 99 | 100 | struc LIMINE_KERNEL_FILE_ADDRESS_REQUEST 101 | .id resq 4 102 | .revision resq 1 103 | .response resq 1 104 | endstruc 105 | 106 | struc LIMINE_SMP_RESPONSE 107 | .revision resq 1 108 | .flags resd 1 109 | .bsp_lapic_id resd 1 110 | .cpu_count resq 1 111 | .cpu_info resq 1 112 | endstruc 113 | 114 | struc LIMINE_SMP_REQUEST 115 | .id resq 4 116 | .revision resq 1 117 | .response resq 1 118 | .flags resq 1 119 | endstruc 120 | 121 | struc LIMINE_SMP_INFO 122 | .processor_id resd 1 123 | .lapic_id resd 1 124 | .reserved resq 1 125 | .goto_address resq 1 126 | .extra_argument resq 1 127 | endstruc 128 | 129 | struc LIMINE_MODULE_RESPONSE 130 | .revision resq 1 131 | .module_count resq 1 132 | .modules resq 1 133 | endstruc 134 | 135 | struc LIMINE_MODULE_REQUEST 136 | .id resq 4 137 | .revision resq 1 138 | .response resq 1 139 | endstruc 140 | %endif -------------------------------------------------------------------------------- /kernel/init/memory.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;------------------------------------------------------------------------------- 6 | ; void 7 | kernel_init_memory: 8 | ; preserve original registers 9 | push rax 10 | push rbx 11 | push rcx 12 | push rdx 13 | push rsi 14 | push rdi 15 | 16 | ; global kernel environment variables/functions/rountines 17 | mov r8, qword [kernel] 18 | 19 | ; place binary memory map after global kernel environment variables/functions/rountines (aligned to page boundaries) 20 | mov qword [r8 + KERNEL.memory_base_address], r8 21 | add qword [r8 + KERNEL.memory_base_address], (KERNEL.SIZE + ~STD_PAGE_mask) & STD_PAGE_mask 22 | 23 | ; properties of binary memory map 24 | mov r9, qword [r8 + KERNEL.memory_base_address] 25 | 26 | ;---------------------------------------------------------------------- 27 | 28 | ; properties of memory map response 29 | mov rsi, qword [kernel_limine_memmap_request + LIMINE_MEMMAP_REQUEST.response] 30 | 31 | ; amount of entries inside memory map 32 | mov rcx, qword [rsi + LIMINE_MEMMAP_RESPONSE.entry_count] 33 | 34 | ; list of memory map entires 35 | mov rsi, qword [rsi + LIMINE_MEMMAP_RESPONSE.entries] 36 | 37 | .entry: 38 | ; parse "next" entry? 39 | dec rcx 40 | js .done ; no 41 | 42 | ; retrieve entry 43 | mov rax, qword [rsi + rcx * STD_SIZE_PTR_byte] 44 | 45 | ; USABLE, BOOTLOADER_RECLAIMABLE, KERNEL_AND_MODULES or ACPI_RECLAIMABLE memory area? 46 | cmp qword [rax + LIMINE_MEMMAP_ENTRY.type], LIMINE_MEMMAP_USABLE 47 | je .parse 48 | cmp qword [rax + LIMINE_MEMMAP_ENTRY.type], LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE 49 | je .parse 50 | cmp qword [rax + LIMINE_MEMMAP_ENTRY.type], LIMINE_MEMMAP_KERNEL_AND_MODULES 51 | je .parse 52 | cmp qword [rax + LIMINE_MEMMAP_ENTRY.type], LIMINE_MEMMAP_ACPI_RECLAIMABLE 53 | jne .entry ; next entry 54 | 55 | .parse: 56 | ; calculate farthest part of memory area for use 57 | mov rdx, qword [rax + LIMINE_MEMMAP_ENTRY.base] 58 | add rdx, qword [rax + LIMINE_MEMMAP_ENTRY.length] 59 | shr rdx, STD_SHIFT_PAGE 60 | 61 | ; further than previous? 62 | cmp rdx, qword [r8 + KERNEL.page_limit] 63 | jb .below ; no 64 | 65 | ; remember area 66 | mov qword [r8 + KERNEL.page_limit], rdx 67 | 68 | .below: 69 | ; keep number of pages registered in the binary memory map 70 | mov rdx, qword [rax + LIMINE_MEMMAP_ENTRY.length] 71 | shr rdx, STD_SHIFT_PAGE 72 | add qword [r8 + KERNEL.page_total], rdx 73 | 74 | ; USABLE memory area? 75 | cmp qword [rax + LIMINE_MEMMAP_ENTRY.type], LIMINE_MEMMAP_USABLE 76 | jne .entry ; no, next entry 77 | 78 | ; add memory area to available memory 79 | add qword [r8 + KERNEL.page_available], rdx 80 | 81 | ; first page number of area 82 | mov rdi, qword [rax + LIMINE_MEMMAP_ENTRY.base] 83 | shr rdi, STD_SHIFT_PAGE 84 | 85 | .fill: 86 | ; register inside binary memory map 87 | bts qword [r9], rdi 88 | 89 | ; next page 90 | inc rdi 91 | 92 | ; entire area is registered? 93 | dec rdx 94 | jnz .fill ; no 95 | 96 | ; next entry 97 | jmp .entry 98 | 99 | .done: 100 | ; round up kernel page limit up to Byte 101 | mov rax, qword [r8 + KERNEL.page_limit] 102 | xor edx, edx 103 | mov rcx, STD_MOVE_BYTE 104 | div rcx 105 | jz .limited ; already done 106 | 107 | ; apply new limit 108 | add qword [r8 + KERNEL.page_limit], STD_MOVE_BYTE 109 | sub qword [r8 + KERNEL.page_limit], rdx 110 | 111 | .limited: 112 | ; first page number of reserved area (global kernel environment variables/functions/rountines and binary memory map) 113 | mov rdi, ~KERNEL_PAGE_mirror 114 | and rdi, r8 115 | shr rdi, STD_SHIFT_PAGE 116 | 117 | ; calculate length of reserved area in pages 118 | mov rdx, qword [r8 + KERNEL.page_limit] 119 | shr rdx, STD_SHIFT_8 ; convert Bits to Bytes 120 | inc rdx ; add semaphore area 121 | add rdx, ~STD_PAGE_mask ; align up to page boundary 122 | add rdx, r9 ; add position of binary memory map 123 | mov rax, ~KERNEL_PAGE_mirror 124 | and rdx, rax ; convert to physical address 125 | shr rdx, STD_SHIFT_PAGE ; change to pages 126 | 127 | ; so, our available pages are less by 128 | sub rdx, rdi 129 | sub qword [r8 + KERNEL.page_available], rdx 130 | 131 | .mark: 132 | ; mark page as unavailable 133 | btr qword [r9], rdi 134 | 135 | ; next page 136 | inc rdi 137 | 138 | ; unavailable space marked? 139 | dec rdx 140 | jnz .mark ; no 141 | 142 | ; restore original registers 143 | pop rdi 144 | pop rsi 145 | pop rdx 146 | pop rcx 147 | pop rbx 148 | pop rax 149 | 150 | ; return from routine 151 | ret -------------------------------------------------------------------------------- /kernel/init/page.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;------------------------------------------------------------------------------- 6 | ; void 7 | kernel_init_page: 8 | ; preserve original registers 9 | push rax 10 | push rbx 11 | push rcx 12 | push rdx 13 | push rsi 14 | push rdi 15 | push r11 16 | 17 | ; allow all BS/A processors to write on read-only pages inside ring0 18 | mov rax, cr0 19 | and rax, ~(1 << 16) 20 | mov cr0, rax 21 | 22 | ; alloc 1 page for PML4 kernel environment array 23 | mov ecx, TRUE 24 | call kernel_memory_alloc 25 | mov qword [r8 + KERNEL.page_base_address], rdi 26 | 27 | ; default flags of every page 28 | mov bx, KERNEL_PAGE_FLAG_present | KERNEL_PAGE_FLAG_write; 29 | 30 | ; all paging procedures use R11 register for PML4 address 31 | mov r11, rdi 32 | 33 | ;--------------------------------------------------------------------- 34 | 35 | ; properties of memory map response 36 | mov rsi, qword [kernel_limine_memmap_request + LIMINE_MEMMAP_REQUEST.response] 37 | 38 | ; amount of entries inside memory map 39 | mov rcx, qword [rsi + LIMINE_MEMMAP_RESPONSE.entry_count] 40 | 41 | ; list of memory map entires 42 | mov rsi, qword [rsi + LIMINE_MEMMAP_RESPONSE.entries] 43 | 44 | .entry: 45 | ; parse "next" entry? 46 | dec rcx 47 | js .done ; no 48 | 49 | ; retrieve entry 50 | mov rax, qword [rsi + rcx * STD_SIZE_PTR_byte] 51 | 52 | ; USABLE, BOOTLOADER_RECLAIMABLE, KERNEL_AND_MODULES, FRAMEBUFFER or ACPI_RECLAIMABLE memory area? 53 | cmp qword [rax + LIMINE_MEMMAP_ENTRY.type], LIMINE_MEMMAP_USABLE 54 | je .parse 55 | cmp qword [rax + LIMINE_MEMMAP_ENTRY.type], LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE 56 | je .parse 57 | cmp qword [rax + LIMINE_MEMMAP_ENTRY.type], LIMINE_MEMMAP_KERNEL_AND_MODULES 58 | je .parse 59 | cmp qword [rax + LIMINE_MEMMAP_ENTRY.type], LIMINE_MEMMAP_FRAMEBUFFER 60 | je .parse 61 | cmp qword [rax + LIMINE_MEMMAP_ENTRY.type], LIMINE_MEMMAP_ACPI_RECLAIMABLE 62 | jne .entry ; next entry 63 | 64 | .parse: 65 | ; preserve original registers 66 | push rcx 67 | push rsi 68 | 69 | ; size of area in pages 70 | mov rcx, qword [rax + LIMINE_MEMMAP_ENTRY.length] 71 | shr rcx, STD_SHIFT_PAGE 72 | 73 | ; physical area to logical area 74 | mov rsi, qword [rax + LIMINE_MEMMAP_ENTRY.base] 75 | mov rax, KERNEL_PAGE_mirror 76 | or rax, rsi 77 | 78 | ; map memory area to kernel paging arrays 79 | call kernel_page_map 80 | 81 | ; restore original registers 82 | pop rsi 83 | pop rcx 84 | 85 | ; next entry 86 | jmp .entry 87 | 88 | .done: 89 | ;--------------------------------------------------------------------- 90 | 91 | ; every controller space is about 4096 Bytes 92 | mov ecx, STD_PAGE_page 93 | 94 | ; map LAPIC controller space 95 | mov rax, qword [r8 + KERNEL.lapic_base_address] 96 | mov rsi, ~KERNEL_PAGE_mirror 97 | and rsi, rax 98 | call kernel_page_map 99 | 100 | ; map I/O APIC controller space 101 | mov rax, qword [r8 + KERNEL.io_apic_base_address] 102 | mov rsi, ~KERNEL_PAGE_mirror 103 | and rsi, rax 104 | call kernel_page_map 105 | 106 | ; now something harder ------------------------------------------------ 107 | 108 | ; kernel file properties 109 | mov rdi, qword [kernel_limine_kernel_file_request + LIMINE_KERNEL_FILE_REQUEST.response] 110 | mov rdi, qword [rdi + LIMINE_KERNEL_FILE_RESPONSE.kernel_file] 111 | mov rdi, qword [rdi + LIMINE_FILE.address] 112 | 113 | ; number of hedaers in ELF structure 114 | mov cx, word [rdi + LIB_ELF_STRUCTURE.h_entry_count] 115 | 116 | ; move pointer to first header entry 117 | add rdi, qword [rdi + LIB_ELF_STRUCTURE.headers_offset] 118 | 119 | ; get pointer to kernel address response 120 | mov rdx, qword [kernel_limine_kernel_address_request + LIMINE_KERNEL_FILE_ADDRESS_REQUEST.response] 121 | 122 | .header: 123 | ; entry doesn't have type set? 124 | cmp byte [rdi + LIB_ELF_STRUCTURE_HEADER.type], EMPTY 125 | je .next ; yes 126 | 127 | ; entry have EMPTY length? 128 | cmp byte [rdi + LIB_ELF_STRUCTURE_HEADER.memory_size], EMPTY 129 | je .next ; yes 130 | 131 | ; preserve original registers 132 | push rcx 133 | 134 | ; segment length 135 | mov rcx, ~KERNEL_BASE_address 136 | and rcx, qword [rdi + LIB_ELF_STRUCTURE_HEADER.virtual_address] 137 | add rcx, qword [rdi + LIB_ELF_STRUCTURE_HEADER.memory_size] 138 | MACRO_PAGE_ALIGN_UP_REGISTER rcx 139 | shr rcx, STD_SHIFT_PAGE ; convert to pages 140 | 141 | ; segment offset 142 | mov rsi, ~KERNEL_BASE_address 143 | and rsi, qword [rdi + LIB_ELF_STRUCTURE_HEADER.virtual_address] 144 | and si, STD_PAGE_mask 145 | 146 | ; kernel segment target 147 | mov rax, KERNEL_BASE_address 148 | add rax, rsi 149 | 150 | ; kernel segment source 151 | add rsi, qword [rdx + LIMINE_KERNEL_FILE_ADDRESS_RESPONCE.physical_base] 152 | 153 | ; default flags of kernel segment 154 | mov bx, KERNEL_PAGE_FLAG_present 155 | 156 | ; update with additional flag (if exist) 157 | test dword [rdi + LIB_ELF_STRUCTURE_HEADER.flags], LIB_ELF_FLAG_write 158 | jnz .default ; no 159 | 160 | ; data segment 161 | or bx, KERNEL_PAGE_FLAG_write 162 | 163 | .default: 164 | ; map segment to kernel paging arrays 165 | call kernel_page_map 166 | 167 | ; restore original registers 168 | pop rcx 169 | 170 | .next: 171 | ; next entry 172 | add rdi, LIB_ELF_STRUCTURE_HEADER.SIZE 173 | 174 | ; some entries left? 175 | dec cx 176 | jns .header ; yes 177 | 178 | .end: 179 | ;--------------------------------------------------------------------- 180 | 181 | ; and last thing, create kernel stack area 182 | mov rax, KERNEL_STACK_address 183 | mov ecx, KERNEL_STACK_page 184 | call kernel_page_alloc 185 | 186 | ; restore original registers 187 | pop r11 188 | pop rdi 189 | pop rsi 190 | pop rdx 191 | pop rcx 192 | pop rbx 193 | pop rax 194 | 195 | ; return from routine 196 | ret -------------------------------------------------------------------------------- /kernel/init/smp.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;------------------------------------------------------------------------------- 6 | ; void 7 | kernel_init_smp: 8 | ; SMP specification available? 9 | cmp qword [kernel_limine_smp_request + LIMINE_SMP_REQUEST.response], EMPTY 10 | je .alone ; no 11 | 12 | ; initialize all available APs on host 13 | mov rsi, qword [kernel_limine_smp_request + LIMINE_SMP_REQUEST.response] 14 | 15 | ; set amount of APs and set pointer to first entry 16 | mov rcx, qword [rsi + LIMINE_SMP_RESPONSE.cpu_count] 17 | mov rsi, qword [rsi + LIMINE_SMP_RESPONSE.cpu_info] 18 | 19 | ; ID of current CPU (BSP) 20 | call kernel_lapic_id 21 | 22 | .next: 23 | ; entries left 24 | dec rcx 25 | js .alone ; no more APs 26 | 27 | ; properties of entry 28 | mov rdi, qword [rsi + rcx * STD_SIZE_PTR_byte] 29 | 30 | ; it's the BSP? 31 | cmp dword [rdi + LIMINE_SMP_INFO.lapic_id], eax 32 | je .next ; yes 33 | 34 | ; set jump point of this AP 35 | mov qword [rdi + LIMINE_SMP_INFO.goto_address], kernel_init_ap 36 | 37 | ; AP is running 38 | inc qword [kernel_smp_count] 39 | 40 | .wait: 41 | ; wait for AP initialization 42 | mov rbx, qword [r8 + KERNEL.cpu_count] 43 | cmp rbx, qword [kernel_smp_count] 44 | jne .wait 45 | 46 | ; current AP have higest ID? 47 | mov ebx, dword [rdi + LIMINE_SMP_INFO.lapic_id] 48 | cmp ebx, dword [r8 + KERNEL.lapic_last_id] 49 | jb .next ; no 50 | 51 | ; remember CPU ID 52 | mov dword [r8 + KERNEL.lapic_last_id], ebx 53 | 54 | ; next AP from list 55 | jmp .next 56 | 57 | .alone: 58 | ; if additional APs were initialized 59 | cmp qword [kernel_smp_count], EMPTY 60 | je .free ; no 61 | 62 | ; prefix 63 | mov ecx, kernel_log_prefix_end - kernel_log_prefix 64 | mov rsi, kernel_log_prefix 65 | call driver_serial_string 66 | 67 | ; number of APs initialized 68 | mov rax, qword [kernel_smp_count] 69 | mov ebx, STD_NUMBER_SYSTEM_decimal 70 | xor ecx, ecx ; no prefix 71 | xor dl, dl ; value unsigned 72 | call driver_serial_value 73 | mov ecx, kernel_log_smp_end - kernel_log_smp 74 | mov rsi, kernel_log_smp 75 | call driver_serial_string 76 | 77 | .free: 78 | ; free up reclaimable memory 79 | jmp kernel_init_free -------------------------------------------------------------------------------- /kernel/init/storage.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;------------------------------------------------------------------------------- 6 | ; void 7 | kernel_init_storage: 8 | ; preserve original registers 9 | push rax 10 | push rbx 11 | push rcx 12 | push rdx 13 | push rsi 14 | push rdi 15 | push r9 16 | push r11 17 | 18 | ; modules available? 19 | cmp qword [kernel_limine_module_request + LIMINE_MODULE_REQUEST.response], EMPTY 20 | je .error ; no 21 | 22 | ; kernel task properties 23 | call kernel_task_active 24 | 25 | ; assign space for storage list 26 | mov ecx, ((KERNEL_STORAGE_limit * KERNEL_STORAGE_STRUCTURE.SIZE) + ~STD_PAGE_mask) >> STD_SHIFT_PAGE 27 | call kernel_memory_alloc 28 | 29 | ; save pointer to storage list 30 | mov qword [r8 + KERNEL.storage_base_address], rdi 31 | 32 | ; pointer of modules response structure 33 | mov rbx, qword [kernel_limine_module_request + LIMINE_MODULE_REQUEST.response] 34 | 35 | ; first entry of modules list 36 | xor eax, eax 37 | mov rdx, qword [rbx + LIMINE_MODULE_RESPONSE.modules] 38 | 39 | .next: 40 | ; retrieve entry address 41 | mov r11, qword [rdx + rax * STD_SIZE_PTR_byte] 42 | 43 | ;----------------------------------------------------------------------- 44 | ; VFS module? 45 | ;---------------------------------------------------------------------- 46 | 47 | ; properties of module 48 | mov rcx, qword [r11 + LIMINE_FILE.size] 49 | mov rsi, qword [r11 + LIMINE_FILE.address] 50 | 51 | ; preserve module id 52 | push rax 53 | 54 | ; magic identificator exist? 55 | cmp dword [rsi + rcx - LIB_VFS_length], LIB_VFS_magic 56 | jne .no_vfs ; no 57 | 58 | ; register module as memory storage 59 | mov al, KERNEL_STORAGE_TYPE_memory 60 | call kernel_storage_register 61 | 62 | ; all device slots are used? 63 | test rdi, rdi 64 | jz .no_vfs ; ignore device 65 | 66 | ; set device properties 67 | mov qword [rdi + KERNEL_STORAGE_STRUCTURE.device_blocks], rcx 68 | mov qword [rdi + KERNEL_STORAGE_STRUCTURE.device_first_block], rsi 69 | mov qword [rdi + KERNEL_STORAGE_STRUCTURE.storage_file], kernel_storage_file 70 | mov qword [rdi + KERNEL_STORAGE_STRUCTURE.storage_read], kernel_storage_read 71 | 72 | ; initialize VFS storage 73 | call lib_vfs_init 74 | 75 | .no_vfs: 76 | ; restore module id 77 | pop rax 78 | 79 | ; next module? 80 | inc rax 81 | cmp rax, qword [rbx + LIMINE_MODULE_RESPONSE.module_count] 82 | jb .next ; yes 83 | 84 | ;----------------------------------------------------------------------- 85 | ; which storage device contains system files? 86 | ;----------------------------------------------------------------------- 87 | 88 | ; limit of devices 89 | mov rcx, KERNEL_STORAGE_limit 90 | 91 | ; devices list base address 92 | mov rax, qword [r8 + KERNEL.storage_base_address] 93 | 94 | .storage: 95 | ; no more devices? 96 | dec rcx 97 | js .error ; Geralt: Hmmm... 98 | 99 | ; device exist? 100 | cmp byte [rax + KERNEL_STORAGE_STRUCTURE.device_type], EMPTY 101 | jne .files ; yes 102 | 103 | ; next slot 104 | add rax, KERNEL_STORAGE_STRUCTURE.SIZE 105 | 106 | ; next storage 107 | jmp .storage 108 | 109 | .files: 110 | ; preserve original register 111 | push rax 112 | push rcx 113 | 114 | ; local structure of file descriptor 115 | sub rsp, KERNEL_STORAGE_STRUCTURE_FILE.SIZE 116 | mov rbp, rsp ; pointer of file descriptor 117 | 118 | ; change storage pointer to ID 119 | sub rax, qword [r8 + KERNEL.storage_base_address] 120 | shr rax, KERNEL_STORAGE_STRUCTURE_SIZE_shift 121 | 122 | ; search for "init" file on storage device 123 | movzx ecx, byte [kernel_exec_file_init_length] 124 | mov rsi, kernel_exec_file_init 125 | call kernel_storage_file 126 | 127 | ; set storage of kernel process 128 | mov qword [r9 + KERNEL_STRUCTURE_TASK.storage], rax 129 | 130 | ; system storage located? 131 | cmp qword [rsp + KERNEL_STORAGE_STRUCTURE_FILE.id], EMPTY 132 | jne .release ; yes 133 | 134 | ; restore original register 135 | pop rcx 136 | pop rax 137 | 138 | ; not a system storage, check next one 139 | jmp .storage 140 | 141 | .release: 142 | ; remove file descriptor from stack 143 | add rsp, KERNEL_STORAGE_STRUCTURE_FILE.SIZE 144 | 145 | ; restore preserved registers 146 | pop rcx 147 | pop rax 148 | 149 | ; set root directory of kernel process 150 | push qword [rax + KERNEL_STORAGE_STRUCTURE.device_first_block] 151 | pop qword [r9 + KERNEL_STRUCTURE_TASK.directory] 152 | 153 | ; show information about system storage 154 | mov ecx, kernel_log_system_end - kernel_log_system 155 | mov rsi, kernel_log_system 156 | call driver_serial_string 157 | 158 | ; convert Bytes to KiB 159 | mov rax, qword [rax + KERNEL_STORAGE_STRUCTURE.device_blocks] 160 | shr rax, STD_SHIFT_1024 161 | 162 | ; show size of system storage 163 | mov ebx, STD_NUMBER_SYSTEM_decimal 164 | xor ecx, ecx ; no prefix 165 | call driver_serial_value 166 | 167 | .end: 168 | ; restore original registers 169 | pop r11 170 | pop r9 171 | pop rdi 172 | pop rsi 173 | pop rdx 174 | pop rcx 175 | pop rbx 176 | pop rax 177 | 178 | ; return from routine 179 | ret 180 | 181 | .error: 182 | ; storage is not available 183 | mov ecx, kernel_log_storage_end - kernel_log_storage 184 | mov rsi, kernel_log_storage 185 | call driver_serial_string 186 | 187 | ; hold the door 188 | jmp $ -------------------------------------------------------------------------------- /kernel/init/stream.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;------------------------------------------------------------------------------- 6 | ; void 7 | kernel_init_stream: 8 | ; preserve original registers 9 | push rcx 10 | push rdi 11 | 12 | ; prepare area for streams 13 | mov ecx, MACRO_PAGE_ALIGN_UP( KERNEL_STREAM_limit * KERNEL_STRUCTURE_STREAM.SIZE ) >> STD_SHIFT_PAGE 14 | call kernel_memory_alloc 15 | 16 | ; preserve pointer inside KERNEL environment 17 | mov qword [r8 + KERNEL.stream_base_address], rdi 18 | 19 | ; restore original registers 20 | pop rdi 21 | pop rcx 22 | 23 | ; return from routine 24 | ret -------------------------------------------------------------------------------- /kernel/init/task.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;------------------------------------------------------------------------------- 6 | ; void 7 | kernel_init_task: 8 | ; preserve original registers 9 | push rax 10 | ; TODO, remove me after refactoring 11 | push rbx 12 | push rcx 13 | push rdi 14 | push rsi 15 | 16 | ; default task limit (expendable) 17 | mov qword [r8 + KERNEL.task_limit], KERNEL_TASK_limit 18 | 19 | ; prepare area for Task entries 20 | mov ecx, MACRO_PAGE_ALIGN_UP( KERNEL_TASK_limit * KERNEL_STRUCTURE_TASK.SIZE ) >> STD_SHIFT_PAGE 21 | call kernel_memory_alloc 22 | 23 | ; preserve pointer inside KERNEL environment 24 | mov qword [r8 + KERNEL.task_base_address], rdi 25 | 26 | ;---------------------------------------------------------------------- 27 | ; we need to create first entry inside task queue for kernel itself 28 | ; that entry will never be *active*, none of BSP/AP CPUs will ever run it 29 | ; so why we still need it? each CPU exiting initialization state (file: ap.c) 30 | ; will go stright into task selection procedure, and as we know (later) 31 | ; all registers/flags needs to be stored somewhere before choosing next task 32 | ; thats the purpose of kernel entry :) 33 | ;---------------------------------------------------------------------- 34 | 35 | ; mark first entry of task queue as secured (in use) 36 | mov word [rdi + KERNEL_STRUCTURE_TASK.flags], KERNEL_TASK_FLAG_secured 37 | 38 | ; kernel paging structure 39 | mov rax, qword [r8 + KERNEL.page_base_address] 40 | mov qword [rdi + KERNEL_STRUCTURE_TASK.cr3], rax 41 | 42 | ; set binary memory map of kernel 43 | mov rax, qword [r8 + KERNEL.memory_base_address] 44 | mov qword [rdi + KERNEL_STRUCTURE_TASK.memory_map], rax 45 | 46 | ; prepare stream[s] for kernel 47 | call kernel_stream 48 | 49 | ; as a kernel, both streams are of type null 50 | or byte [rsi + KERNEL_STRUCTURE_STREAM.flags], KERNEL_STREAM_FLAG_null 51 | 52 | ; assign stream[s] to kernel entry 53 | mov qword [rdi + KERNEL_STRUCTURE_TASK.stream_in], rsi 54 | mov qword [rdi + KERNEL_STRUCTURE_TASK.stream_out], rsi 55 | 56 | ; remember pointer kernel task entry 57 | push rdi 58 | 59 | ; retrieve available CPUs on host 60 | mov rcx, qword [kernel_limine_smp_request + LIMINE_SMP_REQUEST.response] 61 | mov rcx, qword [rcx + LIMINE_SMP_RESPONSE.cpu_count] 62 | 63 | ; calculate CPU list size in Pages 64 | shl rcx, STD_SHIFT_PTR 65 | MACRO_PAGE_ALIGN_UP_REGISTER rcx 66 | shr rcx, STD_SHIFT_PAGE 67 | 68 | ; prepare area for APs 69 | call kernel_memory_alloc 70 | mov qword [r8 + KERNEL.task_cpu_address], rdi 71 | 72 | ; each CPU needs to know which task he is currently executing 73 | ; that information is stored on CPU list 74 | call kernel_lapic_id 75 | pop qword [rdi + rax * STD_SIZE_PTR_byte] 76 | 77 | ; TODO, remove me after refactoring 78 | mov rax, kernel_task 79 | mov bx, KERNEL_IDT_TYPE_irq 80 | mov ecx, KERNEL_TASK_irq 81 | call kernel_idt_mount 82 | 83 | ; mark IRQ line as in use 84 | and dword [r8 + KERNEL.io_apic_irq_lines], ~(1 << 0) 85 | 86 | ; restore original registers 87 | pop rdi 88 | pop rsi 89 | pop rcx 90 | ; TODO, remove me after refactoring 91 | pop rbx 92 | pop rax 93 | 94 | ; return from routine 95 | ret -------------------------------------------------------------------------------- /kernel/init/vfs.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;------------------------------------------------------------------------------- 6 | ; void 7 | kernel_vfs_init: 8 | ; preserve original registers 9 | push rax 10 | push rcx 11 | push rsi 12 | push rbp 13 | 14 | ;----------------------------------------------------------------------- 15 | ; which storage device contains home folder? 16 | ;----------------------------------------------------------------------- 17 | 18 | ; limit of devices 19 | mov rcx, KERNEL_STORAGE_limit 20 | 21 | ; devices list base address 22 | mov rax, qword [r8 + KERNEL.storage_base_address] 23 | 24 | .storage: 25 | ; no more devices? 26 | dec rcx 27 | js .create ; prepare empty vfs 28 | 29 | ; device exist? 30 | cmp byte [rax + KERNEL_STORAGE_STRUCTURE.device_type], EMPTY 31 | jne .files ; yes 32 | 33 | ; next slot 34 | add rax, KERNEL_STORAGE_STRUCTURE.SIZE 35 | 36 | ; next storage 37 | jmp .storage 38 | 39 | .files: 40 | ; preserve original register 41 | push rax 42 | push rcx 43 | 44 | ; local structure of file descriptor 45 | sub rsp, KERNEL_STORAGE_STRUCTURE_FILE.SIZE 46 | mov rbp, rsp ; pointer of file descriptor 47 | 48 | ; change storage pointer to ID 49 | sub rax, qword [r8 + KERNEL.storage_base_address] 50 | shr rax, KERNEL_STORAGE_STRUCTURE_SIZE_shift 51 | 52 | ; search for "welcome.txt" file on storage device 53 | mov ecx, kernel_vfs_file_welcome_end - kernel_vfs_file_welcome 54 | mov rsi, kernel_vfs_file_welcome 55 | call kernel_storage_file 56 | 57 | ; home storage located? 58 | cmp qword [rsp + KERNEL_STORAGE_STRUCTURE_FILE.id], EMPTY 59 | jne .init ; yes 60 | 61 | ; restore original register 62 | pop rcx 63 | pop rax 64 | 65 | ; not a home storage, check next one 66 | jmp .storage 67 | 68 | .init: 69 | ; remove file descriptor from stack 70 | add rsp, KERNEL_STORAGE_STRUCTURE_FILE.SIZE 71 | 72 | ; restore original register 73 | pop rcx 74 | pop rax 75 | 76 | ; preserve home storage id 77 | shr rax, KERNEL_STORAGE_STRUCTURE_SIZE_shift 78 | mov qword [r8 + KERNEL.storage_home_id], rax 79 | 80 | ; initialize VFS storage 81 | call lib_vfs_init 82 | 83 | .end: 84 | ; restore original registers 85 | pop rbp 86 | pop rsi 87 | pop rbx 88 | pop rax 89 | 90 | ; return from routine 91 | ret 92 | 93 | .create: 94 | ; home vfs initialized ready 95 | jmp .end -------------------------------------------------------------------------------- /kernel/io_apic.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;=============================================================================== 6 | ; in: 7 | ; eax - interrupt number 8 | ; ebx - I/O APIC register 9 | kernel_io_apic_connect: 10 | ; preserve original registers 11 | push rax 12 | push rbx 13 | push rdi 14 | 15 | ; kernel environment variables/rountines base address 16 | mov rdi, qword [kernel] 17 | mov rdi, qword [rdi + KERNEL.io_apic_base_address] 18 | 19 | ; inside lower half of register 20 | add ebx, KERNEL_IO_APIC_iowin_low 21 | mov dword [rdi + KERNEL_IO_APIC_ioregsel], ebx 22 | 23 | ; save lower half of interrupt vector 24 | mov dword [rdi + KERNEL_IO_APIC_iowin], eax 25 | 26 | ; inside higher half 27 | add ebx, KERNEL_IO_APIC_iowin_high - KERNEL_IO_APIC_iowin_low 28 | mov dword [rdi + KERNEL_IO_APIC_ioregsel], ebx 29 | 30 | ; save higher half of interrupt vector 31 | shr rax, STD_MOVE_DWORD 32 | mov dword [rdi + KERNEL_IO_APIC_iowin], eax 33 | 34 | ; restore original registers 35 | pop rdi 36 | pop rbx 37 | pop rax 38 | 39 | ; return from routine 40 | ret -------------------------------------------------------------------------------- /kernel/io_apic.inc: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | KERNEL_IO_APIC_ioregsel equ 0x00 6 | KERNEL_IO_APIC_iowin equ 0x10 7 | KERNEL_IO_APIC_iowin_low equ 0x00 8 | KERNEL_IO_APIC_iowin_high equ 0x01 -------------------------------------------------------------------------------- /kernel/ipc.inc: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | %ifndef KERNEL_IPC 6 | %define KERNEL_IPC 7 | 8 | %define KERNEL_IPC_limit 512 9 | %define KERNEL_IPC_ttl (DRIVER_RTC_Hz >> STD_SHIFT_8) ; about 1/8 of second 10 | %endif -------------------------------------------------------------------------------- /kernel/lapic.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;------------------------------------------------------------------------------- 6 | ; void 7 | kernel_lapic_accept: 8 | ; preserve original register 9 | push rax 10 | 11 | ; LAPIC controller base address 12 | mov rax, qword [kernel] 13 | mov rax, qword [rax + KERNEL.lapic_base_address] 14 | 15 | ; accept currently pending interrupt 16 | mov dword [rax + KERNEL_LAPIC_STRUCTURE.eoi], EMPTY 17 | 18 | ; restore original register 19 | pop rax 20 | 21 | ; return from routine 22 | ret 23 | 24 | ;------------------------------------------------------------------------------- 25 | ; out: 26 | ; eax - cpu id 27 | kernel_lapic_id: 28 | ; kernel environment variables/rountines base address 29 | mov rax, qword [kernel] 30 | 31 | ; retrieve CPU ID from LAPIC 32 | mov rax, qword [rax + KERNEL.lapic_base_address] 33 | mov eax, dword [rax + KERNEL_LAPIC_STRUCTURE.id] 34 | shr eax, 24 ; move ID at a begining of EAX register 35 | 36 | ; return from routine 37 | ret 38 | 39 | ;------------------------------------------------------------------------------- 40 | ; void 41 | kernel_lapic_init: 42 | ; preserve original registers 43 | push rax 44 | push rdi 45 | 46 | ; kernel environment variables/rountines base address 47 | mov rdi, qword [kernel] 48 | mov rdi, qword [rdi + KERNEL.lapic_base_address] 49 | 50 | ; turn off Task Priority and Priority Sub-Class 51 | mov dword [rdi + KERNEL_LAPIC_STRUCTURE.tp], EMPTY; 52 | 53 | ; turn on Flat Mode 54 | mov dword [rdi + KERNEL_LAPIC_STRUCTURE.df], KERNEL_LAPIC_DF_FLAG_flat_mode 55 | 56 | ; all logical/BSP processors gets interrupts (physical!) 57 | mov dword [rdi + KERNEL_LAPIC_STRUCTURE.ld], KERNEL_LAPIC_LD_FLAG_target_cpu 58 | 59 | ; enable APIC controller on the BSP/logical processor 60 | mov eax, dword [rdi + KERNEL_LAPIC_STRUCTURE.siv] 61 | or eax, KERNEL_LAPIC_SIV_FLAG_enable_apic | KERNEL_LAPIC_SIV_FLAG_spurious_vector3 62 | mov dword [rdi + KERNEL_LAPIC_STRUCTURE.siv], eax 63 | 64 | ; turn on internal interrupts time on APIC controller of BSP/logical processor 65 | mov eax, dword [rdi + KERNEL_LAPIC_STRUCTURE.lvt] 66 | and eax, KERNEL_LAPIC_LVT_TR_FLAG_mask_interrupts 67 | mov dword [rdi + KERNEL_LAPIC_STRUCTURE.lvt], eax 68 | 69 | ; number of hardware interrupt at the end of the timer 70 | mov dword [rdi + KERNEL_LAPIC_STRUCTURE.lvt], KERNEL_LAPIC_IRQ_number 71 | 72 | ; countdown time converter 73 | mov dword [rdi + KERNEL_LAPIC_STRUCTURE.tdc], KERNEL_LAPIC_TDC_divide_by_1 74 | 75 | ; restore original registers 76 | pop rdi 77 | pop rax 78 | 79 | ; return from routine 80 | ret 81 | 82 | ;------------------------------------------------------------------------------- 83 | ; void 84 | kernel_lapic_reload: 85 | ; preserve original register 86 | push rax 87 | 88 | ; LAPIC controller base address 89 | mov rax, qword [kernel] 90 | mov rax, qword [rax + KERNEL.lapic_base_address] 91 | 92 | ; wake up internal interrupt after KERNEL_LAPIC_Hz cycles 93 | mov dword [rax + KERNEL_LAPIC_STRUCTURE.tic], KERNEL_LAPIC_Hz 94 | 95 | ; restore original register 96 | pop rax 97 | 98 | ; return from routine 99 | ret -------------------------------------------------------------------------------- /kernel/lapic.inc: -------------------------------------------------------------------------------- 1 | ;=============================================================================== 2 | ;Copyright (C) Andrzej Adamczyk (at https:;blackdev.org/). All rights reserved. 3 | ;=============================================================================== 4 | 5 | %define KERNEL_LAPIC_Hz 1024 6 | 7 | %define KERNEL_LAPIC_IRQ_number 0x20 8 | %define KERNEL_LAPIC_INIT_READY_bit 12 9 | %define KERNEL_LAPIC_DF_FLAG_flat_mode 0xFFFFFFFF 10 | %define KERNEL_LAPIC_LD_FLAG_target_cpu 0x01000000 11 | %define KERNEL_LAPIC_SIV_FLAG_enable_apic 00000000000000000000000100000000b 12 | %define KERNEL_LAPIC_SIV_FLAG_spurious_vector3 00000000000000000000000011111111b 13 | %define KERNEL_LAPIC_LVT_TR_FLAG_mask_interrupts 00000000000000010000000000000000b 14 | %define KERNEL_LAPIC_TDC_divide_by_1 00000000000000000000000000000111b 15 | 16 | struc KERNEL_LAPIC_STRUCTURE 17 | .reserved_0 resb 32 18 | .id resd 1 19 | .reserved_1 resb 92 20 | .tp resd 1 21 | .reserved_2 resb 44 22 | .eoi resd 1 23 | .reserved_3 resb 28 24 | .ld resd 1 25 | .reserved_4 resb 12 26 | .df resd 1 27 | .reserved_5 resb 12 28 | .siv resd 1 29 | .reserved_6 resb 524 30 | .icl resd 1 31 | .reserved_7 resb 12 32 | .ich resd 1 33 | .reserved_8 resb 12 34 | .lvt resd 1 35 | .reserved_9 resb 92 36 | .tic resd 1 37 | .reserved_A resb 12 38 | .tcc resd 1 39 | .reserved_B resb 76 40 | .tdc resd 1 41 | endstruc -------------------------------------------------------------------------------- /kernel/library.inc: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | %ifndef KERNEL_LIBRARY 6 | %define KERNEL_LIBRARY_limit 16 7 | 8 | %define KERNEL_LIBRARY_base_address 0x0000700000000000 9 | 10 | %define KERNEL_LIBRARY_FLAG_reserved 1 << 0 11 | %define KERNEL_LIBRARY_FLAG_active 1 << 1 12 | 13 | struc KERNEL_LIBRARY_STRUCTURE 14 | .address resq 1 15 | .dynsym resq 1 16 | .dynsym_limit resq 1 17 | .strtab resq 1 18 | .size_page resw 1 19 | .flags resw 1 20 | .length resb 1 21 | .name resb 255 22 | 23 | ; align next label 24 | alignb 0x08 25 | 26 | .SIZE: 27 | endstruc 28 | %endif -------------------------------------------------------------------------------- /kernel/log.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ; debug, TODO remove this function 6 | driver_serial_string: 7 | ret 8 | 9 | %MACRO KERNEL_LOG_INITIALIZE 0 10 | ; prepare stack for arguments from variables 11 | sub rsp, 0x20 12 | 13 | ; add first 4 variables to stack 14 | mov qword [rsp], rsi 15 | mov qword [rsp + 0x08], rdx 16 | mov qword [rsp + 0x10], rcx 17 | mov qword [rsp + 0x18], r8 18 | 19 | ; preserve original registers 20 | push rbp 21 | lea rbp, [rsp + 0x08] 22 | push r8 23 | mov r8, qword [rbp + 0x20] 24 | 25 | ; add 5th variable to stack 26 | mov qword [rbp + 0x20], r9 27 | %ENDMACRO 28 | 29 | %MACRO KERNEL_LOG_FINALIZE 0 30 | ; restore original registers 31 | mov qword [rbp + 0x20], r8 32 | pop r8 33 | pop rbp 34 | 35 | ; remove local variables 36 | add rsp, 0x20 37 | %ENDMACRO 38 | 39 | ;------------------------------------------------------------------------------- 40 | ; in: 41 | ; void printf( const char *string, ... ); 42 | kernel_log: 43 | KERNEL_LOG_INITIALIZE 44 | 45 | ; preserve original registers 46 | push rax 47 | push rbx 48 | push rcx 49 | push rdx 50 | push rsi 51 | push rdi 52 | push rbp 53 | 54 | .loop: 55 | ; retrieve character from string 56 | mov al, byte [rdi] 57 | inc rdi ; next character in progress 58 | 59 | ; end of string? 60 | test al, al 61 | jz .end ; yes 62 | 63 | ; start of sequence? 64 | cmp al, STD_ASCII_PERCENT 65 | jne .unsequenced ; no 66 | 67 | ; retrieve sequence type 68 | mov al, byte [rdi] 69 | inc rdi ; next character in progress 70 | 71 | ; decimal value? 72 | cmp al, 'd' 73 | jne .no_decimal 74 | 75 | ; retrieve variable 76 | mov rax, qword [rbp] 77 | mov ebx, STD_NUMBER_SYSTEM_decimal 78 | mov ecx, 1 ; at least 1 digit 79 | xor dl, dl ; unsigned 80 | call driver_serial_value 81 | 82 | ; variable parsed 83 | add rbp, STD_SIZE_QWORD_byte 84 | 85 | ; continue 86 | jmp .loop 87 | 88 | .no_decimal: 89 | ; hexadecimal value? 90 | cmp al, 'x' 91 | jne .no_hexadecimal 92 | 93 | ; retrieve variable 94 | mov rax, qword [rbp] 95 | mov ebx, STD_NUMBER_SYSTEM_hexadecimal 96 | mov ecx, 1 ; at least 1 digit 97 | xor dl, dl ; unsigned 98 | call driver_serial_value 99 | 100 | ; variable parsed 101 | add rbp, STD_SIZE_QWORD_byte 102 | 103 | ; continue 104 | jmp .loop 105 | 106 | .no_hexadecimal: 107 | ; string? 108 | cmp al, 's' 109 | jne .no_string 110 | 111 | ; retrieve string pointer 112 | mov rsi, qword [rbp] 113 | call lib_string_length 114 | call driver_serial_string 115 | 116 | ; variable parsed 117 | add rbp, STD_SIZE_QWORD_byte 118 | 119 | ; continue 120 | jmp .loop 121 | 122 | .no_string: 123 | ; unrecognized value, show whole sequence 124 | push rax 125 | mov al, STD_ASCII_PERCENT 126 | call driver_serial_char 127 | pop rax 128 | 129 | .unsequenced: 130 | ; send character to failover output 131 | call driver_serial_char 132 | 133 | ; continue with string 134 | jmp .loop 135 | 136 | .end: 137 | ; restore original registers 138 | pop rbp 139 | pop rdi 140 | pop rsi 141 | pop rdx 142 | pop rcx 143 | pop rbx 144 | pop rax 145 | 146 | KERNEL_LOG_FINALIZE 147 | 148 | ; return from routine 149 | ret -------------------------------------------------------------------------------- /kernel/memory.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;------------------------------------------------------------------------------- 6 | ; in: 7 | ; rcx - length of area in pages 8 | ; out: 9 | ; CF - set if not available 10 | ; rdi - pointer to allocated area (logical address) 11 | kernel_memory_alloc: 12 | ; preserve original registers 13 | push rax 14 | push r8 15 | push r9 16 | 17 | ; kernel environment variables/rountines base address 18 | mov r8, qword [kernel] 19 | 20 | .lock: 21 | ; request an exclusive access 22 | mov al, LOCK 23 | xchg byte [r8 + KERNEL.memory_semaphore], al 24 | 25 | ; assigned? 26 | test al, al 27 | jnz .lock ; no 28 | 29 | ; start searching from first page of binary memory map 30 | mov r9, qword [r8 + KERNEL.memory_base_address] 31 | call kernel_memory_acquire 32 | jc .end ; no enough memory 33 | 34 | ; convert page number to its logical address 35 | shl rdi, STD_SHIFT_PAGE 36 | add rdi, qword [kernel_page_mirror] 37 | 38 | ; less memory available 39 | sub qword [r8 + KERNEL.page_available], rcx 40 | 41 | .end: 42 | ; release access 43 | mov byte [r8 + KERNEL.memory_semaphore], UNLOCK 44 | 45 | ; restore original registers 46 | pop r9 47 | pop r8 48 | pop rax 49 | 50 | ; return from routine 51 | ret 52 | 53 | ;------------------------------------------------------------------------------- 54 | ; out: 55 | ; CF - set if not available 56 | ; rdi - pointer to allocated page (physical address) 57 | kernel_memory_alloc_page: 58 | ; preserve original registers 59 | push rcx 60 | 61 | ; alloc only 1 page 62 | mov ecx, STD_PAGE_page 63 | call kernel_memory_alloc 64 | jc .error ; no enough memory, really? ok 65 | 66 | ; convert page address to physical area 67 | mov rcx, ~KERNEL_PAGE_mirror 68 | and rdi, rcx 69 | 70 | .error: 71 | ; restore original registers 72 | pop rcx 73 | 74 | ; return from routine 75 | ret 76 | 77 | ;------------------------------------------------------------------------------- 78 | ; in: 79 | ; rcx - length of space in pages 80 | ; r9 - pointer to binary memory map of process 81 | ; out: 82 | ; CF - set if not available 83 | ; rdi - first page number of aquired space 84 | kernel_memory_acquire: 85 | ; preserve original registers 86 | push rax 87 | push r8 88 | push rcx 89 | 90 | ; kernel environment variables/rountines base address 91 | mov r8, qword [kernel] 92 | 93 | ; start from first page of binary memory map 94 | xor eax, eax 95 | 96 | .new: 97 | ; start of the considered space 98 | mov rdi, rax 99 | 100 | ; length of considered space 101 | xor ecx, ecx 102 | 103 | .check: 104 | ; check 105 | bt qword [r9], rax 106 | 107 | ; next page from area and current its length 108 | inc rax 109 | inc rcx 110 | 111 | ; continuity ensured? 112 | jnc .new ; no 113 | 114 | ; area located? 115 | cmp rcx, qword [rsp] 116 | je .found ; yes 117 | 118 | ; end of binary memory map? 119 | cmp rax, qword [r8 + KERNEL.page_limit] 120 | je .error ; yes 121 | 122 | ; conitnue search 123 | jmp .check 124 | 125 | .found: 126 | ; first page of located area 127 | mov rax, rdi 128 | 129 | .mark: 130 | ; mark page as reserved 131 | btr qword [r9], rax 132 | 133 | ; next page of area 134 | inc rax 135 | 136 | ; continue with reservation? 137 | dec rcx 138 | jnz .mark ; tes 139 | 140 | ; allocated successful 141 | clc 142 | jmp .end 143 | 144 | .error: 145 | ; operation failed 146 | stc 147 | 148 | .end: 149 | ; restore original registers 150 | pop rcx 151 | pop r8 152 | pop rax 153 | 154 | ; return from routine 155 | ret 156 | 157 | ;------------------------------------------------------------------------------- 158 | ; in: 159 | ; rsi - length of space in pages 160 | ; rdi - pointer to first page of space 161 | kernel_memory_release: 162 | ; preserve original registers 163 | push rax 164 | push rcx 165 | push rdi 166 | push rsi 167 | 168 | ; we guarantee, clean pages on stack 169 | mov rcx, rsi 170 | call kernel_page_clean_few 171 | 172 | ; convert page address to physical, and offset of memory binary map 173 | mov rax, ~KERNEL_PAGE_mirror 174 | and rax, rdi 175 | shr rax, STD_SHIFT_PAGE 176 | 177 | ; kernel environment variables/rountines base address 178 | mov rcx, qword [kernel] 179 | 180 | ; put page back to binary memory map 181 | mov rdi, qword [rcx + KERNEL.memory_base_address] 182 | 183 | .page: 184 | ; release first page of space 185 | bts qword [rdi], rax 186 | 187 | ; next page? 188 | inc rax 189 | dec rsi 190 | jnz .page ; yes 191 | 192 | ; released RSI pages 193 | mov rsi, qword [rsp] 194 | add qword [rcx + KERNEL.page_available], rsi 195 | 196 | ; restore original registers 197 | pop rsi 198 | pop rdi 199 | pop rcx 200 | pop rax 201 | 202 | ; return from routine 203 | ret 204 | 205 | ;------------------------------------------------------------------------------- 206 | ; in: 207 | ; rdi - logical page address 208 | kernel_memory_release_page: 209 | ; preserve original registers 210 | push rsi 211 | 212 | ; release page 213 | mov rsi, STD_PAGE_page 214 | call kernel_memory_release 215 | 216 | ; restore original registers 217 | pop rsi 218 | 219 | ; return from routine 220 | ret 221 | 222 | ;------------------------------------------------------------------------------- 223 | ; in: 224 | ; rcx - size of memory space in Bytes 225 | ; rsi - pointer of memory space to be shared 226 | ; r11 - pointer to process paging array 227 | ; out: 228 | ; CF - set if no enough memory 229 | ; rax - pointer to process shared memory 230 | kernel_memory_share: 231 | ; preserve original registers 232 | push rbx 233 | push rsi 234 | push rdi 235 | push r8 236 | push r9 237 | 238 | ; kernel environment variables/rountines base address 239 | mov r8, qword [kernel] 240 | 241 | ; retrieve pointer to current task descriptor 242 | call kernel_task_active 243 | 244 | ; reserve space in binary memory map of process 245 | mov r9, qword [r9 + KERNEL_STRUCTURE_TASK.memory_map] 246 | call kernel_memory_acquire 247 | jc .end ; no enough memory 248 | 249 | ; convert page number to logical address 250 | shl rdi, STD_SHIFT_PAGE 251 | 252 | ; map source space to process paging array 253 | mov rax, rdi 254 | mov bx, KERNEL_PAGE_FLAG_present | KERNEL_PAGE_FLAG_write | KERNEL_PAGE_FLAG_user | KERNEL_PAGE_FLAG_shared 255 | sub rsi, qword [kernel_page_mirror] 256 | call kernel_page_map 257 | 258 | .end: 259 | ; restore original registers 260 | pop r9 261 | pop r8 262 | pop rdi 263 | pop rsi 264 | pop rbx 265 | 266 | ; return from routine 267 | ret -------------------------------------------------------------------------------- /kernel/page.inc: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | %define KERNEL_PAGE_mask 0xFFFF000000000000 6 | %define KERNEL_PAGE_mirror 0xFFFF800000000000 7 | 8 | %define KERNEL_PAGE_ENTRY_count 512 9 | 10 | %define KERNEL_PAGE_PML1_SIZE_byte KERNEL_PAGE_ENTRY_count * STD_PAGE_byte 11 | %define KERNEL_PAGE_PML2_SIZE_byte KERNEL_PAGE_ENTRY_count * KERNEL_PAGE_PML1_SIZE_byte 12 | %define KERNEL_PAGE_PML3_SIZE_byte KERNEL_PAGE_ENTRY_count * KERNEL_PAGE_PML2_SIZE_byte 13 | %define KERNEL_PAGE_PML4_SIZE_byte KERNEL_PAGE_ENTRY_count * KERNEL_PAGE_PML3_SIZE_byte 14 | 15 | %define KERNEL_PAGE_FLAG_present 1 << 0 16 | %define KERNEL_PAGE_FLAG_write 1 << 1 17 | %define KERNEL_PAGE_FLAG_user 1 << 2 18 | %define KERNEL_PAGE_FLAG_write_through 1 << 3 19 | %define KERNEL_PAGE_FLAG_cache_disable 1 << 4 20 | %define KERNEL_PAGE_FLAG_length 1 << 7 21 | %define KERNEL_PAGE_FLAG_process 1 << 9 22 | %define KERNEL_PAGE_FLAG_shared 1 << 10 23 | %define KERNEL_PAGE_FLAG_library 1 << 11 24 | 25 | %define KERNEL_PAGE_ENTRY_stack 223 26 | %define KERNEL_PAGE_ENTRY_stack_context 510 -------------------------------------------------------------------------------- /kernel/storage.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;------------------------------------------------------------------------------- 6 | ; in: 7 | ; rax - device id 8 | ; rcx - length of path 9 | ; rsi - path to file 10 | ; rbp - pointer of file descriptor 11 | kernel_storage_file: 12 | ; preserve original registers 13 | push rax 14 | push rdi 15 | push r8 16 | push r10 17 | 18 | ; kernel environment variables/rountines base address 19 | mov r8, qword [kernel] 20 | 21 | ; by default file does not exist 22 | mov qword [rbp + KERNEL_STORAGE_STRUCTURE_FILE.id], EMPTY 23 | 24 | ; stograge base address 25 | mov r10, qword [r8 + KERNEL.storage_base_address] 26 | 27 | ; device ID overflow? 28 | cmp rax, KERNEL_STORAGE_limit 29 | jae .end ; yes, ignore 30 | 31 | ; change device ID to offset 32 | shl rax, KERNEL_STORAGE_STRUCTURE_SIZE_shift 33 | 34 | ; device type of KERNEL_STORAGE_TYPE_memory? 35 | cmp byte [r10 + rax + KERNEL_STORAGE_STRUCTURE.device_type], KERNEL_STORAGE_TYPE_memory 36 | jne .end ; no 37 | 38 | ; search for requested file 39 | mov rdi, qword [r10 + rax + KERNEL_STORAGE_STRUCTURE.device_first_block] 40 | call lib_vfs_file 41 | 42 | .end: 43 | ; restore original registers 44 | pop r10 45 | pop r8 46 | pop rdi 47 | pop rax 48 | 49 | ; return from routine 50 | ret 51 | 52 | ;------------------------------------------------------------------------------- 53 | ; in: 54 | ; rax - device ID 55 | ; rsi - file identificator 56 | ; rdi - file data destination 57 | kernel_storage_read: 58 | ; preserve original registers 59 | push rax 60 | push r8 61 | push r10 62 | 63 | ; kernel environment variables/rountines base address 64 | mov r8, qword [kernel] 65 | 66 | ; stograge base address 67 | mov r10, qword [r8 + KERNEL.storage_base_address] 68 | 69 | ; device ID overflow? 70 | cmp rax, KERNEL_STORAGE_limit 71 | jae .end ; yes, ignore 72 | 73 | ; change device ID to offset 74 | shl rax, KERNEL_STORAGE_STRUCTURE_SIZE_shift 75 | 76 | ; device type of KERNEL_STORAGE_TYPE_memory? 77 | cmp byte [r10 + rax + KERNEL_STORAGE_STRUCTURE.device_type], KERNEL_STORAGE_TYPE_memory 78 | jne .end ; no 79 | 80 | ; load file 81 | call lib_vfs_read 82 | 83 | .end: 84 | ; restore original registers 85 | pop r10 86 | pop r8 87 | pop rax 88 | 89 | ; return from routine 90 | ret 91 | 92 | ;------------------------------------------------------------------------------- 93 | ; out: 94 | ; rdi - pointer to storage specification 95 | ; or NULL if no free slots 96 | kernel_storage_register: 97 | ; preserve original registers 98 | push rax 99 | push rcx 100 | push r8 101 | 102 | ; kernel environment variables/rountines base address 103 | mov r8, qword [kernel] 104 | 105 | ; limit of devices 106 | mov rcx, KERNEL_STORAGE_limit 107 | 108 | ; base address of device list 109 | mov rdi, qword [r8 + KERNEL.storage_base_address] 110 | 111 | .next: 112 | ; free device slot? 113 | cmp byte [rdi + KERNEL_STORAGE_STRUCTURE.device_type], EMPTY 114 | je .register ; yes 115 | 116 | ; next slot 117 | add rdi, KERNEL_STORAGE_STRUCTURE.SIZE 118 | 119 | ; end of devices list? 120 | dec rcx 121 | jnz .next ; no 122 | 123 | ; no free slots 124 | xor edi, edi 125 | 126 | ; end 127 | jmp .end 128 | 129 | .register: 130 | ; mark slot as used 131 | xchg byte [rdi + KERNEL_STORAGE_STRUCTURE.device_type], al 132 | jnz .next ; could not mark a slot 133 | 134 | .end: 135 | ; restore original registers 136 | pop r8 137 | pop rcx 138 | pop rax 139 | 140 | ; return from routine 141 | ret -------------------------------------------------------------------------------- /kernel/storage.inc: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | %define KERNEL_STORAGE_limit 1 6 | 7 | %define KERNEL_STORAGE_TYPE_memory 00000001b 8 | 9 | %define KERNEL_STORAGE_FILE_TYPE_regular 00000001b 10 | 11 | %define KERNEL_STORAGE_STRUCTURE_SIZE_shift 6 12 | 13 | ; this structure should be divisible by power of 2 14 | struc KERNEL_STORAGE_STRUCTURE 15 | .device_type resb 1 16 | 17 | ; align next label 18 | alignb 0x08 19 | 20 | .device_blocks resq 1 21 | .device_first_block resq 1 22 | .storage_file resq 1 23 | .storage_read resq 1 24 | 25 | ; align next label 26 | .reserved resb 24 27 | 28 | .SIZE: 29 | endstruc 30 | 31 | ; this structure should be divisible by 8 32 | struc KERNEL_STORAGE_STRUCTURE_FILE 33 | .id resq 1 34 | .size_byte resq 1 35 | .address resq 1 36 | .SIZE: 37 | endstruc -------------------------------------------------------------------------------- /kernel/stream.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;------------------------------------------------------------------------------- 6 | ; out: 7 | ; rsi - stream descriptor 8 | kernel_stream: 9 | ; preserve original registers 10 | push rax 11 | push rcx 12 | push rdi 13 | push r8 14 | 15 | ; kernel environment variables/rountines base address 16 | mov r8, qword [kernel] 17 | 18 | .lock: 19 | ; request an exclusive access 20 | mov al, LOCK 21 | xchg byte [r8 + KERNEL.stream_semaphore], al 22 | 23 | ; assigned? 24 | test al, al 25 | jnz .lock ; no 26 | 27 | ; stream first descriptor 28 | mov rsi, qword [r8 + KERNEL.stream_base_address] 29 | 30 | ; amount of streams 31 | mov rcx, KERNEL_STREAM_limit 32 | 33 | .search: 34 | ; available stream? 35 | cmp qword [rsi + KERNEL_STRUCTURE_STREAM.base_address], EMPTY 36 | je .found ; yes 37 | 38 | ; check next stream 39 | add rsi, KERNEL_STRUCTURE_STREAM.SIZE 40 | 41 | ; end of streams? 42 | dec rcx 43 | jnz .search ; no 44 | 45 | .error: 46 | ; free stream not found 47 | xor esi, esi 48 | 49 | ; end of routine 50 | jmp .end 51 | 52 | .found: 53 | ; prepare space for stream 54 | mov ecx, STD_STREAM_SIZE_page 55 | call kernel_memory_alloc 56 | 57 | ; store space of stream 58 | mov qword [rsi + KERNEL_STRUCTURE_STREAM.base_address], rdi 59 | 60 | ; clean up stream content 61 | mov word [rsi + KERNEL_STRUCTURE_STREAM.start], EMPTY 62 | mov word [rsi + KERNEL_STRUCTURE_STREAM.end], EMPTY 63 | mov word [rsi + KERNEL_STRUCTURE_STREAM.free], LIB_SYS_STREAM_SIZE_byte 64 | 65 | ; stream in use by requester 66 | mov qword [rsi + KERNEL_STRUCTURE_STREAM.count], TRUE 67 | 68 | ; stream is unlocked 69 | mov byte [rsi + KERNEL_STRUCTURE_STREAM.lock], UNLOCK 70 | 71 | .end: 72 | ; unlock access 73 | mov byte [r8 + KERNEL.stream_semaphore], UNLOCK 74 | 75 | ; restore original registers 76 | pop r8 77 | pop rdi 78 | pop rcx 79 | pop rax 80 | 81 | ; return from routine 82 | ret 83 | 84 | ;------------------------------------------------------------------------------- 85 | ; in: 86 | ; rdi - pointer to process cache 87 | ; out: 88 | ; rax - amount of transferred data 89 | kernel_stream_in: 90 | ; preserve original registers 91 | push rbx 92 | push rcx 93 | push rdx 94 | push rsi 95 | push rdi 96 | push r9 97 | 98 | ; by default, stream was empty 99 | xor eax, eax 100 | 101 | ; task properties 102 | call kernel_task_active 103 | 104 | ; stream in properties 105 | mov rbx, qword [r9 + KERNEL_STRUCTURE_TASK.stream_in] 106 | 107 | ; there is data inside stream? 108 | cmp word [rbx + KERNEL_STRUCTURE_STREAM.free], LIB_SYS_STREAM_SIZE_byte 109 | je .end ; no 110 | 111 | .lock: 112 | ; request an exclusive access 113 | mov dl, LOCK 114 | xchg byte [rbx + KERNEL_STRUCTURE_STREAM.lock], dl 115 | 116 | ; assigned? 117 | test dl, dl 118 | jnz .lock ; no 119 | 120 | ; get current pointer of start of stream 121 | movzx edx, word [rbx + KERNEL_STRUCTURE_STREAM.start] 122 | 123 | ; get pointer of stream space 124 | mov rsi, qword [rbx + KERNEL_STRUCTURE_STREAM.base_address] 125 | 126 | ; data transferred 127 | xor eax, eax 128 | 129 | .load: 130 | ; retrieve first Byte from stream 131 | mov cl, byte [rsi + rdx] 132 | 133 | ; store inside process cache 134 | mov byte [rdi + rax], cl 135 | 136 | ; move start marker forward 137 | inc dx 138 | 139 | ; end of stream space? 140 | cmp dx, LIB_SYS_STREAM_SIZE_byte 141 | jne .continue ; no 142 | 143 | ; set start marker at begining of stream space 144 | xor dx, dx 145 | 146 | .continue: 147 | ; amount of transferred data 148 | inc ax 149 | 150 | ; end of data inside stream? 151 | cmp dx, word [rbx + KERNEL_STRUCTURE_STREAM.end] 152 | jne .load ; nie 153 | 154 | ; preserve new marker of start of stream 155 | mov word [rbx + KERNEL_STRUCTURE_STREAM.start], dx 156 | 157 | ; stream is drained 158 | mov word [rbx + KERNEL_STRUCTURE_STREAM.free], LIB_SYS_STREAM_SIZE_byte 159 | 160 | .end: 161 | ; release stream 162 | mov byte [rbx + KERNEL_STRUCTURE_STREAM.lock], UNLOCK 163 | 164 | ; restore original registers 165 | pop r9 166 | pop rdi 167 | pop rsi 168 | pop rdx 169 | pop rcx 170 | pop rbx 171 | 172 | ; powrót z procedury 173 | ret 174 | 175 | ;------------------------------------------------------------------------------- 176 | ; in: 177 | ; rdi - pointer to string 178 | ; rsi - string length in bytes 179 | kernel_stream_out: 180 | ; preserve original registers 181 | push rbx 182 | push rcx 183 | push rdx 184 | push rsi 185 | push rdi 186 | push r9 187 | 188 | ; data volume supported? 189 | cmp rsi, LIB_SYS_STREAM_SIZE_byte 190 | jnb .exit ; no 191 | 192 | ; length of string 193 | mov rcx, rsi 194 | 195 | ; task properties 196 | call kernel_task_active 197 | 198 | ; stream out properties 199 | mov rbx, qword [r9 + KERNEL_STRUCTURE_TASK.stream_out] 200 | 201 | ; stream closed? 202 | test byte [rbx + KERNEL_STRUCTURE_STREAM.flags], LIB_SYS_STREAM_FLAG_closed 203 | jnz .exit ; yes 204 | 205 | .lock: 206 | ; request an exclusive access 207 | mov dl, LOCK 208 | xchg byte [rbx + KERNEL_STRUCTURE_STREAM.lock], dl 209 | 210 | ; assigned? 211 | test dl, dl 212 | jnz .lock ; no 213 | 214 | ; there is enough space inside stream? 215 | cmp cx, word [rbx + KERNEL_STRUCTURE_STREAM.free] 216 | ja .end ; no 217 | 218 | ; set string pointer in place 219 | mov rsi, rdi 220 | 221 | ; get pointer of stream space 222 | mov rdi, qword [rbx + KERNEL_STRUCTURE_STREAM.base_address] 223 | 224 | ; get current pointer of end of stream 225 | movzx edx, word [rbx + KERNEL_STRUCTURE_STREAM.end] 226 | 227 | ; after operation there will be less space inside stream 228 | sub word [rbx + KERNEL_STRUCTURE_STREAM.free], cx 229 | 230 | .next: 231 | ; load first char from string 232 | lodsb 233 | 234 | ; preserve in stream 235 | mov byte [rdi + rdx], al 236 | 237 | ; move end marker to next position 238 | inc dx 239 | 240 | ; end of stream space? 241 | cmp dx, LIB_SYS_STREAM_SIZE_byte 242 | jne .continue ; nie 243 | 244 | ; set end marker at begining of stream space 245 | xor dx, dx 246 | 247 | .continue: 248 | ; end of string? 249 | dec cx 250 | jnz .next ; no 251 | 252 | ; preserve new marker of end of stream 253 | mov word [rbx + KERNEL_STRUCTURE_STREAM.end], dx 254 | 255 | ; set meta flag 256 | or byte [rbx + KERNEL_STRUCTURE_STREAM.flags], LIB_SYS_STREAM_FLAG_undefinied; 257 | 258 | ; string inside stream 259 | mov al, TRUE 260 | 261 | .end: 262 | ; release stream 263 | mov byte [rbx + KERNEL_STRUCTURE_STREAM.lock], UNLOCK 264 | 265 | .exit: 266 | ; restore original registers 267 | pop r9 268 | pop rdi 269 | pop rsi 270 | pop rdx 271 | pop rcx 272 | pop rbx 273 | 274 | ; return from routine 275 | ret 276 | 277 | ;------------------------------------------------------------------------------- 278 | ; in: 279 | ; rdi - value 280 | ; sil - number base 281 | ; dl - required N digits, but no more than 64 (QWORD limit) 282 | ; cl - ASCII code of characters 283 | kernel_stream_out_value: 284 | ; preserve original registers 285 | push rax 286 | push rbx 287 | push rcx 288 | push rdx 289 | push rsi 290 | push rdi 291 | 292 | ; prefix overflow? 293 | cmp dl, STD_SIZE_QWORD_bit 294 | ja .end ; yes 295 | 296 | ; string cache 297 | mov eax, STD_SIZE_QWORD_bit 298 | sub rsp, rax 299 | 300 | ; fill with prefix value 301 | xchg al, cl 302 | mov rdi, rsp 303 | rep stosb 304 | 305 | ; prepare acumulator 306 | mov rax, qword [rsp + STD_SIZE_QWORD_bit] 307 | 308 | ; preserve prefix value 309 | movzx rbx, dl 310 | 311 | ; string index 312 | xor ecx, ecx 313 | 314 | ; convert base and prefix to 64bit value 315 | movzx rsi, sil 316 | 317 | .loop: 318 | ; division result 319 | xor edx, edx 320 | 321 | ; modulo 322 | div rsi 323 | 324 | ; assign place for digit 325 | dec rcx 326 | 327 | ; lower prefix requirement 328 | dec rbx 329 | 330 | ; convert digit to ASCII 331 | add dl, STD_ASCII_DIGIT_0 332 | mov byte [rsp + rcx + STD_SIGN_QWORD_bit], dl ; and keep on stack 333 | 334 | ; keep parsing? 335 | test rax, rax 336 | jnz .loop ; yes 337 | 338 | ; prefix fulfilled 339 | bt rbx, STD_SIGN_QWORD_bit 340 | jc .ready ; yes 341 | 342 | ; show N digits 343 | sub rcx, rbx 344 | 345 | .ready: 346 | ; number of digits 347 | mov rsi, rcx 348 | not rsi 349 | inc rsi 350 | 351 | ; send string to stdout 352 | lea rdi, [rsp + rcx + STD_SIGN_QWORD_bit] 353 | call kernel_stream_out 354 | 355 | ; remove string cache from stack 356 | add rsp, STD_SIZE_QWORD_bit 357 | 358 | .end: 359 | ; restore original registers 360 | pop rdi 361 | pop rsi 362 | pop rdx 363 | pop rcx 364 | pop rbx 365 | pop rax 366 | 367 | ; return from routine 368 | ret 369 | 370 | ;------------------------------------------------------------------------------- 371 | ; in: 372 | ; rsi - stream type 373 | ; rdi - pointer to meta descriptor 374 | ; out: 375 | ; al - stream status 376 | kernel_stream_get: 377 | ; preserve original registers 378 | push rcx 379 | push rsi 380 | push rdi 381 | push r9 382 | 383 | ; task properties 384 | call kernel_task_active 385 | 386 | ; stream out? 387 | test rsi, LIB_SYS_STREAM_out 388 | jnz .out ; yes 389 | 390 | ; change to stream in 391 | mov rsi, qword [r9 + KERNEL_STRUCTURE_TASK.stream_in] 392 | 393 | ; continue 394 | jmp .lock 395 | 396 | .out: 397 | ; set to stream out 398 | mov rsi, qword [r9 + KERNEL_STRUCTURE_TASK.stream_out] 399 | 400 | .lock: 401 | ; request an exclusive access 402 | mov cl, LOCK 403 | xchg byte [rsi + KERNEL_STRUCTURE_STREAM.lock], cl 404 | 405 | ; assigned? 406 | test cl, cl 407 | jnz .lock ; no 408 | 409 | ; preserve stream pointer 410 | push rsi 411 | 412 | ; retrieve metadata 413 | mov ecx, LIB_SYS_STREAM_META_LENGTH_byte 414 | add rsi, KERNEL_STRUCTURE_STREAM.meta 415 | rep movsb 416 | 417 | ; restore stream pointer 418 | pop rsi 419 | 420 | ; release stream 421 | mov byte [rsi + KERNEL_STRUCTURE_STREAM.lock], UNLOCK 422 | 423 | ; return stream flags 424 | movzx eax, byte [rsi + KERNEL_STRUCTURE_STREAM.flags] 425 | 426 | ; restore original registers 427 | pop r9 428 | pop rdi 429 | pop rsi 430 | pop rcx 431 | 432 | ; return from routine 433 | ret 434 | 435 | ;------------------------------------------------------------------------------- 436 | ; in: 437 | ; rsi - pointer to stream metadata 438 | ; rdi - stream type 439 | kernel_stream_set: 440 | ; preserve original registers 441 | push rcx 442 | push rsi 443 | push rdi 444 | push r9 445 | 446 | ; task properties 447 | call kernel_task_active 448 | 449 | ; by default stream out 450 | mov rdi, qword [r9 + KERNEL_STRUCTURE_TASK.stream_out] 451 | 452 | ; stream out? 453 | test rdi, LIB_SYS_STREAM_out 454 | jnz .lock ; yes 455 | 456 | ; change to stream in 457 | mov rdi, qword [r9 + KERNEL_STRUCTURE_TASK.stream_in] 458 | 459 | .lock: 460 | ; request an exclusive access 461 | mov cl, LOCK 462 | xchg byte [rdi + KERNEL_STRUCTURE_STREAM.lock], cl 463 | 464 | ; assigned? 465 | test cl, cl 466 | jnz .lock ; no 467 | 468 | ; ignore metadata modification if stream is not empty 469 | mov cx, word [rdi + KERNEL_STRUCTURE_STREAM.start] 470 | cmp cx, word [rdi + KERNEL_STRUCTURE_STREAM.end] 471 | jne .not_empty 472 | 473 | ; preserve stream pointer 474 | push rdi 475 | 476 | ; retrieve metadata 477 | mov ecx, LIB_SYS_STREAM_META_LENGTH_byte 478 | add rdi, KERNEL_STRUCTURE_STREAM.meta 479 | rep movsb 480 | 481 | ; restore stream pointer 482 | pop rdi 483 | 484 | ; metadata are up to date 485 | and byte [rdi + KERNEL_STRUCTURE_STREAM.flags], ~LIB_SYS_STREAM_FLAG_undefinied 486 | 487 | .not_empty: 488 | ; release stream 489 | mov byte [rdi + KERNEL_STRUCTURE_STREAM.lock], UNLOCK 490 | 491 | ; restore original registers 492 | pop r9 493 | pop rdi 494 | pop rsi 495 | pop rcx 496 | 497 | ; return from routine 498 | ret 499 | 500 | ;------------------------------------------------------------------------------- 501 | ; in: 502 | ; rdi - pointer to stream descriptor 503 | kernel_stream_release: 504 | ; preserve original registers 505 | push rsi 506 | push rdi 507 | 508 | ; lower stream usage 509 | dec qword [rdi + KERNEL_STRUCTURE_STREAM.count] 510 | jnz .end ; someone is still using it 511 | 512 | ; release stream cache 513 | mov rsi, STD_STREAM_SIZE_page 514 | mov rdi, qword [rdi + KERNEL_STRUCTURE_STREAM.base_address] 515 | call kernel_memory_release 516 | 517 | ; mark stream descriptor as free 518 | mov rdi, qword [rsp] 519 | mov qword [rdi + KERNEL_STRUCTURE_STREAM.base_address], EMPTY 520 | 521 | .end: 522 | ; restore original registers 523 | pop rdi 524 | pop rsi 525 | 526 | ; return from routine 527 | ret -------------------------------------------------------------------------------- /kernel/stream.inc: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | %ifndef KERNEL_STREAM 6 | %define KERNEL_STREAM 7 | 8 | %define KERNEL_STREAM_limit (KERNEL_TASK_limit << STD_SHIFT_2) 9 | 10 | %define KERNEL_STREAM_FLAG_data 0b00000001 11 | %define KERNEL_STREAM_FLAG_modified 0b00000010 12 | %define KERNEL_STREAM_FLAG_null 0b01000000 13 | %define KERNEL_STREAM_FLAG_closed 0b10000000 14 | 15 | struc KERNEL_STRUCTURE_STREAM 16 | .base_address resq 1 17 | .start resw 1 18 | .end resw 1 19 | .free resw 1 20 | .lock resb 1 21 | .flags resb 1 22 | .count resq 1 23 | .meta resb LIB_SYS_STREAM_META_LENGTH_byte 24 | .SIZE: 25 | endstruc 26 | %endif -------------------------------------------------------------------------------- /kernel/syscall.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ; information for linker 6 | section .text 7 | 8 | ; align routine 9 | align 0x08, db 0x00 10 | kernel_syscall: 11 | ; keep RIP and EFLAGS registers of process 12 | xchg qword [rsp + 0x08], rcx 13 | xchg qword [rsp], r11 14 | 15 | ; feature available? 16 | cmp rax, (kernel_service_list_end - kernel_service_list) / 0x08 17 | jnb .return ; no 18 | 19 | ; preserve original registers 20 | push rbx 21 | push rcx 22 | push rdx 23 | push rsi 24 | push rdi 25 | push rbp 26 | push r8 27 | push r9 28 | push r10 29 | push r11 30 | push r12 31 | push r13 32 | push r14 33 | push r15 34 | 35 | ; execute kernel function according to parameter in RAX 36 | call qword [kernel_service_list + rax * STD_SIZE_QWORD_byte] 37 | 38 | ; restore original registers 39 | pop r15 40 | pop r14 41 | pop r13 42 | pop r12 43 | pop r11 44 | pop r10 45 | pop r9 46 | pop r8 47 | pop rbp 48 | pop rdi 49 | pop rsi 50 | pop rdx 51 | pop rcx 52 | pop rbx 53 | 54 | .return: 55 | ; restore the RIP and EFLAGS registers of the process 56 | xchg qword [rsp], r11 57 | xchg qword [rsp + STD_SIZE_QWORD_byte], rcx 58 | 59 | ; return to process code 60 | o64 sysret -------------------------------------------------------------------------------- /kernel/task.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ; align routine to full address 6 | align 0x08, db 0x00 7 | ;------------------------------------------------------------------------------- 8 | ; void 9 | kernel_task: 10 | ; turn off Interrupt Flag 11 | cli 12 | 13 | ; turn off Direction Flag 14 | cld 15 | 16 | ; keep original registers 17 | push rax 18 | push rbx 19 | push rcx 20 | push rdx 21 | push rsi 22 | push rdi 23 | push rbp 24 | push r8 25 | push r9 26 | push r10 27 | push r11 28 | push r12 29 | push r13 30 | push r14 31 | push r15 32 | 33 | ; keep "floating point" registers 34 | mov rbp, KERNEL_STACK_pointer 35 | FXSAVE64 [rbp] 36 | 37 | ;----------------------------------------------------------------------- 38 | ; [PRESERVE] 39 | 40 | ; kernel environment variables/rountines base address 41 | mov r8, qword [kernel] 42 | 43 | ; retrieve CPU ID from LAPIC 44 | mov rbx, qword [r8 + KERNEL.lapic_base_address] 45 | mov ebx, dword [rbx + KERNEL_LAPIC_STRUCTURE.id] 46 | shr ebx, 24 ; move ID at a begining of EAX register 47 | 48 | ; get pointer to current task of AP 49 | mov r9, qword [r8 + KERNEL.task_cpu_address] 50 | mov r10, qword [r9 + rbx * STD_SIZE_PTR_byte] 51 | 52 | ;======================================================================= 53 | ; todo, find why task_cpu_address[ cpu_id ] doesn't contain task pointer 54 | ; it might be race condition at AP initialization -_- 55 | ; this bypass is safe 56 | 57 | ; bug, AP doesn't have information about currently executed task? 58 | test r10, r10 59 | jnz .ok 60 | 61 | ; set initial task as closed 62 | mov r10, qword [r8 + KERNEL.task_base_address] 63 | ;======================================================================= 64 | 65 | .ok: 66 | ; save tasks current stack pointer 67 | mov qword [r10 + KERNEL_STRUCTURE_TASK.rsp], rsp 68 | 69 | ; set flag of current task as free for execution by next CPU 70 | and word [r10 + KERNEL_STRUCTURE_TASK.flags], ~KERNEL_TASK_FLAG_exec 71 | 72 | ;----------------------------------------------------------------------- 73 | ; [SELECT] 74 | 75 | .lock: 76 | ; request an exclusive access 77 | mov al, LOCK 78 | xchg byte [r8 + KERNEL.task_cpu_semaphore], al 79 | 80 | ; assigned? 81 | test al, al 82 | jnz .lock ; no 83 | 84 | ; calculate task queue size 85 | mov rax, KERNEL_STRUCTURE_TASK.SIZE 86 | mov ecx, KERNEL_TASK_limit 87 | mul rcx 88 | 89 | ; set queue limit pointer 90 | add rax, qword [r8 + KERNEL.task_base_address] 91 | 92 | .next: 93 | ; move pointer to next task in queue 94 | add r10, KERNEL_STRUCTURE_TASK.SIZE 95 | 96 | ; end of task queue? 97 | cmp r10, rax 98 | jb .check ; no 99 | 100 | ; start searching from beginning 101 | mov r10, qword [r8 + KERNEL.task_base_address] 102 | 103 | .check: 104 | ; task is active? (close etc.) 105 | test word [r10 + KERNEL_STRUCTURE_TASK.flags], KERNEL_TASK_FLAG_active 106 | jz .next ; no 107 | 108 | ; a dormant task? 109 | mov rdx, qword [r10 + KERNEL_STRUCTURE_TASK.sleep] 110 | cmp rdx, qword [r8 + KERNEL.time_rtc] 111 | ja .next ; yes 112 | 113 | ; task can be executed? 114 | test word [r10 + KERNEL_STRUCTURE_TASK.flags], KERNEL_TASK_FLAG_exec 115 | jnz .next ; no 116 | 117 | ; mark task as selected by current CPU 118 | or word [r10 + KERNEL_STRUCTURE_TASK.flags], KERNEL_TASK_FLAG_exec 119 | 120 | ; release access 121 | mov byte [r8 + KERNEL.task_cpu_semaphore], UNLOCK 122 | 123 | ;----------------------------------------------------------------------- 124 | ; [RESTORE] 125 | 126 | ; set pointer to current task for AP 127 | mov qword [r9 + rbx * STD_SIZE_PTR_byte], r10 128 | 129 | ; restore tasks stack pointer 130 | mov rsp, qword [r10 + KERNEL_STRUCTURE_TASK.rsp] 131 | 132 | ; restore tasks page arrays 133 | mov rax, qword [r10 + KERNEL_STRUCTURE_TASK.cr3] 134 | mov cr3, rax 135 | 136 | ; first run? 137 | test word [r10 + KERNEL_STRUCTURE_TASK.flags], KERNEL_TASK_FLAG_init 138 | jz .ready ; no 139 | 140 | ; disable init flag 141 | and word [r10 + KERNEL_STRUCTURE_TASK.flags], ~KERNEL_TASK_FLAG_init 142 | 143 | ; reset FPU state 144 | fninit 145 | 146 | ; save FPU state/registers 147 | mov rbp, KERNEL_STACK_pointer 148 | FXSAVE64 [rbp] 149 | 150 | ; it's a daemon? 151 | test word [r10 + KERNEL_STRUCTURE_TASK.flags], KERNEL_TASK_FLAG_module 152 | jz .no_daemon ; no 153 | 154 | ; share with daemon - kernel environment variables/rountines base address 155 | mov qword [rsp + 0x48], r8 156 | 157 | ; initialized 158 | jmp .ready 159 | 160 | .no_daemon: 161 | ; retrieve from stack: 162 | mov rax, qword [rsp + 0x90] 163 | 164 | ; length of string 165 | mov rcx, qword [rax] 166 | 167 | ; pointer to string 168 | add rax, STD_SIZE_QWORD_byte 169 | 170 | ; and pass them to process 171 | mov qword [rsp + 0x48], rcx 172 | mov qword [rsp + 0x50], rax 173 | 174 | .ready: 175 | ; reload CPU cycle counter in APIC controller 176 | mov rax, qword [r8 + KERNEL.lapic_base_address] 177 | mov dword [rax + KERNEL_LAPIC_STRUCTURE.tic], KERNEL_LAPIC_Hz 178 | 179 | ; accept current interrupt call 180 | mov dword [rax + KERNEL_LAPIC_STRUCTURE.eoi], EMPTY 181 | 182 | ; restore "floating point" registers 183 | mov rbp, KERNEL_STACK_pointer 184 | FXRSTOR64 [rbp] 185 | 186 | ; restore ogirinal registers 187 | pop r15 188 | pop r14 189 | pop r13 190 | pop r12 191 | pop r11 192 | pop r10 193 | pop r9 194 | pop r8 195 | pop rbp 196 | pop rdi 197 | pop rsi 198 | pop rdx 199 | pop rcx 200 | pop rbx 201 | pop rax 202 | 203 | ; return from routine 204 | iretq 205 | 206 | ;------------------------------------------------------------------------------- 207 | ; in: 208 | ; rcx - length of process name in characters 209 | ; rsi - pointer to process name 210 | ; out: 211 | ; r10 - pointer to registered task entry 212 | ; or EMPTY if unsuccessful 213 | kernel_task_add: 214 | ; preserve original registers 215 | push rax 216 | push rcx 217 | push rdx 218 | push rsi 219 | push rdi 220 | push r8 221 | 222 | ; kernel environment variables/rountines base address 223 | mov r8, qword [kernel] 224 | 225 | ; search for free entry from beginning 226 | mov rax, KERNEL_TASK_limit 227 | mov r10, qword [r8 + KERNEL.task_base_address] 228 | 229 | .lock: 230 | ; request an exclusive access 231 | mov al, LOCK 232 | xchg byte [r8 + KERNEL.task_semaphore], al 233 | 234 | .loop: 235 | ; free queue entry? 236 | lock bts word [r10 + KERNEL_STRUCTURE_TASK.flags], STD_SIGN_WORD_bit 237 | jnc .found ; yes 238 | 239 | ; move pointer to next task in queue 240 | add r10, KERNEL_STRUCTURE_TASK.SIZE 241 | 242 | ; end of task queue? 243 | dec rax 244 | jnz .loop ; no 245 | 246 | ; there is no free entry on task queue 247 | xor r10, r10 248 | 249 | ; end of procedure 250 | jmp .end 251 | 252 | .found: 253 | ; set process ID 254 | call kernel_task_id_new 255 | mov qword [r10 + KERNEL_STRUCTURE_TASK.pid], rax 256 | 257 | ; retieve parent ID 258 | call kernel_task_id_parent 259 | mov qword [r10 + KERNEL_STRUCTURE_TASK.pid_parent], rdx 260 | 261 | ; task doesn't use memory, yet 262 | mov qword [r10 + KERNEL_STRUCTURE_TASK.page], EMPTY 263 | 264 | ; process name too long? 265 | cmp rcx, KERNEL_TASK_NAME_limit 266 | jbe .proper_length ; no 267 | 268 | ; fix name length 269 | mov rcx, KERNEL_TASK_NAME_limit 270 | 271 | .proper_length: 272 | ; length of process name 273 | mov qword [r10 + KERNEL_STRUCTURE_TASK.name_length], rcx 274 | 275 | ; copy name to task entry 276 | mov rdi, r10 277 | add rdi, KERNEL_STRUCTURE_TASK.name 278 | rep movsb 279 | 280 | ; last character as TERMINATOR 281 | mov byte [rdi], STD_ASCII_TERMINATOR 282 | 283 | ; number of tasks inside queue 284 | inc qword [r8 + KERNEL.task_count] 285 | 286 | .end: 287 | ; release access 288 | mov byte [r8 + KERNEL.task_semaphore], UNLOCK 289 | 290 | ; restore original registers 291 | pop r8 292 | pop rdi 293 | pop rsi 294 | pop rdx 295 | pop rcx 296 | pop rax 297 | 298 | ; return from routine 299 | ret 300 | 301 | ;------------------------------------------------------------------------------- 302 | ; in: 303 | ; rdx - ID of requested task 304 | ; out: 305 | ; rbx - pointer to task of this ID 306 | ; or EMPTY if not found 307 | kernel_task_by_id: 308 | ; preserve original registers 309 | push rcx 310 | push r8 311 | 312 | ; kernel environment variables/rountines base address 313 | mov r8, qword [kernel] 314 | 315 | ; search for free entry from beginning 316 | mov rcx, KERNEL_TASK_limit 317 | mov rbx, qword [r8 + KERNEL.task_base_address] 318 | 319 | .loop: 320 | ; our task we are looking for? 321 | cmp qword [rbx + KERNEL_STRUCTURE_TASK.pid], rdx 322 | je .end ; yes 323 | 324 | ; move pointer to next task in queue 325 | add rbx, KERNEL_STRUCTURE_TASK.SIZE 326 | 327 | ; end of task queue? 328 | dec rcx 329 | jnz .loop ; no 330 | 331 | ; task not found 332 | xor ebx, ebx 333 | 334 | .end: 335 | ; restore original registers 336 | pop r8 337 | pop rcx 338 | 339 | ; return from routine 340 | ret 341 | 342 | ;------------------------------------------------------------------------------- 343 | ; out: 344 | ; r9 - pointer to current task descriptor 345 | kernel_task_active: 346 | ; preserve original flags 347 | push rax 348 | pushf 349 | 350 | ; turn off interrupts 351 | ; we cannot allow task switch 352 | ; when looking for current task pointer 353 | cli 354 | 355 | ; retrieve CPU id 356 | call kernel_lapic_id 357 | 358 | ; set pointer to current task of CPU 359 | mov r9, qword [kernel] 360 | mov r9, qword [r9 + KERNEL.task_cpu_address] 361 | mov r9, qword [r9 + rax * STD_SIZE_PTR_byte] 362 | 363 | ; restore original flags 364 | popf 365 | pop rax 366 | 367 | ; return from routine 368 | ret 369 | 370 | ;------------------------------------------------------------------------------- 371 | ; out: 372 | ; rax - new ID for use 373 | kernel_task_id_new: 374 | ; preserve original registers 375 | push r8 376 | 377 | ; kernel environment variables/rountines base address 378 | mov r8, qword [kernel] 379 | 380 | ; generate new ID :D 381 | inc qword [r8 + KERNEL.task_id] 382 | 383 | ; new ID 384 | mov rax, qword [r8 + KERNEL.task_id] 385 | 386 | ; restore original registers 387 | pop r8 388 | 389 | ; return from routine 390 | ret 391 | 392 | ;------------------------------------------------------------------------------- 393 | ; out: 394 | ; rdx - ID of parent 395 | kernel_task_id_parent: 396 | ; preserve original registers 397 | push r9 398 | 399 | ; retrieve pointer to current task descriptor 400 | call kernel_task_active 401 | 402 | ; return parent ID 403 | mov rdx, qword [r9 + KERNEL_STRUCTURE_TASK.pid] 404 | 405 | ; restore original registers 406 | pop r9 407 | 408 | ; return from routine 409 | ret 410 | 411 | ;------------------------------------------------------------------------------- 412 | ; out: 413 | ; rax - ID of currrent task 414 | kernel_task_pid: 415 | ; preserve original flags 416 | push r8 417 | pushf 418 | 419 | ; turn off interrupts 420 | ; we cannot allow task switch 421 | ; when looking for current task pointe 422 | cli 423 | 424 | ; retrieve CPU id 425 | call kernel_lapic_id 426 | 427 | ; set pointer to current task of CPU 428 | mov r8, qword [kernel] 429 | mov r8, qword [r8 + KERNEL.task_cpu_address] 430 | mov r8, qword [r8 + rax * STD_SIZE_PTR_byte] 431 | mov rax, qword [r8 + KERNEL_STRUCTURE_TASK.pid] 432 | 433 | ; restore original flags 434 | popf 435 | pop r8 436 | 437 | ; return from routine 438 | ret -------------------------------------------------------------------------------- /kernel/task.inc: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | %ifndef KERNEL_TASK 6 | %define KERNEL_TASK 7 | 8 | %define KERNEL_TASK_EFLAGS_cf 000000000000000000000001b 9 | %define KERNEL_TASK_EFLAGS_df 000000000000010000000000b 10 | %define KERNEL_TASK_EFLAGS_if 000000000000001000000000b 11 | %define KERNEL_TASK_EFLAGS_zf 000000000000000001000000b 12 | %define KERNEL_TASK_EFLAGS_default KERNEL_TASK_EFLAGS_if 13 | 14 | %define KERNEL_TASK_FLAG_active 0000000000000001b 15 | %define KERNEL_TASK_FLAG_exec 0000000000000010b 16 | %define KERNEL_TASK_FLAG_close 0000000000000100b 17 | %define KERNEL_TASK_FLAG_module 0000000000001000b 18 | %define KERNEL_TASK_FLAG_thread 0000000000010000b 19 | %define KERNEL_TASK_FLAG_sleep 0000000000100000b 20 | %define KERNEL_TASK_FLAG_init 0100000000000000b 21 | %define KERNEL_TASK_FLAG_secured 1000000000000000b 22 | 23 | %define KERNEL_TASK_limit (8192 / KERNEL_STRUCTURE_TASK.SIZE) ; hard limit 24 | 25 | ; TODO, remove me after refactoring 26 | %define KERNEL_TASK_irq 0x20 27 | 28 | %define KERNEL_TASK_NAME_limit 254 29 | 30 | %define KERNEL_TASK_STACK_pointer KERNEL_LIBRARY_base_address 31 | %define KERNEL_TASK_STACK_limit STD_PAGE_byte 32 | 33 | struc KERNEL_STRUCTURE_TASK 34 | .cr3 resq 1 35 | .rsp resq 1 36 | .pid resq 1 37 | .pid_parent resq 1 38 | .sleep resq 1 39 | .storage resq 1 40 | .directory resq 1 41 | .page resq 1 ; amount of pages assigned to process 42 | .page_type resb 1 43 | .stack resq 1 ; size of stack in Pages 44 | .time resq 1 45 | .time_previous resq 1 46 | .stream_in resq 1 47 | .stream_out resq 1 48 | .memory_map resq 1 49 | .flags resw 1 50 | .name_length resb 1 51 | .name resb KERNEL_TASK_NAME_limit + 1 52 | .SIZE: 53 | endstruc 54 | %endif -------------------------------------------------------------------------------- /kernel/tss.inc: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | %ifndef KERNEL_TSS 6 | %define KERNEL_TSS 7 | 8 | %define KERNEL_TSS_OFFSET 0x06 9 | 10 | struc KERNEL_STRUCTURE_TSS 11 | .reserved resd 1 12 | .rsp0 resq 1 13 | .unused resb 92; 14 | .SIZE: 15 | endstruc 16 | 17 | struc KERNEL_STRUCTURE_TSS_ENTRY 18 | .limit_low resw 1 19 | .base_low resw 1 20 | .base_middle resb 1 21 | .access resb 1 22 | .flags_and_limit_high resb 1 23 | .base_high resb 1 24 | .base_64bit resd 1 25 | .reserved resd 1 26 | endstruc 27 | %endif -------------------------------------------------------------------------------- /library/elf.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;---------------------------------------------------------------------- 6 | ; variables, structures, definitions 7 | ;---------------------------------------------------------------------- 8 | %ifndef LIB_ELF 9 | %include "./elf.inc" 10 | %endif 11 | 12 | ; we are using Position Independed Code 13 | default rel 14 | 15 | ; 64 bit code 16 | [bits 64] 17 | 18 | ; information for linker 19 | section .text 20 | 21 | ;------------------------------------------------------------------------------- 22 | ; in: 23 | ; rdi - pointer to beginning of file 24 | ; out: 25 | ; CF - if its not an ELF64 file 26 | lib_elf_identify: 27 | ; by default 28 | clc 29 | 30 | ; file contains ELF header? 31 | cmp dword [rdi + LIB_ELF_STRUCTURE.magic_number], 0x464C457F 32 | je .done ; yes 33 | 34 | ; undefinied file 35 | stc 36 | 37 | .done: 38 | ; return from routine 39 | ret 40 | -------------------------------------------------------------------------------- /library/elf.inc: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | %ifndef LIB_ELF 6 | %define LIB_ELF 7 | 8 | %define LIB_ELF_HEADER_magic_number 0x464C457F ; 0x7F, 'E, 'L', 'F' 9 | 10 | %define LIB_ELF_FLAG_execute 00000001b ; segment is executable 11 | %define LIB_ELF_FLAG_write 00000010b ; segment is writable 12 | 13 | %define LIB_ELF_TYPE_unknown 0x00 14 | %define LIB_ELF_TYPE_relocatable 0x01 15 | %define LIB_ELF_TYPE_executable 0x02 16 | %define LIB_ELF_TYPE_shared_object 0x03 17 | 18 | %define LIB_ELF_HEADER_TYPE_load 1 19 | 20 | %define LIB_ELF_SECTION_TYPE_null 0x00 21 | %define LIB_ELF_SECTION_TYPE_progbits 0x01 22 | %define LIB_ELF_SECTION_TYPE_symtab 0x02 23 | %define LIB_ELF_SECTION_TYPE_strtab 0x03 24 | %define LIB_ELF_SECTION_TYPE_rela 0x04 25 | %define LIB_ELF_SECTION_TYPE_hash 0x05 26 | %define LIB_ELF_SECTION_TYPE_dynamic 0x06 27 | %define LIB_ELF_SECTION_TYPE_note 0x07 28 | %define LIB_ELF_SECTION_TYPE_nobits 0x08 29 | %define LIB_ELF_SECTION_TYPE_rel 0x09 30 | %define LIB_ELF_SECTION_TYPE_shlib 0x0A 31 | %define LIB_ELF_SECTION_TYPE_dynsym 0x0B 32 | 33 | %define LIB_ELF_SECTION_DYNAMIC_TYPE_needed 1 34 | 35 | struc LIB_ELF_STRUCTURE 36 | .magic_number resd 1 37 | .class resb 1 38 | .memory_layout resb 1 39 | .header_version resb 1 40 | .abi resb 1 41 | .abi_version resb 1 42 | .padding resb 7 43 | .type resw 1 44 | .instruction_set resw 1 45 | .elf_version resd 1 46 | ;-------------------------------- 47 | .entry_ptr resq 1 48 | .headers_offset resq 1 49 | .sections_offset resq 1 50 | ;-------------------------------- 51 | .flags resd 1 52 | .header_size resw 1 53 | .header_table_size resw 1 54 | .h_entry_count resw 1 55 | .section_table_size resw 1 56 | .s_entry_count resw 1 57 | .correlation resw 1 58 | endstruc 59 | 60 | struc LIB_ELF_STRUCTURE_HEADER 61 | .type resd 1 62 | .flags resd 1 63 | .segment_offset resq 1 64 | .virtual_address resq 1 65 | .physical_address resq 1 66 | .segment_size resq 1 67 | .memory_size resq 1 68 | .alignment resq 1 69 | .SIZE: 70 | endstruc 71 | 72 | struc LIB_ELF_STRUCTURE_SECTION 73 | .name resd 1 74 | .type resd 1 75 | .flags resq 1 76 | .virtual_address resq 1 77 | .file_offset resq 1 78 | .size_byte resq 1 79 | .link resd 1 80 | .info resd 1 81 | .alignment resq 1 82 | .entry_count resq 1 83 | .SIZE: 84 | endstruc 85 | 86 | struc LIB_ELF_STRUCTURE_DYNAMIC_ENTRY 87 | .type resq 1 88 | .name_offset resq 1 89 | .SIZE: 90 | endstruc 91 | 92 | struc LIB_ELF_STRUCTURE_DYNAMIC_SYMBOL 93 | .name_offset resd 1 94 | .flags resd 1 95 | .address resq 1 96 | .size_byte resq 1 97 | .SIZE: 98 | endstruc 99 | 100 | struc LIB_ELF_STRUCTURE_DYNAMIC_RELOCATION 101 | .offset resq 1 102 | .flags resd 1 103 | .index resd 1 104 | .symbol_value resq 1 105 | .SIZE: 106 | endstruc 107 | %endif -------------------------------------------------------------------------------- /library/macro.inc: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | %ifndef MACRO 6 | %define MACRO 7 | 8 | ; Bochs Enchanced Debugger: line break 9 | %macro MACRO_DEBUF 0 10 | xchg bx, bx 11 | %endmacro 12 | 13 | %define MACRO_PAGE_ALIGN_UP( value )( ((value) + ~STD_PAGE_mask) & STD_PAGE_mask ) 14 | %define MACRO_PAGE_ALIGN_DOWN( value )( (value) & ~(STD_PAGE_byte - 1) ) 15 | 16 | %macro MACRO_PAGE_ALIGN_UP_REGISTER 1 17 | add %1, ~STD_PAGE_mask ; align up 18 | and %1, STD_PAGE_mask ; to page boundaries 19 | %endmacro 20 | %endif 21 | -------------------------------------------------------------------------------- /library/std.inc: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | %ifndef STD 6 | %define STD 7 | 8 | ; definitions, that are always nice to have 9 | %include "./library/macro.inc" 10 | 11 | %ifndef LIB_VFS 12 | %include "./library/vfs.inc" 13 | %endif 14 | 15 | %define EMPTY 0 16 | %define INIT EMPTY 17 | 18 | %define FALSE 0 19 | %define TRUE 1 20 | 21 | %define LOCK TRUE 22 | %define UNLOCK FALSE 23 | 24 | ; listed alphabetically below 25 | 26 | %define STD_ASCII_TERMINATOR EMPTY 27 | %define STD_ASCII_DIFFERENCE_0_A 0x07 28 | %define STD_ASCII_BACKSPACE 0x08 29 | %define STD_ASCII_TAB 0x09 30 | %define STD_ASCII_NEW_LINE 0x0A 31 | %define STD_ASCII_RETURN 0x0D 32 | %define STD_ASCII_ESC 0x1B 33 | %define STD_ASCII_SPACE 0x20 34 | %define STD_ASCII_EXCLAMATION 0x21 35 | %define STD_ASCII_QUOTATION 0x22 36 | %define STD_ASCII_DOLLAR 0x24 37 | %define STD_ASCII_PERCENT 0x25 38 | %define STD_ASCII_AMPERSAND 0x26 39 | %define STD_ASCII_APOSTROPHE 0x27 40 | %define STD_ASCII_ASTERISK 0x2A 41 | %define STD_ASCII_PLUS 0x2B 42 | %define STD_ASCII_COMMA 0x2C 43 | %define STD_ASCII_MINUS 0x2D 44 | %define STD_ASCII_DOT 0x2E 45 | %define STD_ASCII_SLASH 0x2F 46 | %define STD_ASCII_DIGIT_0 0x30 47 | %define STD_ASCII_DIGIT_1 0x31 48 | %define STD_ASCII_DIGIT_2 0x32 49 | %define STD_ASCII_DIGIT_3 0x33 50 | %define STD_ASCII_DIGIT_4 0x34 51 | %define STD_ASCII_DIGIT_5 0x35 52 | %define STD_ASCII_DIGIT_6 0x36 53 | %define STD_ASCII_DIGIT_7 0x37 54 | %define STD_ASCII_DIGIT_8 0x38 55 | %define STD_ASCII_DIGIT_9 0x39 56 | %define STD_ASCII_COLON 0x3A 57 | %define STD_ASCII_SEMICOLON 0x3B 58 | %define STD_ASCII_LOWER_THAN 0x3C 59 | %define STD_ASCII_GREATER_THAN 0x3E 60 | %define STD_ASCII_QUESTION_MARK 0x3F 61 | %define STD_ASCII_LETTER_A 0x41 62 | %define STD_ASCII_LETTER_F 0x46 63 | %define STD_ASCII_LETTER_N 0x4E 64 | %define STD_ASCII_LETTER_T 0x54 65 | %define STD_ASCII_LETTER_Z 0x5A 66 | %define STD_ASCII_BRACKET_SQUARE_OPEN 0x5B 67 | %define STD_ASCII_BACKSLASH 0x5C 68 | %define STD_ASCII_BRACKET_SQUARE_CLOSE 0x5D 69 | %define STD_ASCII_CARET 0x5E 70 | %define STD_ASCII_GRAVE 0x60 71 | %define STD_ASCII_LETTER_a 0x61 72 | %define STD_ASCII_LETTER_b 0x62 73 | %define STD_ASCII_LETTER_c 0x63 74 | %define STD_ASCII_LETTER_d 0x64 75 | %define STD_ASCII_LETTER_f 0x66 76 | %define STD_ASCII_LETTER_h 0x68 77 | %define STD_ASCII_LETTER_i 0x69 78 | %define STD_ASCII_LETTER_l 0x6C 79 | %define STD_ASCII_LETTER_n 0x6E 80 | %define STD_ASCII_LETTER_q 0x71 81 | %define STD_ASCII_LETTER_r 0x72 82 | %define STD_ASCII_LETTER_s 0x73 83 | %define STD_ASCII_LETTER_t 0x74 84 | %define STD_ASCII_LETTER_u 0x75 85 | %define STD_ASCII_LETTER_x 0x78 86 | %define STD_ASCII_LETTER_z 0x7A 87 | %define STD_ASCII_BRACLET_OPEN 0x7B 88 | %define STD_ASCII_STREAM 0x7C 89 | %define STD_ASCII_BRACLET_CLOSE 0x7D 90 | %define STD_ASCII_TILDE 0x7E 91 | %define STD_ASCII_DELETE 0x7F 92 | 93 | %define STD_COLOR_mask 0xFF000000 94 | %define STD_COLOR_BLACK 0xFF000000 95 | %define STD_COLOR_DARK 0xFF272727 96 | %define STD_COLOR_RED 0xFF800000 97 | %define STD_COLOR_GREEN 0xFF008000 98 | %define STD_COLOR_BROWN 0xFF808000 99 | %define STD_COLOR_BLUE 0xFF000080 100 | %define STD_COLOR_MAGENTA 0xFF800080 101 | %define STD_COLOR_CYAN 0xFF008080 102 | %define STD_COLOR_GRAY_LIGHT 0xFFC0C0C0 103 | %define STD_COLOR_GRAY 0xFF808080 104 | %define STD_COLOR_REG_LIGHT 0xFFFF0000 105 | %define STD_COLOR_GREEN_LIGHT 0xFFFFFF00 106 | %define STD_COLOR_YELLOW 0xFF00FF00 107 | %define STD_COLOR_BLUE_LIGHT 0xFF0000FF 108 | %define STD_COLOR_MAGENTA_LIGHT 0xFFFF00FF 109 | %define STD_COLOR_CYAN_LIGHT 0xFF00FFFF 110 | %define STD_COLOR_WHITE 0xFFFFFFFF 111 | 112 | %define STD_ERROR_file_not_found -1 113 | %define STD_ERROR_memory_low -2 114 | %define STD_ERROR_file_unknown -3 115 | %define STD_ERROR_file_not_executable -4 116 | %define STD_ERROR_syntax_error -5 // provided values or structure is invalid 117 | %define STD_ERROR_overflow -6 118 | %define STD_ERROR_file_dependence -7 119 | %define STD_ERROR_limit -8 120 | %define STD_ERROR_locked -9 121 | %define STD_ERROR_unavailable -10 122 | 123 | ; %define STD_FILE_MODE_reserved 0b00000001 124 | ; %define STD_FILE_MODE_read 0b00000010 125 | ; %define STD_FILE_MODE_write 0b00000100 126 | ; %define STD_FILE_MODE_append 0b00001000 127 | 128 | %define STD_FILE_NAME_limit LIB_VFS_NAME_limit 129 | 130 | %define STD_FILE_TOUCH_file STD_FILE_TYPE_file 131 | %define STD_FILE_TOUCH_directory STD_FILE_TYPE_directory 132 | 133 | %define STD_FILE_TYPE_file 0b00000001 134 | %define STD_FILE_TYPE_directory 0b00000010 135 | %define STD_FILE_TYPE_link 0b00000100 136 | 137 | %define STD_IPC_SIZE_byte 40 138 | 139 | %define STD_IPC_TYPE_keyboard 0x00 140 | %define STD_IPC_TYPE_mouse 0x01 141 | %define STD_IPC_TYPE_event 0xFF 142 | 143 | %define STD_IPC_MOUSE_BUTTON_left 0b00000001 144 | %define STD_IPC_MOUSE_BUTTON_right 0b00000010 145 | %define STD_IPC_MOUSE_BUTTON_middle 0b00000100 146 | %define STD_IPC_MOUSE_BUTTON_release 0b10000000 147 | 148 | struc STD_IPC_STRUCTURE 149 | .ttl resq 1 150 | .source resq 1 151 | .target resq 1 152 | .data resb STD_IPC_SIZE_byte ; first Byte of data defines TYPE 153 | .SIZE: 154 | endstruc 155 | 156 | struc STD_IPC_STRUCTURE_DEFAULT 157 | .type resb 1 158 | endstruc 159 | 160 | %define STD_KEY_BACKSPACE 0x0008 161 | %define STD_KEY_TAB 0x0009 162 | %define STD_KEY_LINE 0x000A 163 | %define STD_KEY_ENTER 0x000D 164 | %define STD_KEY_ESC 0x001B 165 | %define STD_KEY_CTRL_LEFT 0x001D 166 | %define STD_KEY_SPACE 0x0020 167 | %define STD_KEY_RELEASE 0x0080 168 | %define STD_KEY_SHIFT_LEFT 0xE02A 169 | %define STD_KEY_SHIFT_RIGHT 0xE036 170 | %define STD_KEY_NUMLOCK_MULTIPLY 0xE037 171 | %define STD_KEY_ALT_LEFT 0xE038 172 | %define STD_KEY_CAPSLOCK 0xE03A 173 | %define STD_KEY_F1 0xE03B 174 | %define STD_KEY_F2 0xE03C 175 | %define STD_KEY_F3 0xE03D 176 | %define STD_KEY_F4 0xE03E 177 | %define STD_KEY_F5 0xE03F 178 | %define STD_KEY_F6 0xE040 179 | %define STD_KEY_F7 0xE041 180 | %define STD_KEY_F8 0xE042 181 | %define STD_KEY_F9 0xE043 182 | %define STD_KEY_F10 0xE044 183 | %define STD_KEY_NUMLOCK 0xE045 184 | %define STD_KEY_SCROLL_LOCK 0xE046 185 | %define STD_KEY_NUMLOCK_MINUS 0xE04A 186 | %define STD_KEY_NUMLOCK_4 0xE14B 187 | %define STD_KEY_NUMLOCK_5 0xE04C 188 | %define STD_KEY_NUMLOCK_6 0xE14D 189 | %define STD_KEY_NUMLOCK_PLUS 0xE04E 190 | %define STD_KEY_NUMLOCK_7 0xE047 191 | %define STD_KEY_NUMLOCK_8 0xE048 192 | %define STD_KEY_NUMLOCK_9 0xE049 193 | %define STD_KEY_NUMLOCK_1 0xE14F 194 | %define STD_KEY_NUMLOCK_2 0xE150 195 | %define STD_KEY_NUMLOCK_3 0xE151 196 | %define STD_KEY_NUMLOCK_0 0xE152 197 | %define STD_KEY_NUMLOCK_DOT 0xE153 198 | %define STD_KEY_F11 0xE057 199 | %define STD_KEY_F12 0xE158 200 | %define STD_KEY_CTRL_RIGHT 0xE01D 201 | %define STD_KEY_NUMLOCK_DIVIDE 0xE035 202 | %define STD_KEY_ALT_RIGHT 0xE038 203 | %define STD_KEY_HOME 0xE047 204 | %define STD_KEY_ARROW_UP 0xE048 205 | %define STD_KEY_PAGE_UP 0xE049 206 | %define STD_KEY_ARROW_LEFT 0xE04B 207 | %define STD_KEY_ARROW_RIGHT 0xE04D 208 | %define STD_KEY_END 0xE04F 209 | %define STD_KEY_ARROW_DOWN 0xE050 210 | %define STD_KEY_PAGE_DOWN 0xE051 211 | %define STD_KEY_INSERT 0xE052 212 | %define STD_KEY_DELETE 0xE053 213 | %define STD_KEY_MENU 0xE05B 214 | %define STD_KEY_SUBMENU 0xE05D 215 | 216 | %define STD_MASK_word 0x000000000000FFFF 217 | 218 | %define STD_MAX_unsigned -1 219 | 220 | %define STD_MOUSE_BUTTON_left 0b00000001 221 | %define STD_MOUSE_BUTTON_right 0b00000010 222 | %define STD_MOUSE_BUTTON_middle 0b00000100 223 | 224 | %define STD_MOVE_BYTE_half 4 225 | %define STD_MOVE_BYTE 8 226 | %define STD_MOVE_WORD 16 227 | %define STD_MOVE_DWORD 32 228 | 229 | %define STD_NETWORK_PROTOCOL_arp 0x00 230 | %define STD_NETWORK_PROTOCOL_icmp 0x01 231 | %define STD_NETWORK_PROTOCOL_udp 0x02 232 | %define STD_NETWORK_PROTOCOL_tcp 0x03 233 | 234 | %define STD_NUMBER_SYSTEM_decimal 10 235 | %define STD_NUMBER_SYSTEM_hexadecimal 16 236 | 237 | %define STD_PAGE_page 1 238 | %define STD_PAGE_byte 0x1000 239 | %define STD_PAGE_mask 0xFFFFFFFFFFFFF000 240 | 241 | %define STD_SHIFT_2 1 242 | %define STD_SHIFT_4 2 243 | %define STD_SHIFT_8 3 244 | %define STD_SHIFT_16 4 245 | %define STD_SHIFT_32 5 246 | %define STD_SHIFT_64 6 247 | %define STD_SHIFT_PTR STD_SHIFT_64 248 | %define STD_SHIFT_128 7 249 | %define STD_SHIFT_256 8 250 | %define STD_SHIFT_512 9 251 | %define STD_SHIFT_1024 10 252 | %define STD_SHIFT_2048 11 253 | %define STD_SHIFT_4096 12 254 | %define STD_SHIFT_PAGE STD_SHIFT_4096 255 | %define STD_SHIFT_65536 16 256 | 257 | %define STD_SIGN_BYTE_bit 7 258 | %define STD_SIGN_WORD_bit 15 259 | %define STD_SIGN_DWORD_bit 31 260 | %define STD_SIGN_QWORD_bit 63 261 | 262 | %define STD_SIZE_BYTE_byte 1 263 | %define STD_SIZE_BYTE_bit 8 264 | %define STD_SIZE_WORD_byte 2 265 | %define STD_SIZE_WORD_bit 16 266 | %define STD_SIZE_DWORD_byte 4 267 | %define STD_SIZE_DWORD_bit 32 268 | %define STD_SIZE_QWORD_byte 8 269 | %define STD_SIZE_QWORD_bit 64 270 | %define STD_SIZE_PTR_byte STD_SIZE_QWORD_byte 271 | 272 | %define STD_STREAM_SIZE_page 1 ; less or equal to 16, limited by struct KERNEL_STRUCTURE_STREAM 273 | 274 | %define STD_STREAM_FLOW_out_to_parent_in 0b00000001 275 | %define STD_STREAM_FLOW_out_to_in 0b00000010 276 | 277 | %define STD_STREAM_OUT 0x00 278 | %define STD_STREAM_IN 0x01 279 | 280 | %define STD_STREAM_META_limit 8 281 | 282 | %define STD_SYSCALL_EXIT 0x00 283 | %define STD_SYSCALL_FRAMEBUFFER 0x01 284 | %define STD_SYSCALL_MEMORY_ALLOC 0x02 285 | %define STD_SYSCALL_MEMORY_RELEASE 0x03 286 | %define STD_SYSCALL_UPTIME 0x04 287 | %define STD_SYSCALL_LOG 0x05 288 | %define STD_SYSCALL_THREAD 0x06 289 | %define STD_SYSCALL_PID 0x07 290 | %define STD_SYSCALL_EXEC 0x08 291 | %define STD_SYSCALL_PID_CHECK 0x09 292 | %define STD_SYSCALL_IPC_SEND 0x0A 293 | %define STD_SYSCALL_IPC_RECEIVE 0x0B 294 | %define STD_SYSCALL_MEMORY_SHARE 0x0C 295 | %define STD_SYSCALL_MOUSE 0x0D 296 | %define STD_SYSCALL_FRAMEBUFFER_CHANGE 0x0E 297 | %define STD_SYSCALL_IPC_RECEIVE_BY_PID 0x0F 298 | %define STD_SYSCALL_STREAM_OUT 0x10 299 | %define STD_SYSCALL_STREAM_IN 0x11 300 | %define STD_SYSCALL_KEYBOARD 0x12 301 | %define STD_SYSCALL_STREAM_SET 0x13 302 | %define STD_SYSCALL_STREAM_GET 0x14 303 | %define STD_SYSCALL_MEMORY 0x15 304 | %define STD_SYSCALL_SLEEP 0x16 305 | %define STD_SYSCALL_FILE_OPEN 0x17 306 | %define STD_SYSCALL_FILE_CLOSE 0x18 307 | %define STD_SYSCALL_CD 0x19 308 | %define STD_SYSCALL_IPC_RECEIVE_BY_TYPE 0x1A 309 | %define STD_SYSCALL_MICROTIME 0x1B 310 | %define STD_SYSCALL_TIME 0x1C 311 | %define STD_SYSCALL_FILE_READ 0x1D 312 | %define STD_SYSCALL_FILE 0x1E 313 | %define STD_SYSCALL_FILE_WRITE 0x1F 314 | %define STD_SYSCALL_FILE_TOUCH 0x20 315 | %define STD_SYSCALL_TASK 0x21 316 | %define STD_SYSCALL_KILL 0x22 317 | %define STD_SYSCALL_NETWORK_INTERFACE 0x23 318 | %define STD_SYSCALL_NETWORK_OPEN 0x24 319 | %define STD_SYSCALL_NETWORK_SEND 0x25 320 | %define STD_SYSCALL_NETWORK_INTERFACE_SET 0x26 321 | %define STD_SYSCALL_NETWORK_RECEIVE 0x27 322 | 323 | %define STD_TASK_FLAG_active 0b0000000000000001 324 | %define STD_TASK_FLAG_exec 0b0000000000000010 325 | %define STD_TASK_FLAG_close 0b0000000000000100 326 | %define STD_TASK_FLAG_module 0b0000000000001000 327 | %define STD_TASK_FLAG_thread 0b0000000000010000 328 | %define STD_TASK_FLAG_sleep 0b0000000000100000 329 | %define STD_TASK_FLAG_init 0b0100000000000000 330 | %define STD_TASK_FLAG_secured 0b1000000000000000 331 | 332 | %define STD_VIDEO_DEPTH_shift 2 333 | %define STD_VIDEO_DEPTH_byte 4 334 | %define STD_VIDEO_DEPTH_bit 32 335 | 336 | %define STD_WINDOW_FLAG_active 0b0000000000000001 337 | %define STD_WINDOW_FLAG_visible 0b0000000000000010 338 | %define STD_WINDOW_FLAG_fixed_xy 0b0000000000000100 339 | %define STD_WINDOW_FLAG_fixed_z 0b0000000000001000 340 | %define STD_WINDOW_FLAG_release 0b0000000000010000 ; window marked as ready to be removed 341 | %define STD_WINDOW_FLAG_name 0b0000000000100000 342 | %define STD_WINDOW_FLAG_minimize 0b0000000001000000 343 | %define STD_WINDOW_FLAG_unstable 0b0000000010000000 ; hide window on any mouse button press 344 | %define STD_WINDOW_FLAG_resizable 0b0000000100000000 345 | %define STD_WINDOW_FLAG_properties 0b0000001000000000 ; Window Manager proposed new window properties 346 | %define STD_WINDOW_FLAG_maximize 0b0000010000000000 347 | %define STD_WINDOW_FLAG_flush 0b0010000000000000 348 | %define STD_WINDOW_FLAG_taskbar 0b0100000000000000 349 | %define STD_WINDOW_FLAG_cursor 0b1000000000000000 350 | 351 | %define STD_WINDOW_REQUEST_create 0b00000001 352 | %define STD_WINDOW_REQUEST_active 0b00000010 353 | 354 | %define STD_WINDOW_ANSWER_create 0b10000000 | STD_WINDOW_REQUEST_create 355 | %define STD_WINDOW_ANSWER_active 0b10000000 | STD_WINDOW_REQUEST_active 356 | %endif -------------------------------------------------------------------------------- /library/string/compare.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;----------------------------------------------------------------------- 6 | ; structures, definitions 7 | ;----------------------------------------------------------------------- 8 | ; global --------------------------------------------------------------- 9 | %include "library/std.inc" ; not required, but nice to have 10 | ;======================================================================= 11 | 12 | ;------------------------------------------------------------------------------- 13 | ; in: 14 | ; rcx - length to compare 15 | ; rsi - pointer to first string 16 | ; rdi - pointer to second string 17 | ; out: 18 | ; CF - if doesn't match 19 | lib_string_compare: 20 | ; preserve original registers 21 | push rax 22 | push rcx 23 | push rsi 24 | push rdi 25 | 26 | .loop: 27 | ; load first character from string 28 | lodsb 29 | 30 | ; characters equal? 31 | cmp al, byte [rdi] 32 | jne .error ; no 33 | 34 | ; move pointer to next character 35 | inc rdi 36 | 37 | ; strings match? 38 | dec rcx 39 | jnz .loop ; not, yet 40 | 41 | ; they match 42 | clc 43 | jmp .end 44 | 45 | .error: 46 | ; doesn't match 47 | stc 48 | 49 | .end: 50 | ; restore original registers 51 | pop rdi 52 | pop rsi 53 | pop rcx 54 | pop rax 55 | 56 | ; return from routine 57 | ret 58 | -------------------------------------------------------------------------------- /library/string/length.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;----------------------------------------------------------------------- 6 | ; structures, definitions 7 | ;----------------------------------------------------------------------- 8 | ; global --------------------------------------------------------------- 9 | %include "library/std.inc" ; not required, but nice to have 10 | ;======================================================================= 11 | 12 | ;------------------------------------------------------------------------------- 13 | ; in: 14 | ; rsi - pointer to string 15 | ; out: 16 | ; rcx - length of string in bytes 17 | lib_string_length: 18 | ; preserve original register 19 | push rsi 20 | 21 | ; empty string as default 22 | mov rcx, STD_MAX_unsigned 23 | 24 | .next: 25 | ; length of current string 26 | inc rcx 27 | 28 | ; consider next byte 29 | inc rsi 30 | 31 | ; not end of string? 32 | cmp byte [rsi - 1], STD_ASCII_TERMINATOR 33 | jne .next ; yes 34 | 35 | .end: 36 | ; restore original register 37 | pop rsi 38 | 39 | ; return from routine 40 | ret 41 | -------------------------------------------------------------------------------- /library/string/word.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;----------------------------------------------------------------------- 6 | ; structures, definitions 7 | ;----------------------------------------------------------------------- 8 | ; global --------------------------------------------------------------- 9 | %include "library/std.inc" ; not required, but nice to have 10 | ;======================================================================= 11 | 12 | ;------------------------------------------------------------------------------- 13 | ;=============================================================================== 14 | ; in: 15 | ; rcx - length of string 16 | ; rsi - pointer to string 17 | ; out: 18 | ; rbx - length of string up to first separator 19 | lib_string_word: 20 | ; preserve original registers 21 | push rcx 22 | 23 | ; counter 24 | xor ebx, ebx 25 | 26 | .search: 27 | ; separator found? 28 | cmp byte [rsi + rbx], STD_ASCII_EXCLAMATION 29 | jb .end ; yes 30 | cmp byte [rsi + rbx], STD_ASCII_TILDE 31 | ja .end ; yes 32 | 33 | ; word size 34 | inc rbx 35 | 36 | ; end of string? 37 | dec rcx 38 | jnz .search ; no 39 | 40 | .end: 41 | ; restore original registers 42 | pop rcx 43 | 44 | ; return from routine 45 | ret 46 | -------------------------------------------------------------------------------- /library/sys.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;----------------------------------------------------------------------- 6 | ; structures, definitions 7 | ;----------------------------------------------------------------------- 8 | ; global --------------------------------------------------------------- 9 | %include "library/std.inc" ; not required, but nice to have 10 | ; library -------------------------------------------------------------- 11 | %ifndef LIB_SYS 12 | %include "library/sys.inc" 13 | %endif 14 | ;======================================================================= 15 | 16 | ; 64 bit code 17 | [bits 64] 18 | 19 | ; we are using Position Independed Code 20 | default rel 21 | 22 | ;------------------------------------------------------------------------------- 23 | ; in: 24 | ; interchangeably due to the LIB_SYS_REQUEST_* 25 | lib_sys_request: 26 | ; preserve original registers 27 | push rcx 28 | push r11 29 | 30 | ; execute request 31 | syscall 32 | 33 | ; restore original registers 34 | pop r11 35 | pop rcx 36 | 37 | ; return from routine 38 | ret 39 | 40 | ;=============================================================================== 41 | ; SUBSTITUTE OF LIBC 42 | ;=============================================================================== 43 | 44 | ; yes, it's so simple ;) 45 | ; + small code 46 | ; - horrific amount of wasted memory (Hello, Chrome!) 47 | 48 | ;------------------------------------------------------------------------------- 49 | ; in: 50 | ; rdi - length of space in Bytes 51 | ; out: 52 | ; rax - pointer to allocated space 53 | ; or EMPTY if no enough memory 54 | malloc: 55 | ; preserve original registers 56 | push rdi 57 | 58 | ; request for definied space 59 | mov eax, LIB_SYS_REQUEST_MEMORY_ALLOC 60 | add rdi, STD_SIZE_QWORD_byte << STD_SHIFT_2 61 | call lib_sys_request 62 | jc .end ; not enough space 63 | 64 | ; store information about size of this space 65 | add rdi, STD_PAGE_mask 66 | shr rdi, STD_SHIFT_PAGE 67 | mov qword [rax], rdi 68 | 69 | ; return pointer to space 70 | add rax, STD_SIZE_QWORD_byte << STD_SHIFT_2 71 | 72 | .end: 73 | ; restore original registers 74 | pop rdi 75 | 76 | ; return from routine 77 | ret 78 | 79 | ;------------------------------------------------------------------------------- 80 | ; in: 81 | ; rdi - pointer to allocated space 82 | free: 83 | ; preserve original registers 84 | push rax 85 | push rsi 86 | push rdi 87 | 88 | ; request for definied space 89 | mov eax, LIB_SYS_REQUEST_MEMORY_RELEASE 90 | mov rsi, qword [rdi - (STD_SIZE_QWORD_byte << STD_SHIFT_2)] 91 | and di, STD_PAGE_mask 92 | call lib_sys_request 93 | 94 | .end: 95 | ; restore original registers 96 | pop rdi 97 | pop rsi 98 | pop rax 99 | 100 | ; return from routine 101 | ret 102 | -------------------------------------------------------------------------------- /library/sys.inc: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | %ifndef LIB_SYS 6 | %define LIB_SYS 7 | 8 | %define LIB_SYS_ERROR_undefinied -1 9 | %define LIB_SYS_ERROR_memory_no_enough 1 10 | %define LIB_SYS_ERROR_file_not_found 2 11 | %define LIB_SYS_ERROR_exec_not_executable 3 12 | 13 | %define LIB_SYS_REQUEST_EXIT 0x00 14 | %define LIB_SYS_REQUEST_FRAMEBUFFER 0x01 15 | %define LIB_SYS_REQUEST_MEMORY_ALLOC 0x02 16 | %define LIB_SYS_REQUEST_MEMORY_RELEASE 0x03 17 | %define LIB_SYS_REQUEST_TASK_PID 0x04 18 | %define LIB_SYS_REQUEST_DRIVER_MOUSE 0x05 19 | %define LIB_SYS_REQUEST_STORAGE_READ_FILE 0x06 20 | %define LIB_SYS_REQUEST_EXEC 0x07 21 | %define LIB_SYS_REQUEST_IPC_SEND 0x08 22 | %define LIB_SYS_REQUEST_IPC_RECEIVE 0x09 23 | %define LIB_SYS_REQUEST_MEMORY_SHARE 0x0A 24 | %define LIB_SYS_REQUEST_KEYBOARD 0x0B 25 | %define LIB_SYS_REQUEST_TASK_STATUS 0x0C 26 | %define LIB_SYS_REQUEST_STREAM_OUT 0x0D 27 | %define LIB_SYS_REQUEST_STREAM_IN 0x0E 28 | %define LIB_SYS_REQUEST_SERIAL_CHAR 0x0F 29 | %define LIB_SYS_REQUEST_SERIAL_STRING 0x10 30 | %define LIB_SYS_REQUEST_SERIAL_VALUE 0x11 31 | %define LIB_SYS_REQUEST_TIME 0x12 32 | %define LIB_SYS_REQUEST_STREAM_SET 0x13 33 | %define LIB_SYS_REQUEST_STREAM_GET 0x14 34 | %define LIB_SYS_REQUEST_SLEEP 0x15 35 | %define LIB_SYS_REQUEST_UPTIME 0x16 36 | %define LIB_SYS_REQUEST_STREAM_OUT_VALUE 0x17 37 | %define LIB_SYS_REQUEST_TASK 0x18 38 | %define LIB_SYS_REQUEST_MEMORY 0x19 39 | %define LIB_SYS_REQUEST_THREAD 0x1A 40 | 41 | struc LIB_SYS_STRUCTURE_MEMORY 42 | .total resq 1 43 | .available resq 1 44 | .SIZE: 45 | endstruc 46 | 47 | struc LIB_SYS_STRUCTURE_FRAMEBUFFER 48 | .width_pixel resw 1 49 | .height_pixel resw 1 50 | .base_address resq 1 51 | .scanline_byte resq 1 52 | .pid resq 1 53 | .SIZE: 54 | endstruc 55 | 56 | %define LIB_SYS_STREAM_SIZE_byte 4096 57 | 58 | %define LIB_SYS_STREAM_FLOW_out_to_parent_out 00000001b 59 | %define LIB_SYS_STREAM_FLOW_out_to_parent_in 00000010b 60 | %define LIB_SYS_STREAM_FLOW_out_to_in 00000100b 61 | 62 | %define LIB_SYS_STREAM_META_LENGTH_byte 0x08 63 | 64 | %define LIB_SYS_STREAM_FLAG_data 00000001b 65 | %define LIB_SYS_STREAM_FLAG_undefinied 00000010b 66 | %define LIB_SYS_STREAM_FLAG_closed 00100000b 67 | %define LIB_SYS_STREAM_FLAG_null 01000000b 68 | 69 | %define LIB_SYS_STREAM_out 00000001b 70 | %define LIB_SYS_STREAM_in 00000010b 71 | 72 | %define STD_IPC_SIZE_byte 40 73 | 74 | %define LIB_SYS_IPC_TYPE_ANY 0x00 75 | %define LIB_SYS_IPC_TYPE_MOUSE 0x01 76 | %define LIB_SYS_IPC_TYPE_KEYBOARD 0x02 77 | 78 | struc STD_IPC_STRUCTURE 79 | .ttl resq 1 80 | .source resq 1 81 | .target resq 1 82 | .data resb STD_IPC_SIZE_byte 83 | .SIZE: 84 | endstruc 85 | 86 | struc STD_IPC_STRUCTURE_DEFAULT 87 | .type resb 1 88 | endstruc 89 | 90 | struc STD_IPC_STRUCTURE_KEYBOARD 91 | .type resb 1 92 | .key resw 1 93 | endstruc 94 | 95 | struc STD_IPC_STRUCTURE_MOUSE 96 | .type resb 1 97 | .status resb 1 98 | endstruc 99 | 100 | %define LIB_SYS_device_mouse_status_left_mouse_button 00000001b 101 | %define LIB_SYS_device_mouse_status_right_mouse_button 00000010b 102 | 103 | struc LIB_SYS_STRUCTURE_MOUSE 104 | .x resw 1 105 | .y resw 1 106 | .status resb 1 107 | endstruc 108 | 109 | struc LIB_SYS_STRUCTURE_STORAGE 110 | .address resq 1 111 | .size_byte resq 1 112 | .length resb 1 113 | .name resb 255 114 | endstruc 115 | 116 | %define LIB_SYS_TASK_NAME_length 255 117 | 118 | struc LIB_SYS_STRUCTURE_TASK 119 | .pid resq 1 120 | .pid_parent resq 1 121 | .sleep resq 1 122 | .page resq 1 123 | .flags resw 1 124 | .length resb 1 125 | .name resb LIB_SYS_TASK_NAME_length 126 | .SIZE: 127 | endstruc 128 | %endif -------------------------------------------------------------------------------- /library/vfs.asm: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | ;----------------------------------------------------------------------- 6 | ; structures, definitions 7 | ;----------------------------------------------------------------------- 8 | ; global --------------------------------------------------------------- 9 | %include "library/std.inc" ; not required, but nice to have 10 | ; library -------------------------------------------------------------- 11 | %ifndef LIB_VFS 12 | %include "library/vfs.inc" 13 | %endif 14 | ;======================================================================= 15 | 16 | ; 64 bit code 17 | [bits 64] 18 | 19 | ; we are using Position Independed Code 20 | default rel 21 | 22 | ;------------------------------------------------------------------------------- 23 | ; in: 24 | ; rcx - length of path 25 | ; rsi - path to file 26 | ; rdi - pointer to begining of file data 27 | ; rbp - pointer of file descriptor 28 | lib_vfs_file: 29 | ; preserve original registers 30 | push rcx 31 | push rsi 32 | push rdi 33 | 34 | ; by default file does not exist 35 | mov qword [rbp + KERNEL_STORAGE_STRUCTURE_FILE.id], EMPTY 36 | 37 | .file: 38 | ; file name length 39 | cmp word [rdi + LIB_VFS_STRUCTURE.length], cx 40 | jne .next ; incorrect 41 | 42 | ; check file name 43 | add rdi, LIB_VFS_STRUCTURE.name 44 | call lib_string_compare 45 | 46 | ; names are similar? 47 | jnc .found ; yes 48 | 49 | ; move pointer back to entry 50 | sub rdi, LIB_VFS_STRUCTURE.name 51 | 52 | .next: 53 | ; no more files in VFS? 54 | cmp word [rdi + LIB_VFS_STRUCTURE.length], EMPTY 55 | je .end 56 | 57 | ; move pointer to next file 58 | add rdi, LIB_VFS_base 59 | 60 | ; continue search 61 | jmp .file 62 | 63 | .found: 64 | ; return file specification 65 | 66 | ; move pointer back to entry 67 | sub rdi, LIB_VFS_STRUCTURE.name 68 | 69 | ; size in Bytes 70 | mov rcx, qword [rdi + LIB_VFS_STRUCTURE.size] 71 | mov qword [rbp + KERNEL_STORAGE_STRUCTURE_FILE.size_byte], rcx 72 | 73 | ; and ID 74 | mov qword [rbp + KERNEL_STORAGE_STRUCTURE_FILE.id], rdi 75 | 76 | .end: 77 | ; restore original registers 78 | pop rdi 79 | pop rsi 80 | pop rcx 81 | 82 | ; return from routine 83 | ret 84 | 85 | ;------------------------------------------------------------------------------- 86 | ; in: 87 | ; rsi - pointer to begining of file data 88 | lib_vfs_init: 89 | ; preserve original registers 90 | push rax 91 | push rsi 92 | 93 | ; VFS position inside memory 94 | mov rax, rsi 95 | 96 | .loop: 97 | ; all files parsed? 98 | cmp word [rsi + LIB_VFS_STRUCTURE.length], EMPTY 99 | je .end ; yes 100 | 101 | ; set correct file content offsets, related to package inside memory 102 | add qword [rsi + LIB_VFS_STRUCTURE.offset], rax 103 | 104 | ; next file 105 | add rsi, LIB_VFS_STRUCTURE.SIZE 106 | jmp .loop 107 | 108 | .end: 109 | ; restore original registers 110 | pop rsi 111 | pop rax 112 | 113 | ; return from routine 114 | ret 115 | 116 | ;------------------------------------------------------------------------------- 117 | ; in: 118 | ; rsi - file identificator 119 | ; rdi - file data destination 120 | lib_vfs_read: 121 | ; preserve original registers 122 | push rcx 123 | push rsi 124 | push rdi 125 | 126 | ; file size in Bytes 127 | mov rcx, qword [rsi + LIB_VFS_STRUCTURE.size] 128 | 129 | ; file data position 130 | mov rsi, qword [rsi + LIB_VFS_STRUCTURE.offset] 131 | 132 | ; copy file content 133 | rep movsb 134 | 135 | ; restore original registers 136 | pop rdi 137 | pop rsi 138 | pop rcx 139 | 140 | ; return from routine 141 | ret 142 | -------------------------------------------------------------------------------- /library/vfs.inc: -------------------------------------------------------------------------------- 1 | ;================================================================================= 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;================================================================================= 4 | 5 | %define LIB_VFS 6 | 7 | %define LIB_VFS_align 16 8 | %define LIB_VFS_base 64 9 | %define LIB_VFS_length 4 10 | %define LIB_VFS_magic "#VFS" 11 | %define LIB_VFS_NAME_limit 42 12 | %define LIB_VFS_shift 6 13 | %define LIB_VFS_default 2 14 | 15 | %define LIB_VFS_TYPE_regular_file 00000001b 16 | %define LIB_VFS_TYPE_directory 00000010b 17 | %define LIB_VFS_TYPE_symbolic_link 00000100b 18 | %define LIB_VFS_TYPE_shared_object 00001000b 19 | 20 | %define LIB_VFS_MODE_user_executable 0x0000000000000001 21 | 22 | ; this structure should be divisible by power of 2 23 | struc LIB_VFS_STRUCTURE 24 | .offset resq 1 25 | .size resq 1 26 | .length resw 1 27 | .mode resw 1 28 | .type resb 1 29 | .name resb LIB_VFS_NAME_limit + 1 30 | .SIZE: 31 | endstruc -------------------------------------------------------------------------------- /make: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #================================================================================= 3 | # Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 4 | #================================================================================= 5 | 6 | # coloristics 7 | green=$(tput setaf 2) 8 | default=$(tput sgr0) 9 | 10 | AA="nasm" 11 | A="nasm -p ./library/std.inc" 12 | LD="ld.lld" 13 | ISO="xorriso" 14 | QEMU="qemu-system-x86_64" 15 | LDFLAGS="-nostdlib -zmax-page-size=0x1000 -static -no-dynamic-linker" 16 | 17 | # for clear view 18 | clear 19 | 20 | # external resources initialization 21 | git submodule update --init 22 | 23 | (cd limine && clang limine.c -o limine) 24 | (cd fern-night && ./make ${1} ${2}) 25 | 26 | # check environment software, required! 27 | ENV=true 28 | echo -n "Cyjon environment: " 29 | type -a ${AA} &> /dev/null || (echo -en "\e[38;5;196m${AA}\e[0m" && ENV=false) 30 | type -a ${LD} &> /dev/null || (echo -en "\e[38;5;196m${LD}\e[0m" && ENV=false) 31 | type -a ${ISO} &> /dev/null || (echo -en "\e[38;5;196m${ISO}\e[0m" && ENV=false) 32 | if [ "${ENV}" = false ]; then echo -e "\n[please install missing software]"; exit 1; else echo -e "\e[38;5;2m\xE2\x9C\x94\e[0m"; fi 33 | 34 | # optional 35 | type -a ${QEMU} &> /dev/null || echo -e "Optional \e[38;5;11m${QEMU}\e[0m not installed. ISO file will be generated regardless of that." 36 | 37 | # remove all obsolete files, which could interference 38 | rm -rf build && mkdir -p build/iso 39 | rm -f bx_enh_dbg.ini # just to make clean directory, if you executed bochs.sh 40 | 41 | # build kernel file 42 | ${A} -f elf64 kernel/init.asm -o build/kernel.o || exit 1 43 | ${LD} build/kernel.o -o build/kernel -T tools/kernel.ld ${LDFLAGS} || exit 1; 44 | strip -s build/kernel 45 | 46 | # information 47 | kernel_size=`ls -lh build/kernel | cut -d ' ' -f 5` 48 | echo -e "${green}\xE2\x9C\x94${default}|Kernel|${kernel_size}" | awk -F "|" '{printf "%s %-30s %s\n", $1, $2, $3 }' 49 | 50 | # copy kernel file, external software and limine files onto destined iso folder 51 | cp build/kernel fern-night/build/system.vfs tools/limine.conf limine/limine-bios.sys limine/limine-bios-cd.bin limine/limine-uefi-cd.bin build/iso 52 | 53 | # convert iso directory to iso file 54 | xorriso -as mkisofs -b limine-bios-cd.bin -no-emul-boot -boot-load-size 4 -boot-info-table --efi-boot limine-uefi-cd.bin -efi-boot-part --efi-boot-image --protective-msdos-label build/iso -o build/cyjon.iso > /dev/null 2>&1 55 | 56 | # install bootloader limine inside created 57 | limine/limine bios-install build/cyjon.iso > /dev/null 2>&1 58 | -------------------------------------------------------------------------------- /qemu: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #================================================================================= 3 | # Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 4 | #================================================================================= 5 | 6 | clear 7 | 8 | # default CPUs amount: 2 9 | SMP="${1}" 10 | if [ -z "${SMP}" ]; then SMP="2"; fi 11 | 12 | # default Memory size: 64 MiB 13 | MEM="${2}" 14 | if [ -z "${MEM}" ]; then MEM="64"; fi 15 | 16 | qemu-system-x86_64 \ 17 | --enable-kvm \ 18 | -cpu max \ 19 | -smp ${SMP} \ 20 | -m ${MEM} \ 21 | -cdrom build/cyjon.iso \ 22 | -rtc base=localtime \ 23 | -audio driver=alsa,model=sb16,id=7 \ 24 | -serial stdio \ 25 | # -usb -device usb-mouse,id=mouse \ 26 | # -usb -device usb-kbd,id=keyboard \ 27 | -------------------------------------------------------------------------------- /tools/bochs.rc: -------------------------------------------------------------------------------- 1 | c 2 | -------------------------------------------------------------------------------- /tools/configure.sh: -------------------------------------------------------------------------------- 1 | # my bochs configuration 2 | ./configure --prefix=/opt/bochs --with-x --with-x11 --enable-x86-64 --enable-smp --enable-long-phy-address --enable-configurable-msrs --enable-debugger --enable-debugger-gui --enable-pci --enable-e1000 --enable-repeat-speedups --enable-fpu --enable-alignment-check --enable-avx --enable-evex --enable-usb --enable-usb-ohci --enable-usb-ehci --enable-usb-xhci --enable-sb16 3 | -------------------------------------------------------------------------------- /tools/kernel.ld: -------------------------------------------------------------------------------- 1 | /*=============================================================================== 2 | Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ===============================================================================*/ 4 | 5 | OUTPUT_FORMAT( elf64-x86-64 ) 6 | OUTPUT_ARCH( i386:x86-64 ) 7 | 8 | ENTRY( _entry ) 9 | 10 | PHDRS { 11 | null PT_NULL FLAGS( 0 ); 12 | text PT_LOAD FLAGS( (1 << 0) | (1 << 2) ); 13 | rodata PT_LOAD FLAGS( (1 << 2) ); 14 | data PT_LOAD FLAGS( (1 << 1) | (1 << 2) ); 15 | bss PT_LOAD FLAGS( (1 << 1) | (1 << 2) ); 16 | dynamic PT_DYNAMIC FLAGS( (1 << 1) | (1 << 2) ); 17 | } 18 | 19 | SECTIONS { 20 | . = 0xffffffff80000000; 21 | 22 | .text : ALIGN( CONSTANT( MAXPAGESIZE ) ) { 23 | *(.text .text.*) 24 | } :text 25 | 26 | .rodata : ALIGN( CONSTANT( MAXPAGESIZE ) ) { 27 | *(.rodata .rodata.*) 28 | } :rodata 29 | 30 | .data : ALIGN( CONSTANT( MAXPAGESIZE ) ) { 31 | *(.data .data.*) 32 | } :data 33 | 34 | .data : ALIGN( CONSTANT( MAXPAGESIZE ) ) { 35 | *(.bss .bss.*) 36 | } :bss 37 | } 38 | -------------------------------------------------------------------------------- /tools/limine.conf: -------------------------------------------------------------------------------- 1 | #================================================================================= 2 | # Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | #================================================================================= 4 | 5 | timeout: 0 6 | 7 | /Cyjon 8 | protocol: limine 9 | kernel_path: boot():/kernel 10 | module_path: boot():/system.vfs 11 | cmdline: wm 12 | 13 | comment: Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 14 | -------------------------------------------------------------------------------- /tools/linux.bxrc: -------------------------------------------------------------------------------- 1 | plugin_ctrl: voodoo=true, e1000=true, sb16=true, es1370=true, usb_uhci=true, usb_ohci=true, usb_ehci=true, usb_xhci=true 2 | config_interface: textconfig 3 | display_library: x, options="gui_debug" 4 | memory: guest=MEM, host=MEM 5 | romimage: file="/opt/bochs-dbg/share/bochs/BIOS-bochs-latest", address=0x00000000, options=none 6 | vgaromimage: file="/opt/bochs-dbg/share/bochs/VGABIOS-lgpl-latest" 7 | boot: cdrom 8 | ata0: enabled=true, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 9 | ata0-master: type=cdrom, path="build/cyjon.iso", status=inserted, model="Generic 1234", biosdetect=auto 10 | pci: enabled=1, chipset=i440fx, slot1=pcivga, slot2=e1000, slot3=voodoo, slot4=none, slot5=none 11 | vga: extension=vbe, update_freq=30, realtime=0, ddc=builtin 12 | cpu: count=1:SMP:1, ips=64000000, model=corei7_sandy_bridge_2600k, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0 13 | magic_break: enabled=1 14 | clock: sync=realtime, time0=local, rtc_sync=1 15 | keyboard: type=mf, serial_delay=250, paste_delay=100000, user_shortcut=none 16 | mouse: type=ps2, enabled=false, toggle=ctrl+mbutton 17 | #usb_uhci: enabled=1, port1=keyboard, options1=none, port2=mouse, options2=none 18 | sound: waveoutdrv=alsa, waveout=none, waveindrv=alsa, wavein=none, midioutdrv=alsa, midiout=none 19 | #voodoo: enabled=true, model=voodoo1 20 | com1: enabled=true, mode=file, dev="serial.log" 21 | e1000: enabled=true, mac=00:22:44:66:88:AA, ethmod=vnet 22 | #es1370: enabled=true, wavedev=alsa 23 | sb16: enabled=true, midimode=0, wavemode=1 24 | --------------------------------------------------------------------------------