├── README.md ├── Slidoor └── boot │ ├── bootloader.bin │ └── grub │ └── grub.cfg ├── bochsrc.bxrc ├── boot ├── bootloader.asm └── incapableboot.asm ├── build.sh ├── kernel └── src │ ├── arch │ └── x86 │ │ ├── cpu.c │ │ ├── cpu.h │ │ ├── idt.c │ │ ├── idt.h │ │ ├── ioapic.c │ │ ├── ioapic.h │ │ ├── irq.asm │ │ ├── irq.c │ │ ├── irq.h │ │ ├── isr.asm │ │ ├── isr.c │ │ ├── isr.h │ │ ├── lapic.c │ │ ├── lapic.h │ │ ├── smp.asm │ │ ├── smp.c │ │ └── smp.h │ ├── console │ ├── Font.psf │ ├── Font10x10.psf │ ├── Font16x16.psf │ ├── Font8x8.psf │ ├── console.c │ ├── console.h │ └── fonts.h │ ├── drivers │ ├── acpi │ │ ├── acpi.c │ │ ├── acpi.h │ │ ├── dsdt.c │ │ ├── dsdt.h │ │ ├── fadt.c │ │ ├── fadt.h │ │ ├── interpreter │ │ │ ├── eval.c │ │ │ ├── eval.h │ │ │ ├── namespace.c │ │ │ ├── namespace.h │ │ │ └── opcode.h │ │ ├── madt.c │ │ ├── madt.h │ │ ├── rsdp.c │ │ ├── rsdp.h │ │ ├── rsdt.c │ │ └── rsdt.h │ ├── ata │ │ ├── ata.c │ │ ├── ata.h │ │ ├── atapi.c │ │ ├── atapi.h │ │ ├── dma │ │ │ ├── ata_dma.c │ │ │ ├── ata_dma.h │ │ │ ├── atapi_dma.c │ │ │ └── atapi_dma.h │ │ └── pio │ │ │ ├── ata_pio.c │ │ │ ├── ata_pio.h │ │ │ ├── atapi_pio.c │ │ │ └── atapi_pio.h │ ├── energy │ │ ├── energy.c │ │ └── energy.h │ ├── hpet │ │ ├── hpet.c │ │ └── hpet.h │ ├── kb │ │ ├── kb.c │ │ └── kb.h │ ├── pci │ │ ├── pci.c │ │ └── pci.h │ ├── pcie │ │ ├── pcie.c │ │ └── pcie.h │ ├── pit │ │ ├── pit.c │ │ └── pit.h │ ├── rtc │ │ ├── rtc.c │ │ └── rtc.h │ ├── sleep │ │ ├── sleep.c │ │ └── sleep.h │ └── vesa │ │ ├── vesa.c │ │ └── vesa.h │ ├── grub │ ├── multiboot.c │ └── multiboot.h │ ├── kernel.c │ ├── kernel.h │ ├── memory │ ├── paging.c │ ├── paging.h │ ├── pmm (pep).c │ ├── pmm (pep).h │ ├── pmm.c │ ├── pmm.h │ ├── vmm.c │ └── vmm.h │ ├── setup │ ├── setup.c │ └── setup.h │ └── string │ ├── string.c │ ├── string.h │ └── types.h └── link.ld /README.md: -------------------------------------------------------------------------------- 1 | Slidoor-OS 2 | ------------------------------------------------ 3 | Slidoor OS is a hobbyist operating system made completely from scratch. 4 | it features: 5 | - [x] Basic ACPI Driver 6 | - [x] ATA/ATAPI PIO Driver 7 | - [x] ATA/ATAPI DMA Driver 8 | - [x] HPET Driver && PIT Driver (the latter is for fallback) 9 | - [x] PCI Bus scanning and parsing 10 | - [x] PCIe scanning 11 | - [x] VBE Framebuffer Driver 12 | - [x] Graphical console 13 | - [x] Support for SSEx, AVX, AVX2, AVX512 14 | 15 | TODO: 16 | - [ ] TSC Driver 17 | - [ ] Parsing other ACPI tables (i.e BGRT... sure.), objects and/or methods (i.e _TTS, _PTS, _GTS), etc. --> Implement an aml interpreter* 18 | - [ ] MSI(x) 19 | - [ ] Suspend to ram, to disk, etc. 20 | - [ ] AHCI Driver 21 | - [ ] NVMe Driver 22 | - [ ] USB Driver (OHCI, UHCI, EHCI and XHCI) 23 | - [ ] Actually implement SMP Support 24 | - [ ] Implement a filesystem 25 | - [ ] Implement VFS 26 | - [ ] Fix atapi irq never firing. 27 | - [ ] Implement userspace 28 | - [ ] Implement networking 29 | 30 | - Notes: 31 | - The TODO list is not ordered. 32 | - when using HPET as the main counter, take in count that bochs finds it pretty difficult to keep a good track of time unless you use sync=both in bochs.bxrc's clock, which is painfully slow btw. 33 | 34 | If you wish to contact me add me in discord, my username is "alberinfo_osdev" 35 | 36 | * This by now has my highest priority. Though, seems like a long update, and if done it will be one of the most (if not the most) important update ever done on my os. Also, i wont be porting ACPICA (seems kind of like a mess to me), but instead will try writing an interpreter for myself (while lying an eye on LAI, seems pretty clean) 37 | 38 | **Updates on the AML Interpreter: As of now, the parser has been done in a good portion, with the only remaining things being: 39 | - Packets inside packets, etc 40 | Then, i should start seeing into ways of executing the AML Code. This will also take some time to do, and a lot of planning. 41 | -------------------------------------------------------------------------------- /Slidoor/boot/bootloader.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alberinfo/Slidoor-OS/e37cc96e86b6e4b43ae82ec263b716451ad7f72f/Slidoor/boot/bootloader.bin -------------------------------------------------------------------------------- /Slidoor/boot/grub/grub.cfg: -------------------------------------------------------------------------------- 1 | set default=0 2 | set timeout=-1 3 | 4 | menuentry "Slidoor ( preferred resolution )" { 5 | multiboot2 /boot/bootloader.bin 6 | set gfxpayload=auto 7 | boot 8 | } 9 | 10 | submenu "Slidoor ( other resulution )" { 11 | menuentry "800x600x32" { 12 | multiboot2 /boot/bootloader.bin 13 | set gfxpayload=800x600x32 14 | boot 15 | } 16 | 17 | menuentry "1024x768x32" { 18 | multiboot2 /boot/bootloader.bin 19 | set gfxpayload=1024x768x32 20 | boot 21 | } 22 | 23 | menuentry "1280x720x32" { 24 | multiboot2 /boot/bootloader.bin 25 | set gfxpayload=1280x720x32 26 | boot 27 | } 28 | 29 | menuentry "1280x1024x32" { 30 | multiboot2 /boot/bootloader.bin 31 | set gfxpayload=1280x1024x32 32 | boot 33 | } 34 | 35 | menuentry "custom" { 36 | multiboot2 /boot/bootloader.bin 37 | vbeinfo 38 | echo "" 39 | echo -n "Screen width: " 40 | read w 41 | echo "" #Would simulate a \n 42 | echo -n "Screen height: " 43 | read h 44 | echo "" #Would simulate a \n 45 | echo -n "Screen bpp: " 46 | read b 47 | set gfxpayload=${w}x${h}x${b} 48 | boot 49 | } 50 | 51 | } -------------------------------------------------------------------------------- /bochsrc.bxrc: -------------------------------------------------------------------------------- 1 | # configuration file generated by Bochs 2 | plugin_ctrl: unmapped=1, biosdev=1, speaker=1, extfpuirq=1, parallel=1, serial=1 3 | config_interface: textconfig 4 | display_library: x 5 | memory: host=512, guest=512 6 | romimage: file="/usr/share/bochs/BIOS-bochs-latest" 7 | vgaromimage: file="/usr/share/bochs/VGABIOS-lgpl-latest" 8 | boot: cdrom 9 | floppy_bootsig_check: disabled=0 10 | # no floppya 11 | # no floppyb 12 | ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 13 | ata0-master: type=cdrom, path="Slidoor.iso", status=inserted, biosdetect=auto, model="Generic 1234" 14 | ata0-slave: type=disk, path=disk.img, mode=flat 15 | ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15 16 | #ata1-master: type=disk, path=disk2.img, mode=flat 17 | #ata1: enabled=0 18 | ata2: enabled=0 19 | ata3: enabled=0 20 | pci: enabled=1, chipset=i440fx 21 | vga: extension=vbe, update_freq=60 22 | cpuid: apic=x2apic, simd=avx512, xsave=1 23 | cpu: count=2, ips=5000000, model=bx_generic, reset_on_triple_fault=0, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0 24 | print_timestamps: enabled=0 25 | debugger_log: - 26 | magic_break: enabled=1 27 | port_e9_hack: enabled=0 28 | private_colormap: enabled=0 29 | clock: sync=none, time0=local, rtc_sync=1 30 | # no cmosimage 31 | # no loader 32 | log: - 33 | logprefix: %t%e%d 34 | panic: action=ask 35 | error: action=report 36 | info: action=report 37 | debug: action=ignore, pci_ide=ignore, harddrv=ignore 38 | debug_symbols: file=kern.sym 39 | keyboard: type=mf, serial_delay=200, paste_delay=100000, keymap= 40 | mouse: enabled=0, type=ps2, toggle=ctrl+mbutton 41 | parport1: enabled=1, file="" 42 | parport2: enabled=0 43 | com1: enabled=1, mode=null, dev="" 44 | com2: enabled=0 45 | com3: enabled=0 46 | com4: enabled=0 47 | -------------------------------------------------------------------------------- /boot/bootloader.asm: -------------------------------------------------------------------------------- 1 | [BITS 32] 2 | 3 | %define STACK_SIZE 0x20000 ;This MAY be not enough. Or maybe it is. who knows (check &/ change in case of those strange unreasonable errors) 4 | 5 | HIGHER_VMA equ 0xFFFF800000000000 6 | high_PML4_idx equ (HIGHER_VMA >> 39) & 0x1FF 7 | high_PDPT_idx equ (HIGHER_VMA >> 30) & 0x1FF 8 | 9 | section .mboot 10 | mboot_header_start: 11 | dd 0xe85250d6 12 | dd 0 13 | dd mboot_header_end - mboot_header_start 14 | dd 0x100000000 - (0xe85250d6 + 0 +(mboot_header_end - mboot_header_start)) 15 | 16 | align 8 17 | mboot_inforeq_start: 18 | dw 1 19 | dw 0 20 | dd mboot_inforeq_end - mboot_inforeq_start 21 | dd 2 ;Boot loader name 22 | dd 6 ;Memory map 23 | dd 7 ;Vbe info 24 | dd 8 ;Framebuffer info 25 | dd 14 ;Acpi 1.0 Rsdp info 26 | dd 15 ;Acpi 2.0+ Rsdp info 27 | mboot_inforeq_end: 28 | 29 | align 8 30 | mboot_framebuffer_start: 31 | dw 5 32 | dw 1 33 | dd mboot_framebuffer_end - mboot_framebuffer_start 34 | dd 800 35 | dd 600 36 | dd 32 37 | mboot_framebuffer_end: ; in this tag we set a video mode, otherwise the gfxpayload will not work in grub.cfg (note that 800x600 wont be the used mode unless said so by the user) 38 | 39 | align 8 40 | mboot_end_start: 41 | dw 0 42 | dw 0 43 | dd mboot_end_end - mboot_end_start 44 | mboot_end_end: 45 | 46 | mboot_header_end: 47 | 48 | extern no_cpuid 49 | extern no_lmode 50 | extern no_higher_half 51 | 52 | [bits 32] 53 | section .uarch 54 | global _start 55 | _start: 56 | push ebx 57 | call check_cpuid 58 | call check_lmode 59 | call check_vbits 60 | xor ecx, ecx 61 | call map_PD 62 | call setup_paging 63 | call enable_paging 64 | pop ebx 65 | lgdt [lowgdt64.pointer] 66 | jmp lowgdt64.code:trampoline 67 | 68 | check_cpuid: 69 | pushfd 70 | pop eax 71 | mov ecx, eax 72 | xor eax, 1 << 21 73 | push eax 74 | popfd 75 | pushfd 76 | pop eax 77 | push ecx 78 | popfd 79 | cmp eax, ecx 80 | je no_cpuid 81 | ret 82 | 83 | check_lmode: 84 | mov eax, 0x80000000 85 | cpuid 86 | cmp eax, 0x80000001 87 | jb no_lmode 88 | mov eax, 0x80000001 89 | cpuid 90 | test edx, 1 << 29 91 | jz no_lmode 92 | ret 93 | 94 | check_vbits: ;See if the amount of virtual bits is enough 95 | mov eax, 0x80000008 96 | cpuid 97 | shr eax, 8 98 | cmp eax, 0x30 99 | jl no_higher_half 100 | ret 101 | 102 | map_PD: 103 | mov eax, 0x200000 104 | mul ecx 105 | or eax, 0b10000011 106 | mov [PD + ecx * 8], eax 107 | inc ecx 108 | cmp ecx, 512 109 | jne map_PD 110 | ret 111 | 112 | setup_paging: 113 | mov eax, PD 114 | or eax, 0b11 115 | mov [PDPT], eax 116 | mov [PDPT+(high_PDPT_idx*8)], eax 117 | mov eax, PDPT 118 | or eax, 0b11 119 | mov [PML4], eax 120 | mov [PML4+(high_PML4_idx*8)], eax 121 | ret 122 | 123 | enable_paging: 124 | mov eax, PML4 125 | mov cr3, eax 126 | mov eax, cr4 127 | or eax, 1 << 5 128 | mov cr4, eax 129 | mov ecx, 0xC0000080 130 | rdmsr 131 | or eax, 1 << 8 132 | wrmsr 133 | mov eax, cr0 134 | or eax, 1 << 31 135 | mov cr0, eax 136 | ret 137 | 138 | [BITS 64] 139 | 140 | trampoline: ; we fix leave long mode, at the same time we dont get relocation error ;) 141 | mov ax, lowgdt64.data 142 | mov ss, ax 143 | mov ds, ax 144 | mov es, ax 145 | mov fs, ax 146 | mov gs, ax 147 | mov rax, qword higher_half 148 | jmp rax 149 | 150 | extern kmain 151 | 152 | section .text 153 | higher_half: 154 | mov rbp, qword (stack + 0xFFFF800000000000) 155 | mov rsp, qword (stack_end + 0xFFFF800000000000) 156 | mov rax, qword gdt64.pointer 157 | lgdt [rax] 158 | ;remove lower half 159 | xor rax, rax 160 | mov [PML4], rax 161 | invlpg [0] 162 | push rax 163 | push rbx 164 | push rcx 165 | push rdx 166 | call AVX512Enable 167 | pop rdx 168 | pop rcx 169 | pop rbx 170 | pop rax 171 | call kmain 172 | cli 173 | hlt 174 | 175 | AVX512Enable: 176 | mov rax, cr4 177 | or rax, 1 << 9 ;enable fxsave fxstor 178 | or rax, 1 << 10 ;enable unmasked SIMD floating point exceptions 179 | mov cr4, rax 180 | 181 | mov rax, 7 182 | xor rcx, rcx 183 | xor rbx, rbx 184 | cpuid 185 | and rbx, 1 << 16 186 | cmp rbx, 1 << 16 187 | je .enable 188 | jne AVXEnable 189 | ret 190 | 191 | .enable: 192 | mov rax, cr4 193 | or rax, 1 << 18 194 | mov cr4, rax 195 | 196 | xor rcx, rcx 197 | xor rax, rax 198 | xgetbv 199 | or rax, 7 200 | or rax, 7 << 5 201 | xsetbv 202 | ret 203 | 204 | AVXEnable: 205 | mov rax, 7 206 | xor rcx, rcx 207 | xor rbx, rbx 208 | cpuid 209 | and rbx, 1 << 5 210 | cmp rbx, 1 << 5 211 | je .enable 212 | 213 | mov rax, 1 214 | xor rcx, rcx 215 | cpuid 216 | and rcx, 1 << 28 217 | cmp rcx, 1 << 28 218 | je .enable 219 | jne SSE_Enable 220 | ret 221 | 222 | .enable: 223 | mov rax, cr4 224 | or eax, 0x40000 225 | or eax, 1 << 9 ;enable fxsave fxstor 226 | or eax, 1 << 10 ;enable unmasked SIMD floating point exceptions 227 | mov cr4, rax 228 | 229 | xor rcx, rcx 230 | xor rax, rax 231 | xgetbv 232 | or rax, 7 233 | xsetbv 234 | ret 235 | 236 | SSE_Enable: 237 | mov rax, cr0 238 | and rax, ~(1 << 2) ; clear Emulation bit 239 | or rax, 1 << 1 ;enable Monitor co-processor 240 | mov cr0, rax 241 | ret 242 | 243 | section .pregdt 244 | lowgdt64: ;preliminar GDT for the lower half, linked at 1MiB 245 | dq 0 246 | .code: equ $ - lowgdt64 247 | dw 0xFFFF 248 | dw 0 249 | dd 0x00209A00 250 | .data: equ $ - lowgdt64 251 | dw 0xFFFF 252 | dw 0 253 | dd 0x00009200 254 | .pointer: 255 | dw $ - lowgdt64 - 1 256 | dq lowgdt64 257 | 258 | section .rodata 259 | gdt64: ;GDT for the higher half, linked at HIGHER_VMA 260 | dq 0 261 | .code: equ $ - gdt64 262 | dw 0xFFFF 263 | dw 0 264 | dd 0x00209A00 265 | .data: equ $ - gdt64 266 | dw 0xFFFF 267 | dw 0 268 | dd 0x00009200 269 | .pointer: 270 | dw $ - gdt64 - 1 271 | dq gdt64 272 | 273 | section .prebss 274 | align 4096 275 | PML4 : resb 4096 ; AT 0x103000 276 | PDPT : resb 4096 ; AT 0x104000 277 | PD : resb 4096 ; AT 0x105000 278 | 279 | stack: 280 | resb STACK_SIZE 281 | stack_end: 282 | -------------------------------------------------------------------------------- /boot/incapableboot.asm: -------------------------------------------------------------------------------- 1 | [bits 32] 2 | 3 | ;extern VGAMode 4 | 5 | section .uarch 6 | global no_lmode 7 | no_lmode: 8 | mov dword [0xB8000], 0x0F680F54 9 | mov dword [0xB8004], 0x0F730F69 10 | mov dword [0xB8008], 0x0F700F20 11 | mov dword [0xB800C], 0x0F6F0F72 12 | mov dword [0xB8010], 0x0F650F63 13 | mov dword [0xB8014], 0x0F730F73 14 | mov dword [0xB8018], 0x0F720F6F 15 | mov dword [0xB801C], 0x0F640F20 16 | mov dword [0xB8020], 0x0F650F6F 17 | mov dword [0xB8024], 0x0F200F73 18 | mov dword [0xB8028], 0x0F6F0F6E 19 | mov dword [0xB802C], 0x0F200F74 20 | mov dword [0xB8030], 0x0F750F73 21 | mov dword [0xB8034], 0x0F700F70 22 | mov dword [0xB8038], 0x0F720F6F 23 | mov dword [0xB803C], 0x0F200F74 24 | mov dword [0xB8040], 0x0F680F74 25 | mov dword [0xB8044], 0x0F200F65 26 | mov dword [0xB8048], 0x0F380F78 27 | mov dword [0xB804C], 0x0F5F0F36 28 | mov dword [0xB8050], 0x0F340F36 29 | mov dword [0xB8054], 0x0F610F20 30 | mov dword [0xB8058], 0x0F630F72 31 | mov dword [0xB805C], 0x0F690F68 32 | mov dword [0xB8060], 0x0F650F74 33 | mov dword [0xB8064], 0x0F740F63 34 | mov dword [0xB8068], 0x0F720F75 35 | mov dword [0xB806C], 0x0F2E0F65 36 | mov dword [0xB8070], 0x0F540F20 37 | mov dword [0xB8074], 0x0F750F68 38 | mov dword [0xB8078], 0x0F2C0F73 39 | mov dword [0xB807C], 0x0F690F20 40 | mov dword [0xB8080], 0x0F200F74 41 | mov dword [0xB8084], 0x0F610F63 42 | mov dword [0xB8088], 0x0F270F6E 43 | mov dword [0xB808C], 0x0F200F74 44 | mov dword [0xB8090], 0x0F6F0F62 45 | mov dword [0xB8094], 0x0F740F6F 46 | mov dword [0xB8098], 0x0F770F20 47 | mov dword [0xB809C], 0x0F740F69 48 | mov dword [0xB80A0], 0x0F200F68 49 | mov dword [0xB80A4], 0x0F680F74 50 | mov dword [0xB80A8], 0x0F730F69 51 | mov dword [0xB80AC], 0x0F4F0F20 52 | mov dword [0xB80B0], 0x0F2E0F53 53 | mov dword [0xB80B4], 0x0F530F20 54 | mov dword [0xB80B8], 0x0F730F79 55 | mov dword [0xB80BC], 0x0F650F74 56 | mov dword [0xB80C0], 0x0F200F6D 57 | mov dword [0xB80C4], 0x0F610F48 58 | mov dword [0xB80C8], 0x0F740F6C 59 | mov dword [0xB80CC], 0x0F640F65 60 | mov word [0xB80D0], 0x0F2E 61 | cli 62 | hlt 63 | 64 | global no_cpuid 65 | no_cpuid: 66 | cli 67 | hlt 68 | mov dword [0xB8000], 0x0F546869 69 | mov dword [0xB8004], 0x0F732070 70 | mov dword [0xB8008], 0x0F726f63 71 | mov dword [0xB800C], 0x0F657373 72 | mov dword [0xB8010], 0x0F6f7220 73 | mov dword [0xB8014], 0x0F646f65 74 | mov dword [0xB8018], 0x0F73206e 75 | mov dword [0xB801C], 0x0F6f7420 76 | mov dword [0xB8020], 0x0F737570 77 | mov dword [0xB8024], 0x0F706f72 78 | mov dword [0xB8028], 0x0F742063 79 | mov dword [0xB802C], 0x0F707569 80 | mov dword [0xB8030], 0x0F642e20 81 | mov dword [0xB8034], 0x0F546875 82 | mov dword [0xB8038], 0x0F732c20 83 | mov dword [0xB803C], 0x0F697420 84 | mov dword [0xB8040], 0x0F63616e 85 | mov dword [0xB8044], 0x0F277420 86 | mov dword [0xB8048], 0x0F626f6f 87 | mov dword [0xB804C], 0x0F742077 88 | mov dword [0xB8050], 0x0F697468 89 | mov dword [0xB8054], 0x0F207468 90 | mov dword [0xB8058], 0x0F697320 91 | mov dword [0xB805C], 0x0F4f532e 92 | mov dword [0xB8060], 0x0F205379 93 | mov dword [0xB8064], 0x0F737465 94 | mov dword [0xB8068], 0x0F6d2048 95 | mov dword [0xB806C], 0x0F616c74 96 | mov dword [0xB8070], 0x0F65642e 97 | cli 98 | hlt 99 | 100 | global no_higher_half 101 | no_higher_half: 102 | mov dword [0xB8000], 0x0F680F54 103 | mov dword [0xB8004], 0x0F730F69 104 | mov dword [0xB8008], 0x0F700F20 105 | mov dword [0xB800C], 0x0F6F0F72 106 | mov dword [0xB8010], 0x0F650F63 107 | mov dword [0xB8014], 0x0F730F73 108 | mov dword [0xB8018], 0x0F720F6F 109 | mov dword [0xB801C], 0x0F640F20 110 | mov dword [0xB8020], 0x0F650F6F 111 | mov dword [0xB8024], 0x0F200F73 112 | mov dword [0xB8028], 0x0F6F0F6E 113 | mov dword [0xB802C], 0x0F200F74 114 | mov dword [0xB8030], 0x0F610F68 115 | mov dword [0xB8034], 0x0F650F76 116 | mov dword [0xB8038], 0x0F650F20 117 | mov dword [0xB803C], 0x0F6F0F6E 118 | mov dword [0xB8040], 0x0F670F75 119 | mov dword [0xB8044], 0x0F200F68 120 | mov dword [0xB8048], 0x0F690F76 121 | mov dword [0xB804C], 0x0F740F72 122 | mov dword [0xB8050], 0x0F610F75 123 | mov dword [0xB8054], 0x0F200F6C 124 | mov dword [0xB8058], 0x0F640F61 125 | mov dword [0xB805C], 0x0F720F64 126 | mov dword [0xB8060], 0x0F730F65 127 | mov dword [0xB8064], 0x0F200F73 128 | mov dword [0xB8068], 0x0F700F73 129 | mov dword [0xB806C], 0x0F630F61 130 | mov dword [0xB8070], 0x0F2E0F65 131 | mov dword [0xB8074], 0x0F540F20 132 | mov dword [0xB8078], 0x0F750F68 133 | mov dword [0xB807C], 0x0F2C0F73 134 | mov dword [0xB8080], 0x0F740F20 135 | mov dword [0xB8084], 0x0F650F68 136 | mov dword [0xB8088], 0x0F4F0F20 137 | mov dword [0xB808C], 0x0F200F53 138 | mov dword [0xB8090], 0x0F610F63 139 | mov dword [0xB8094], 0x0F740F6E 140 | mov dword [0xB8098], 0x0F6A0F20 141 | mov dword [0xB809C], 0x0F6D0F75 142 | mov dword [0xB80A0], 0x0F200F70 143 | mov dword [0xB80A4], 0x0F6F0F74 144 | mov dword [0xB80A8], 0x0F680F20 145 | mov dword [0xB80AC], 0x0F670F69 146 | mov dword [0xB80B0], 0x0F650F68 147 | mov dword [0xB80B4], 0x0F200F72 148 | mov dword [0xB80B8], 0x0F610F68 149 | mov dword [0xB80BC], 0x0F660F6C 150 | mov dword [0xB80C0], 0x0F200F2E 151 | mov dword [0xB80C4], 0x0F790F53 152 | mov dword [0xB80C8], 0x0F740F73 153 | mov dword [0xB80CC], 0x0F6D0F65 154 | mov dword [0xB80D0], 0x0F480F20 155 | mov dword [0xB80D4], 0x0F6C0F61 156 | mov dword [0xB80D8], 0x0F650F74 157 | mov dword [0xB80DC], 0x0F2E0F64 158 | cli 159 | hlt 160 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | GCC="../Cross-compiler/gcc/x86_64-elf-gcc-8.3.0" 4 | LD="../Cross-compiler/ld/bin/ld" 5 | WINIMG="../OSInWin" 6 | 7 | # clean previous build files 8 | rm -f kernel/obin/*.o 9 | rm -f kernel/obin/bootloader.bin 10 | rm -f Slidoor/boot/bootloader.bin 11 | 12 | if [ "clean" = "$1" ]; then 13 | exit 14 | fi; 15 | 16 | # compile 17 | nasm -f elf64 -w -all boot/bootloader.asm -o kernel/obin/bootloader.o 18 | nasm -f elf64 -w -all boot/incapableboot.asm -o kernel/obin/incapableboot.o 19 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -c kernel/src/kernel.c -o kernel/obin/kc.o -w -g #nostdlib? 20 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/grub/multiboot.c -o kernel/obin/multiboot.o -w -g 21 | 22 | nasm -f elf64 -w -all kernel/src/arch/x86/isr.asm -o kernel/obin/israsm.o 23 | nasm -f elf64 -w -all kernel/src/arch/x86/irq.asm -o kernel/obin/irqasm.o 24 | nasm -f elf64 -w -all kernel/src/arch/x86/smp.asm -o kernel/obin/smpasm.o 25 | #"$GCC" -m32 -S multiboot.c -o multibooterr.s -w 26 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/setup/setup.c -o kernel/obin/setup.o -w 27 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -c kernel/src/arch/x86/cpu.c -o kernel/obin/cpu.o -w 28 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/drivers/vesa/vesa.c -o kernel/obin/vesa.o -w 29 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/console/console.c -o kernel/obin/console.o -w 30 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/drivers/acpi/acpi.c -o kernel/obin/acpi.o -w 31 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/drivers/acpi/madt.c -o kernel/obin/madt.o -w 32 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/drivers/acpi/fadt.c -o kernel/obin/fadt.o -w 33 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/drivers/acpi/dsdt.c -o kernel/obin/dsdt.o -w 34 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/drivers/acpi/rsdt.c -o kernel/obin/rsdt.o -w 35 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/drivers/acpi/rsdp.c -o kernel/obin/rsdp.o -w 36 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/drivers/acpi/interpreter/namespace.c -o kernel/obin/AcpiNamespace.o -w 37 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/drivers/acpi/interpreter/eval.c -o kernel/obin/AcpiEval.o -w 38 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/arch/x86/lapic.c -o kernel/obin/lapic.o -w 39 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/arch/x86/ioapic.c -o kernel/obin/ioapic.o -w 40 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/drivers/energy/energy.c -o kernel/obin/energy.o -w 41 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -c kernel/src/string/string.c -o kernel/obin/string.o -w 42 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/arch/x86/smp.c -o kernel/obin/smp.o -w 43 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/drivers/pci/pci.c -o kernel/obin/pci.o -w 44 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/drivers/pcie/pcie.c -o kernel/obin/pcie.o -w 45 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/drivers/kb/kb.c -o kernel/obin/kb.o -w 46 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/arch/x86/idt.c -o kernel/obin/idt.o -w 47 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/arch/x86/isr.c -o kernel/obin/isr.o -w 48 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/arch/x86/irq.c -o kernel/obin/irq.o -w 49 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/memory/paging.c -o kernel/obin/paging.o -w 50 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/memory/pmm.c -o kernel/obin/pmm.o -w 51 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/drivers/rtc/rtc.c -o kernel/obin/rtc.o -w 52 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/drivers/sleep/sleep.c -o kernel/obin/sleep.o -w 53 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/drivers/pit/pit.c -o kernel/obin/pit.o -w 54 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/drivers/hpet/hpet.c -o kernel/obin/hpet.o -w 55 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/drivers/ata/ata.c -o kernel/obin/ata.o -w 56 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/drivers/ata/atapi.c -o kernel/obin/atapi.o -w 57 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/drivers/ata/pio/ata_pio.c -o kernel/obin/ata_pio.o -w 58 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/drivers/ata/pio/atapi_pio.c -o kernel/obin/atapi_pio.o -w 59 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/drivers/ata/dma/ata_dma.c -o kernel/obin/ata_dma.o -w 60 | "$GCC" -m64 -fno-stack-protector -mno-red-zone -msse2 -ftree-vectorize -mcmodel=large -I. -O3 -c kernel/src/drivers/ata/dma/atapi_dma.c -o kernel/obin/atapi_dma.o -w 61 | 62 | cd kernel/src/console/ 63 | 64 | objcopy -O elf64-x86-64 -B i386 -I binary "Font.psf" ../../obin/font.o 65 | 66 | 67 | # link 68 | cd ../../obin/ 69 | 70 | "../../$LD" -N --output=bootloader.bin --script=../../link.ld bootloader.o incapableboot.o kc.o multiboot.o setup.o vesa.o console.o string.o smpasm.o smp.o idt.o israsm.o isr.o irqasm.o irq.o kb.o acpi.o AcpiNamespace.o AcpiEval.o madt.o fadt.o dsdt.o rsdt.o rsdp.o lapic.o ioapic.o energy.o cpu.o pci.o pcie.o rtc.o paging.o pmm.o sleep.o pit.o hpet.o ata.o atapi.o ata_pio.o atapi_pio.o ata_dma.o atapi_dma.o font.o 71 | 72 | cp bootloader.bin ../../Slidoor/boot/ 73 | cd ../../ 74 | 75 | # build iso image 76 | grub-mkrescue -o Slidoor.iso Slidoor/ 77 | 78 | cp Slidoor.iso "$WINIMG" 79 | 80 | ./objdump.sh 81 | #./"iso dump.sh" 82 | 83 | # run 84 | read -p "Please, choose your emulator. For Bochs, press 0. For Qemu, press 1. " EMULATOR 85 | if [ "$EMULATOR" = 0 ]; then 86 | rm *.img.lock 87 | bochs -q -f bochsrc.bxrc 88 | elif [ "$EMULATOR" = 1 ]; then 89 | qemu-system-x86_64 -accel tcg -cpu SandyBridge -boot d -cdrom Slidoor.iso -hda disk.img -debugcon stdio -smp 4 -m 32M #-gdb tcp::1234 & gdb -w kernel/obin/bootloader.bin \ 90 | #-ex 'target remote localhost:1234' \ 91 | #-ex 'c' 92 | else 93 | read -n 1 -s -r -p "Option $EMULATOR is not in the emulator list. Press any key to continue." 94 | echo 95 | exit 1 96 | fi 97 | 98 | #./"disk dump.sh" 99 | 100 | rm -f Slidoor.iso 101 | rm -f *.img.lock 102 | rm -f kern.sym 103 | rm -f disk.txt 104 | 105 | cd kernel/obin/ 106 | rm *.o 107 | rm *.bin 108 | cd ../../ 109 | -------------------------------------------------------------------------------- /kernel/src/arch/x86/cpu.c: -------------------------------------------------------------------------------- 1 | #include "cpu.h" 2 | 3 | char *Intel[96] = { 4 | "Brand ID Not Supported-", 5 | "Intel(R) Celeron(R) processor", 6 | "Intel(R) Pentium(R) III processor", 7 | "Intel(R) Pentium(R) III Xeon(R) processor", 8 | "Intel(R) Pentium(R) III processor", 9 | "Reserved", 10 | "Mobile Intel(R) Pentium(R) III processor-M", 11 | "Mobile Intel(R) Celeron(R) processor", 12 | "Intel(R) Pentium(R) 4 processor", 13 | "Intel(R) Pentium(R) 4 processor", 14 | "Intel(R) Celeron(R) processor", 15 | "Intel(R) Xeon(R) Processor", 16 | "Intel(R) Xeon(R) processor MP", 17 | "Reserved", 18 | "Mobile Intel(R) Pentium(R) 4 processor-M", 19 | "Mobile Intel(R) Pentium(R) Celeron(R) processor", 20 | "Reserved", 21 | "Mobile Genuine Intel(R) processor", 22 | "Intel(R) Celeron(R) M processor", 23 | "Mobile Intel(R) Celeron(R) processor", 24 | "Intel(R) Celeron(R) processor", 25 | "Mobile Geniune Intel(R) processor", 26 | "Intel(R) Pentium(R) M processor", 27 | "Mobile Intel(R) Celeron(R) processor" 28 | }; 29 | 30 | /* This table is for those brand strings that have two values depending on the processor signature. It should have the same number of entries as the above table. */ 31 | char *Intel_Other[96] = { 32 | "Reserved", 33 | "Reserved", 34 | "Reserved", 35 | "Intel(R) Celeron(R) processor", 36 | "Reserved", 37 | "Reserved", 38 | "Reserved", 39 | "Reserved", 40 | "Reserved", 41 | "Reserved", 42 | "Reserved", 43 | "Intel(R) Xeon(R) processor MP", 44 | "Reserved", 45 | "Reserved", 46 | "Intel(R) Xeon(R) processor", 47 | "Reserved", 48 | "Reserved", 49 | "Reserved", 50 | "Reserved", 51 | "Reserved", 52 | "Reserved", 53 | "Reserved", 54 | "Reserved", 55 | "Reserved" 56 | }; 57 | 58 | void CPUDisableInts(void) 59 | { 60 | asm volatile("cli"); 61 | } 62 | 63 | void CPUEnableInts(void) 64 | { 65 | asm volatile("sti"); 66 | } 67 | 68 | uint8 inportb(uint16 _port) 69 | { 70 | uint8 rv; 71 | asm volatile("inb %1, %0" : "=a" (rv) : "dN" (_port)); 72 | return rv; 73 | } 74 | 75 | void outportb(uint16 _port, uint8 _data) 76 | { 77 | asm volatile("outb %1, %0" : : "dN" (_port), "a" (_data)); 78 | } 79 | 80 | uint16 inportw(uint16 _port) 81 | { 82 | uint16 rv; 83 | asm volatile("inw %1, %0" : "=a"(rv) : "dN" (_port)); 84 | return rv; 85 | } 86 | 87 | void outportw(uint16 _port, uint16 _data) 88 | { 89 | asm volatile("outw %1, %0" : : "dN" (_port), "a" (_data)); 90 | } 91 | 92 | uint32 inportl(uint16 _port) 93 | { 94 | uint32 rv; 95 | asm volatile("inl %1, %0" : "=a"(rv) : "dN" (_port)); 96 | return rv; 97 | } 98 | 99 | void outportl(uint16 _port, uint32 _data) 100 | { 101 | asm volatile("outl %1, %0" : : "dN" (_port), "a" (_data)); 102 | } 103 | 104 | void rdmsr(uint32 msr, uint32 *low, uint32 *high) 105 | { 106 | asm volatile("rdmsr" : "=a" (*low), "=d" (*high) : "c" (msr)); 107 | } 108 | 109 | void wrmsr(uint32 msr, uint32 low, uint32 high) 110 | { 111 | asm volatile("wrmsr" : : "a" (low), "d" (high), "c" (msr)); 112 | } 113 | 114 | 115 | string cpuname2str(uint32 eax, uint32 ebx, uint32 ecx, uint32 edx) { 116 | string str = kmalloc(17); 117 | for(uint8 j = 0; j < 4; j++) { 118 | str[j] = eax >> (8 * j); 119 | str[j + 4] = ebx >> (8 * j); 120 | str[j + 8] = ecx >> (8 * j); 121 | str[j + 12] = edx >> (8 * j); 122 | } 123 | str[16] = '\0'; 124 | return str; 125 | } 126 | 127 | void CpuIntel() { 128 | cpu_info.brand = "Intel"; 129 | uint32 eax, ebx, ecx, edx, max_eax, signature, unused; 130 | volatile int model, family, type, brand, stepping, reserved; 131 | int extended_family = -1; 132 | cpuid(1, eax, ebx, unused, unused); 133 | model = (eax >> 4) & 0xf; 134 | family = (eax >> 8) & 0xf; 135 | type = (eax >> 12) & 0x3; 136 | brand = ebx & 0xff; 137 | stepping = eax & 0xf; 138 | reserved = eax >> 14; 139 | signature = eax; 140 | switch(type) { 141 | case 0: 142 | cpu_info.type = "Original OEM"; 143 | break; 144 | case 1: 145 | cpu_info.type = "Overdrive"; 146 | break; 147 | case 2: 148 | cpu_info.type = "Dual-capable"; 149 | break; 150 | case 3: 151 | cpu_info.type = "Reserved"; 152 | break; 153 | } 154 | switch(family) { 155 | case 3: 156 | cpu_info.family = "i386"; 157 | break; 158 | case 4: 159 | cpu_info.family = "i486"; 160 | break; 161 | case 5: 162 | cpu_info.family = "Pentium"; 163 | break; 164 | case 6: 165 | cpu_info.family = "Pentium Pro"; 166 | break; 167 | case 15: 168 | cpu_info.family = "Pentium 4"; 169 | break; 170 | } 171 | if(family == 15) { 172 | extended_family = (eax >> 20) & 0xff; 173 | cpu_info.extended_family = extended_family; 174 | } else { 175 | cpu_info.extended_family = "Unknown"; 176 | } 177 | switch(family) { 178 | case 3: 179 | break; 180 | case 4: 181 | switch(model) { 182 | case 0: 183 | case 1: 184 | cpu_info.model = "DX"; 185 | break; 186 | case 2: 187 | cpu_info.model = "SX"; 188 | break; 189 | case 3: 190 | cpu_info.model = "487/DX2"; 191 | break; 192 | case 4: 193 | cpu_info.model = "SL"; 194 | break; 195 | case 5: 196 | cpu_info.model = "SX2"; 197 | break; 198 | case 7: 199 | cpu_info.model = "Write-back enhanced DX2"; 200 | break; 201 | case 8: 202 | cpu_info.model = "DX4"; 203 | break; 204 | } 205 | break; 206 | case 5: 207 | switch(model) { 208 | case 1: 209 | cpu_info.model = "60/66"; 210 | break; 211 | case 2: 212 | cpu_info.model = "75/200"; 213 | break; 214 | case 3: 215 | cpu_info.model = "for 486 system"; 216 | break; 217 | case 4: 218 | cpu_info.model = "MMX"; 219 | break; 220 | } 221 | break; 222 | case 6: 223 | switch(model) { 224 | case 1: 225 | cpu_info.model = "Pentium Pro"; 226 | break; 227 | case 3: 228 | cpu_info.model = "Pentium II Model 3"; 229 | break; 230 | case 5: 231 | cpu_info.model = "Pentium II Model 5/Xeon/Celeron"; 232 | break; 233 | case 6: 234 | cpu_info.model = "Celeron"; 235 | break; 236 | case 7: 237 | cpu_info.model = "Pentium III/Pentium III Xeon - external L2 cache"; 238 | break; 239 | case 8: 240 | cpu_info.model = "Pentium III/Pentium III Xeon - internal L2 cache"; 241 | break; 242 | } 243 | break; 244 | case 15: 245 | break; 246 | } 247 | cpuid(0x80000000, max_eax, unused, unused, unused); 248 | /* Quok said: If the max extended eax value is high enough to support the processor brand string 249 | (values 0x80000002 to 0do_intelx80000004), then we'll use that information to return the brand information. 250 | Otherwise, we'll refer back to the brand tables above for backwards compatibility with older processors. 251 | According to the Sept. 2006 Intel Arch Software Developer's Guide, if extended eax values are supported, 252 | then all 3 values for the processor brand string are supported, but we'll test just to make sure and be safe. */ 253 | if(brand > 0) { 254 | if(brand < 0x18) { 255 | if(signature == 0x000006B1 || signature == 0x00000F13) { 256 | cpu_info.name = Intel_Other[brand]; 257 | } else { 258 | cpu_info.name = Intel[brand]; 259 | } 260 | } else { 261 | cpu_info.name = "Reserved"; 262 | } 263 | } else { 264 | cpu_info.name = ""; 265 | for(uint32 j = 0x80000002; j <= 0x80000004; j++) { 266 | cpuid(j, eax, ebx, ecx, edx); 267 | string tmp = cpuname2str(eax, ebx, ecx, edx); 268 | cpu_info.name = strcat(cpu_info.name, tmp); 269 | free(tmp); 270 | } 271 | } 272 | cpu_info.stepping = stepping; 273 | cpu_info.reserved = reserved; 274 | } 275 | 276 | /* AMD-specific information */ 277 | void CpuAmd(void) { 278 | cpu_info.brand = "AMD"; 279 | cpu_info.extended_family = "Unknow"; 280 | uint32 extended, eax, ebx, ecx, edx, unused; 281 | int family, model, stepping, reserved; 282 | cpuid(1, eax, unused, unused, unused); 283 | model = (eax >> 4) & 0xf; 284 | family = (eax >> 8) & 0xf; 285 | stepping = eax & 0xf; 286 | reserved = eax >> 12; 287 | switch(family) { 288 | case 4: 289 | cpu_info.family = "486 Model " + model; 290 | break; 291 | case 5: 292 | switch(model) { 293 | case 0: 294 | case 1: 295 | case 2: 296 | case 3: 297 | case 6: 298 | case 7: 299 | cpu_info.model = "K6 Model " + model; 300 | break; 301 | case 8: 302 | cpu_info.model = "K6-2 Model 8"; 303 | break; 304 | case 9: 305 | cpu_info.model = "K6-III Model 9"; 306 | break; 307 | default: 308 | cpu_info.model = "K5/K6 Model " + model; 309 | break; 310 | } 311 | break; 312 | case 6: 313 | switch(model) { 314 | case 1: 315 | case 2: 316 | case 4: 317 | cpu_info.model = "Athlon Model " + model; 318 | break; 319 | case 3: 320 | cpu_info.model = "Duron Model 3"; 321 | break; 322 | case 6: 323 | cpu_info.model = "Athlon MP/Mobile Athlon Model 6"; 324 | break; 325 | case 7: 326 | cpu_info.model = "Mobile Duron Model 7"; 327 | break; 328 | default: 329 | cpu_info.model = "Duron/Athlon Model " + model; 330 | break; 331 | } 332 | break; 333 | default: 334 | cpu_info.model = "Unknow"; 335 | break; 336 | } 337 | cpuid(0x80000000, extended, unused, unused, unused); 338 | if(extended == 0) { 339 | return; 340 | } 341 | cpu_info.name = ""; 342 | if(extended >= 0x80000002) { 343 | for(uint32 j = 0x80000002; j <= 0x80000004; j++) { 344 | cpuid(j, eax, ebx, ecx, edx); 345 | string tmp = cpuname2str(eax, ebx, ecx, edx); 346 | cpu_info.name = strcat(cpu_info.name, tmp); 347 | free(tmp); 348 | } 349 | } 350 | /*if(extended >= 0x80000007) { 351 | cpuid(0x80000007, unused, unused, unused, edx); 352 | if(edx & 1) { 353 | print("Temperature Sensing Diode Detected!"); 354 | } 355 | }*/ 356 | cpu_info.stepping = stepping; 357 | cpu_info.reserved = reserved; 358 | } 359 | 360 | /* Simply call this function detect_cpu(); */ 361 | void detectCpu() { /* or main() if your trying to port this as an independant application */ 362 | uint32 ebx, unused; 363 | cpuid(0, unused, ebx, unused, unused); 364 | switch(ebx) { 365 | case 0x756e6547: /* Intel Magic Code */ 366 | CpuIntel(); 367 | break; 368 | case 0x68747541: /* AMD Magic Code */ 369 | CpuAmd(); 370 | break; 371 | default: ; 372 | cpu_info.brand = "Unknown"; 373 | cpu_info.type = "Unknown"; 374 | cpu_info.family = "Unknown"; 375 | cpu_info.extended_family = "Unknown"; 376 | cpu_info.model = "Unknown"; 377 | cpu_info.stepping = 0; 378 | cpu_info.reserved = 0; 379 | break; 380 | } 381 | //Check AVX Support (technically its already enabled, but we did not pass that info to the kern so...) 382 | uint32 eax = 0, ecx = 0; 383 | cpuid(7, eax, ebx, ecx, unused); 384 | ebx &= (1 << 16); //AVX512F 385 | if(ebx) 386 | { 387 | cpu_info.AVX = 3; 388 | return; 389 | } 390 | eax ^= eax; ebx ^= ebx; ecx ^= ecx; 391 | cpuid(7, eax, ebx, ecx, unused); 392 | ebx &= (1 << 5); //AVX2 393 | if(ebx) 394 | { 395 | cpu_info.AVX = 2; 396 | return; 397 | } 398 | eax ^= eax; ebx ^= ebx; ecx ^= ecx; 399 | cpuid(1, eax, ebx, ecx, unused); 400 | ecx &= (1 << 28); //AVX 401 | if(ecx) 402 | { 403 | cpu_info.AVX = 1; 404 | return; 405 | } 406 | cpu_info.AVX = 0; //SSE Only 407 | return; 408 | } 409 | -------------------------------------------------------------------------------- /kernel/src/arch/x86/cpu.h: -------------------------------------------------------------------------------- 1 | #ifndef CPU_H 2 | #define CPU_H 3 | 4 | #include "../../string/types.h" 5 | #include "../../string/string.h" 6 | #include "../../memory/pmm.h" 7 | 8 | #define cpuid(in, a, b, c, d) __asm__("cpuid": "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "a" (in)); 9 | 10 | struct cpu_info_t 11 | { 12 | string brand; 13 | string type; 14 | string family; 15 | string extended_family; 16 | string model; 17 | string name; 18 | uint32 stepping; 19 | uint32 reserved; 20 | uint8 AVX; //0 means no AVX, 1 means AVX1, 2 AVX2, 3 AVX512 21 | } __attribute__((packed)); 22 | 23 | struct cpu_info_t cpu_info; 24 | 25 | void CPUDisableInts(void); 26 | void CPUEnableInts(void); 27 | uint8 inportb (uint16 _port); 28 | void outportb (uint16 _port, uint8 _data); 29 | uint16 inportw(uint16 _port); 30 | void outportw(uint16 _port, uint16 _data); 31 | uint32 inportl(uint16 _port); 32 | void outportl(uint16 _port, uint32 _data); 33 | void rdmsr(uint32 msr, uint32 *low, uint32 *high); 34 | void wrmsr(uint32 msr, uint32 low, uint32 high); 35 | void detectCpu(); 36 | 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /kernel/src/arch/x86/idt.c: -------------------------------------------------------------------------------- 1 | #include "idt.h" 2 | #include "irq.h" 3 | 4 | idt_entry_t idt[256] __attribute__((section(".bss"))); 5 | idt_ptr_t idt_ptr __attribute__((section(".bss"))); 6 | idt_entry_t idt_smp[256] __attribute__((section(".bss"))); 7 | idt_ptr_t idt_ptr_smp __attribute__((section(".bss"))); 8 | 9 | void PIC_Mask(uint32 line) 10 | { 11 | uint16 port = 0; 12 | uint8 val = 0; 13 | if(line < 8) 14 | { 15 | port = 0x21; 16 | } else { 17 | port = 0xA1; 18 | line -= 8; 19 | } 20 | val = inportb(port) | (1 << line); 21 | outportb(port, val); 22 | } 23 | 24 | void PIC_Unmask(uint32 line) 25 | { 26 | uint16 port = 0; 27 | uint8 val = 0; 28 | if(line < 8) 29 | { 30 | port = 0x21; 31 | } else { 32 | port = 0xA1; 33 | line -= 8; 34 | } 35 | val = inportb(port) & ~(1 << line); 36 | outportb(port, val); 37 | } 38 | 39 | void PIC_Map(void) 40 | { 41 | outportb(0x20, 0x11); 42 | outportb(0xA0, 0x11); 43 | outportb(0x21, 0x20); 44 | outportb(0xA1, 0x20); 45 | outportb(0x21, 4); 46 | outportb(0xA1, 2); 47 | outportb(0x21, 0x01); 48 | outportb(0xA1, 0x01); 49 | outportb(0x21, 0); 50 | outportb(0xA1, 0); 51 | return; 52 | } 53 | 54 | void PIC_Unmap(void) 55 | { 56 | outportb(0xA1, 0xFF); 57 | outportb(0x21, 0xFF); 58 | return; 59 | } 60 | 61 | void SetIsr(void) 62 | { 63 | idt_ptr.limit = sizeof(idt_entry_t) * 256 - 1; //Since this function is supposed to be the first one called when setting up the idt, we will configure the descriptor right here 64 | idt_ptr.base = &idt; 65 | memset(&idt, 0, sizeof(idt_entry_t)*256); 66 | 67 | idtSetGate(0, (uint64)&isr0, 0x08, 0x8E); 68 | idtSetGate(1, (uint64)&isr1, 0x08, 0x8E); 69 | idtSetGate(2, (uint64)&isr2, 0x08, 0x8E); 70 | idtSetGate(3, (uint64)&isr3, 0x08, 0x8E); 71 | idtSetGate(4, (uint64)&isr4, 0x08, 0x8E); 72 | idtSetGate(5, (uint64)&isr5, 0x08, 0x8E); 73 | idtSetGate(6, (uint64)&isr6, 0x08, 0x8E); 74 | idtSetGate(7, (uint64)&isr7, 0x08, 0x8E); 75 | idtSetGate(8, (uint64)&isr8, 0x08, 0x8E); 76 | idtSetGate(9, (uint64)&isr9, 0x08, 0x8E); 77 | idtSetGate(10, (uint64)&isr10, 0x08, 0x8E); 78 | idtSetGate(11, (uint64)&isr11, 0x08, 0x8E); 79 | idtSetGate(12, (uint64)&isr12, 0x08, 0x8E); 80 | idtSetGate(13, (uint64)&isr13, 0x08, 0x8E); 81 | idtSetGate(14, (uint64)&isr14, 0x08, 0x8E); 82 | idtSetGate(15, (uint64)&isr15, 0x08, 0x8E); 83 | idtSetGate(16, (uint64)&isr16, 0x08, 0x8E); 84 | idtSetGate(17, (uint64)&isr17, 0x08, 0x8E); 85 | idtSetGate(18, (uint64)&isr18, 0x08, 0x8E); 86 | idtSetGate(19, (uint64)&isr19, 0x08, 0x8E); 87 | idtSetGate(20, (uint64)&isr20, 0x08, 0x8E); 88 | idtSetGate(21, (uint64)&isr21, 0x08, 0x8E); 89 | idtSetGate(22, (uint64)&isr22, 0x08, 0x8E); 90 | idtSetGate(23, (uint64)&isr23, 0x08, 0x8E); 91 | idtSetGate(24, (uint64)&isr24, 0x08, 0x8E); 92 | idtSetGate(25, (uint64)&isr25, 0x08, 0x8E); 93 | idtSetGate(26, (uint64)&isr26, 0x08, 0x8E); 94 | idtSetGate(27, (uint64)&isr27, 0x08, 0x8E); 95 | idtSetGate(28, (uint64)&isr28, 0x08, 0x8E); 96 | idtSetGate(29, (uint64)&isr29, 0x08, 0x8E); 97 | idtSetGate(30, (uint64)&isr30, 0x08, 0x8E); 98 | idtSetGate(31, (uint64)&isr31, 0x08, 0x8E); 99 | } 100 | 101 | void SetIrq(void) 102 | { 103 | idtSetGate(32, (uint64)&irq0, 0x08, 0x8E); 104 | idtSetGate(33, (uint64)&irq1, 0x08, 0x8E); 105 | idtSetGate(34, (uint64)&irq2, 0x08, 0x8E); 106 | idtSetGate(35, (uint64)&irq3, 0x08, 0x8E); 107 | idtSetGate(36, (uint64)&irq4, 0x08, 0x8E); 108 | idtSetGate(37, (uint64)&irq5, 0x08, 0x8E); 109 | idtSetGate(38, (uint64)&irq6, 0x08, 0x8E); 110 | idtSetGate(39, (uint64)&irq7, 0x08, 0x8E); 111 | idtSetGate(40, (uint64)&irq8, 0x08, 0x8E); 112 | idtSetGate(41, (uint64)&irq9, 0x08, 0x8E); 113 | idtSetGate(42, (uint64)&irq10, 0x08, 0x8E); 114 | idtSetGate(43, (uint64)&irq11, 0x08, 0x8E); 115 | idtSetGate(44, (uint64)&irq12, 0x08, 0x8E); 116 | idtSetGate(45, (uint64)&irq13, 0x08, 0x8E); 117 | idtSetGate(46, (uint64)&irq14, 0x08, 0x8E); 118 | idtSetGate(47, (uint64)&irq15, 0x08, 0x8E); 119 | } 120 | 121 | void SetLapicSpuriousIrq(void) 122 | { 123 | idtSetGate(255, (uint64)&lapic_spurious, 0x08, 0x8E); 124 | } 125 | 126 | void idtInit(void) 127 | { 128 | asm volatile("lidt %0" :: "m"(idt_ptr)); 129 | asm volatile("sti"); 130 | } 131 | 132 | void idtSetGate(int gate, uint64 base, uint16 selector, uint8 type) 133 | { 134 | idt[gate].offset_1 = base; 135 | idt[gate].selector = selector; 136 | idt[gate].zero = 0; 137 | idt[gate].ist = 0; 138 | idt[gate].type_attr = type; 139 | idt[gate].offset_2 = base >> 16; 140 | idt[gate].offset_3 = base >> 32; 141 | } 142 | -------------------------------------------------------------------------------- /kernel/src/arch/x86/idt.h: -------------------------------------------------------------------------------- 1 | #ifndef IDT_H 2 | #define IDT_H 3 | 4 | #include "../../string/types.h" 5 | 6 | typedef struct idt_entry 7 | { 8 | uint16 offset_1; 9 | uint16 selector; 10 | uint8 ist; 11 | uint8 type_attr; 12 | uint16 offset_2; 13 | uint32 offset_3; 14 | uint32 zero; 15 | } __attribute__((packed)) idt_entry_t; 16 | 17 | typedef struct idt_ptr 18 | { 19 | uint16 limit; 20 | idt_entry_t *base; 21 | } __attribute__((packed)) idt_ptr_t; 22 | 23 | extern int isr0(); 24 | extern int isr1(); 25 | extern int isr2(); 26 | extern int isr3(); 27 | extern int isr4(); 28 | extern int isr5(); 29 | extern int isr6(); 30 | extern int isr7(); 31 | extern int isr8(); 32 | extern int isr9(); 33 | extern int isr10(); 34 | extern int isr11(); 35 | extern int isr12(); 36 | extern int isr13(); 37 | extern int isr14(); 38 | extern int isr15(); 39 | extern int isr16(); 40 | extern int isr17(); 41 | extern int isr18(); 42 | extern int isr19(); 43 | extern int isr20(); 44 | extern int isr21(); 45 | extern int isr22(); 46 | extern int isr23(); 47 | extern int isr24(); 48 | extern int isr25(); 49 | extern int isr26(); 50 | extern int isr27(); 51 | extern int isr28(); 52 | extern int isr29(); 53 | extern int isr30(); 54 | extern int isr31(); 55 | 56 | extern int irq0(); 57 | extern int irq1(); 58 | extern int irq2(); 59 | extern int irq3(); 60 | extern int irq4(); 61 | extern int irq5(); 62 | extern int irq6(); 63 | extern int irq7(); 64 | extern int irq8(); 65 | extern int irq9(); 66 | extern int irq10(); 67 | extern int irq11(); 68 | extern int irq12(); 69 | extern int irq13(); 70 | extern int irq14(); 71 | extern int irq15(); 72 | 73 | void PIC_Map(void); 74 | void PIC_Unmap(void); 75 | void idtSetGate(int gate, uint64 base, uint16 selector, uint8 type); 76 | void SetIsr(void); 77 | void SetIrq(void); 78 | void SetLapicSpuriousIrq(void); 79 | void idtInit(void); 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /kernel/src/arch/x86/ioapic.c: -------------------------------------------------------------------------------- 1 | #include "ioapic.h" 2 | 3 | uint32 IoApicAddress = 0; 4 | 5 | uint32 ReadIoApic(uint32 reg) 6 | { 7 | uint32 volatile *ioapic = (uint32 volatile*)IoApicAddress; 8 | ioapic[0] = (reg & 0xFF); 9 | return ioapic[4]; 10 | } 11 | 12 | void WriteIoApic(uint32 reg, uint32 val) 13 | { 14 | uint32 volatile *ioapic = (uint32 volatile*)IoApicAddress; 15 | ioapic[0] = (reg & 0xFF); 16 | ioapic[4] = val; 17 | } 18 | 19 | void ioapicEnable(uint32 addr, uint8 cpu) 20 | { 21 | IoApicAddress = addr; 22 | for(int i = 0; i < 24; i++) 23 | { 24 | WriteIoApic(0x10 + i * 2, 0x20 + i); //Enable all interrupts 25 | WriteIoApic(0x10 + i * 2 + 1, cpu << 24); 26 | } 27 | SetApicIRQ(true); 28 | lapicSendEOI(); 29 | asm volatile("sti"); 30 | } 31 | 32 | void ioapicDisable() 33 | { 34 | for(int i = 0; i < 24; i++) WriteIoApic(0x10 + i * 2, 1 << 16); 35 | SetApicIRQ(false); 36 | return; 37 | } 38 | 39 | void ioapicMapIrq(uint32 irq_src, uint32 irq_dst, uint8 cpu) 40 | { 41 | WriteIoApic(0x10 + irq_src * 2, 0x20 + irq_dst); 42 | WriteIoApic(0x10 + irq_src * 2 + 1, 0); 43 | } 44 | 45 | void ioapicMaskIrq(uint32 irq) 46 | { 47 | if(IoApicAddress == 0) 48 | { 49 | PIC_Mask(irq); 50 | return; 51 | } 52 | WriteIoApic(0x10 + irq * 2, 1 << 16); //mask 53 | } 54 | 55 | void IOApicConfigureNMI(uint8 irq, uint8 flags) 56 | { 57 | WriteIoApic(0x10 + irq * 2, (0x20 + irq) | (4 << 8) | (flags << 12)); 58 | WriteIoApic(0x10 + irq * 2 + 1, 0); 59 | } 60 | -------------------------------------------------------------------------------- /kernel/src/arch/x86/ioapic.h: -------------------------------------------------------------------------------- 1 | #ifndef IOAPIC_H 2 | #define IOAPIC_H 3 | 4 | #include "../../string/types.h" 5 | #include "../../drivers/acpi/acpi.h" 6 | #include "lapic.h" 7 | 8 | void ioapicEnable(uint32 address, uint8 cpu); 9 | void ioapicDisable(void); 10 | void IOApicConfigureNMI(uint8 irq, uint8 flags); 11 | void ioapicMapIrq(uint32 irq_src, uint32 irq_dst, uint8 cpu); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /kernel/src/arch/x86/irq.asm: -------------------------------------------------------------------------------- 1 | global irq0 2 | global irq1 3 | global irq2 4 | global irq3 5 | global irq4 6 | global irq5 7 | global irq6 8 | global irq7 9 | global irq8 10 | global irq9 11 | global irq10 12 | global irq11 13 | global irq12 14 | global irq13 15 | global irq14 16 | global irq15 17 | 18 | extern irq0_handler 19 | extern irq1_handler 20 | extern irq2_handler 21 | extern irq3_handler 22 | extern irq4_handler 23 | extern irq5_handler 24 | extern irq6_handler 25 | extern irq7_handler 26 | extern irq8_handler 27 | extern irq9_handler 28 | extern irq10_handler 29 | extern irq11_handler 30 | extern irq12_handler 31 | extern irq13_handler 32 | extern irq14_handler 33 | extern irq15_handler 34 | 35 | irq0: 36 | push rax 37 | push rcx 38 | push rdx 39 | push rbx 40 | push rbp 41 | push rsp 42 | push rsi 43 | push rdi 44 | call irq0_handler 45 | pop rdi 46 | pop rsi 47 | pop rsp 48 | pop rbp 49 | pop rbx 50 | pop rdx 51 | pop rcx 52 | pop rax 53 | iretq 54 | 55 | irq1: 56 | push rax 57 | push rcx 58 | push rdx 59 | push rbx 60 | push rbp 61 | push rsp 62 | push rsi 63 | push rdi 64 | call irq1_handler 65 | pop rdi 66 | pop rsi 67 | pop rsp 68 | pop rbp 69 | pop rbx 70 | pop rdx 71 | pop rcx 72 | pop rax 73 | iretq 74 | 75 | irq2: 76 | push rax 77 | push rcx 78 | push rdx 79 | push rbx 80 | push rbp 81 | push rsp 82 | push rsi 83 | push rdi 84 | call irq2_handler 85 | pop rdi 86 | pop rsi 87 | pop rsp 88 | pop rbp 89 | pop rbx 90 | pop rdx 91 | pop rcx 92 | pop rax 93 | iretq 94 | 95 | irq3: 96 | push rax 97 | push rcx 98 | push rdx 99 | push rbx 100 | push rbp 101 | push rsp 102 | push rsi 103 | push rdi 104 | call irq3_handler 105 | pop rdi 106 | pop rsi 107 | pop rsp 108 | pop rbp 109 | pop rbx 110 | pop rdx 111 | pop rcx 112 | pop rax 113 | iretq 114 | 115 | irq4: 116 | push rax 117 | push rcx 118 | push rdx 119 | push rbx 120 | push rbp 121 | push rsp 122 | push rsi 123 | push rdi 124 | call irq4_handler 125 | pop rdi 126 | pop rsi 127 | pop rsp 128 | pop rbp 129 | pop rbx 130 | pop rdx 131 | pop rcx 132 | pop rax 133 | iretq 134 | 135 | irq5: 136 | push rax 137 | push rcx 138 | push rdx 139 | push rbx 140 | push rbp 141 | push rsp 142 | push rsi 143 | push rdi 144 | call irq5_handler 145 | pop rdi 146 | pop rsi 147 | pop rsp 148 | pop rbp 149 | pop rbx 150 | pop rdx 151 | pop rcx 152 | pop rax 153 | iretq 154 | 155 | irq6: 156 | push rax 157 | push rcx 158 | push rdx 159 | push rbx 160 | push rbp 161 | push rsp 162 | push rsi 163 | push rdi 164 | call irq6_handler 165 | pop rdi 166 | pop rsi 167 | pop rsp 168 | pop rbp 169 | pop rbx 170 | pop rdx 171 | pop rcx 172 | pop rax 173 | iretq 174 | 175 | irq7: 176 | push rax 177 | push rcx 178 | push rdx 179 | push rbx 180 | push rbp 181 | push rsp 182 | push rsi 183 | push rdi 184 | call irq7_handler 185 | pop rdi 186 | pop rsi 187 | pop rsp 188 | pop rbp 189 | pop rbx 190 | pop rdx 191 | pop rcx 192 | pop rax 193 | iretq 194 | 195 | irq8: 196 | push rax 197 | push rcx 198 | push rdx 199 | push rbx 200 | push rbp 201 | push rsp 202 | push rsi 203 | push rdi 204 | call irq8_handler 205 | pop rdi 206 | pop rsi 207 | pop rsp 208 | pop rbp 209 | pop rbx 210 | pop rdx 211 | pop rcx 212 | pop rax 213 | iretq 214 | 215 | irq9: 216 | push rax 217 | push rcx 218 | push rdx 219 | push rbx 220 | push rbp 221 | push rsp 222 | push rsi 223 | push rdi 224 | call irq9_handler 225 | pop rdi 226 | pop rsi 227 | pop rsp 228 | pop rbp 229 | pop rbx 230 | pop rdx 231 | pop rcx 232 | pop rax 233 | iretq 234 | 235 | irq10: 236 | push rax 237 | push rcx 238 | push rdx 239 | push rbx 240 | push rbp 241 | push rsp 242 | push rsi 243 | push rdi 244 | call irq10_handler 245 | pop rdi 246 | pop rsi 247 | pop rsp 248 | pop rbp 249 | pop rbx 250 | pop rdx 251 | pop rcx 252 | pop rax 253 | iretq 254 | 255 | irq11: 256 | push rax 257 | push rcx 258 | push rdx 259 | push rbx 260 | push rbp 261 | push rsp 262 | push rsi 263 | push rdi 264 | call irq11_handler 265 | pop rdi 266 | pop rsi 267 | pop rsp 268 | pop rbp 269 | pop rbx 270 | pop rdx 271 | pop rcx 272 | pop rax 273 | iretq 274 | 275 | irq12: 276 | push rax 277 | push rcx 278 | push rdx 279 | push rbx 280 | push rbp 281 | push rsp 282 | push rsi 283 | push rdi 284 | call irq12_handler 285 | pop rdi 286 | pop rsi 287 | pop rsp 288 | pop rbp 289 | pop rbx 290 | pop rdx 291 | pop rcx 292 | pop rax 293 | iretq 294 | 295 | irq13: 296 | push rax 297 | push rcx 298 | push rdx 299 | push rbx 300 | push rbp 301 | push rsp 302 | push rsi 303 | push rdi 304 | call irq13_handler 305 | pop rdi 306 | pop rsi 307 | pop rsp 308 | pop rbp 309 | pop rbx 310 | pop rdx 311 | pop rcx 312 | pop rax 313 | iretq 314 | 315 | irq14: 316 | push rax 317 | push rcx 318 | push rdx 319 | push rbx 320 | push rbp 321 | push rsp 322 | push rsi 323 | push rdi 324 | call irq14_handler 325 | pop rdi 326 | pop rsi 327 | pop rsp 328 | pop rbp 329 | pop rbx 330 | pop rdx 331 | pop rcx 332 | pop rax 333 | iretq 334 | 335 | irq15: 336 | push rax 337 | push rcx 338 | push rdx 339 | push rbx 340 | push rbp 341 | push rsp 342 | push rsi 343 | push rdi 344 | call irq15_handler 345 | pop rdi 346 | pop rsi 347 | pop rsp 348 | pop rbp 349 | pop rbx 350 | pop rdx 351 | pop rcx 352 | pop rax 353 | iretq 354 | -------------------------------------------------------------------------------- /kernel/src/arch/x86/irq.c: -------------------------------------------------------------------------------- 1 | #include "irq.h" 2 | 3 | bool isapicenabled = false; 4 | 5 | void SetApicIRQ(bool val) 6 | { 7 | isapicenabled = val; 8 | } 9 | 10 | void lapic_spurious() 11 | { 12 | lapicSendEOI(); 13 | return; 14 | } 15 | 16 | void irq0_handler() 17 | { 18 | if(memcmp(getUsedTimer(),"PIT",3) == 0) 19 | { 20 | pitHandler(); 21 | } else if(memcmp(getUsedTimer(),"APIC", 4) == 0){ 22 | lapicTimerHandler(); 23 | } else if(memcmp(getUsedTimer(),"HPET",4) == 0) { 24 | HpetHandler(); 25 | } 26 | if(!isapicenabled) 27 | { 28 | outportb(0x20, 0x20); 29 | } else { 30 | lapicSendEOI(); 31 | } 32 | return; 33 | } 34 | 35 | void irq1_handler() 36 | { 37 | kbd_handler(); 38 | if(!isapicenabled) 39 | { 40 | outportb(0x20, 0x20); 41 | } else { 42 | lapicSendEOI(); 43 | } 44 | return; 45 | } 46 | 47 | void irq2_handler() 48 | { 49 | if(memcmp(getUsedTimer(),"PIT",3) == 0) 50 | { 51 | pitHandler(); 52 | } else if(memcmp(getUsedTimer(),"APIC", 4) == 0){ 53 | lapicTimerHandler(); 54 | } else if(memcmp(getUsedTimer(),"HPET", 4) == 0) { 55 | HpetHandler(); 56 | } 57 | if(!isapicenabled) 58 | { 59 | outportb(0x20, 0x20); 60 | } else { 61 | lapicSendEOI(); 62 | } 63 | return; 64 | } 65 | 66 | void irq3_handler() 67 | { 68 | if(!isapicenabled) 69 | { 70 | outportb(0x20, 0x20); 71 | } else { 72 | lapicSendEOI(); 73 | } 74 | return; 75 | } 76 | 77 | void irq4_handler() 78 | { 79 | if(!isapicenabled) 80 | { 81 | outportb(0x20, 0x20); 82 | } else { 83 | lapicSendEOI(); 84 | } 85 | return; 86 | } 87 | 88 | void irq5_handler() 89 | { 90 | if(!isapicenabled) 91 | { 92 | outportb(0x20, 0x20); 93 | } else { 94 | lapicSendEOI(); 95 | } 96 | return; 97 | } 98 | 99 | void irq6_handler() 100 | { 101 | if(!isapicenabled) 102 | { 103 | outportb(0x20, 0x20); 104 | } else { 105 | lapicSendEOI(); 106 | } 107 | return; 108 | } 109 | 110 | void irq7_handler() 111 | { 112 | if(!isapicenabled) 113 | { 114 | outportb(0x20, 0x20); 115 | } else { 116 | lapicSendEOI(); 117 | } 118 | return; 119 | } 120 | 121 | void irq8_handler() 122 | { 123 | if(!isapicenabled) 124 | { 125 | outportb(0xA0, 0x20); 126 | outportb(0x20, 0x20); 127 | } else { 128 | lapicSendEOI(); 129 | } 130 | return; 131 | } 132 | 133 | void irq9_handler() 134 | { 135 | AcpiSCIHandler(); 136 | if(!isapicenabled) 137 | { 138 | outportb(0xA0, 0x20); 139 | outportb(0x20, 0x20); 140 | } else { 141 | lapicSendEOI(); 142 | } 143 | return; 144 | } 145 | 146 | void irq10_handler() 147 | { 148 | if(!isapicenabled) 149 | { 150 | outportb(0xA0, 0x20); 151 | outportb(0x20, 0x20); 152 | } else { 153 | lapicSendEOI(); 154 | } 155 | return; 156 | } 157 | 158 | void irq11_handler() 159 | { 160 | if(!isapicenabled) 161 | { 162 | outportb(0xA0, 0x20); 163 | outportb(0x20, 0x20); 164 | } else { 165 | lapicSendEOI(); 166 | } 167 | return; 168 | } 169 | 170 | void irq12_handler() 171 | { 172 | if(!isapicenabled) 173 | { 174 | outportb(0xA0, 0x20); 175 | outportb(0x20, 0x20); 176 | } else { 177 | lapicSendEOI(); 178 | } 179 | return; 180 | } 181 | 182 | void irq13_handler() 183 | { 184 | if(!isapicenabled) 185 | { 186 | outportb(0xA0, 0x20); 187 | outportb(0x20, 0x20); 188 | } else { 189 | lapicSendEOI(); 190 | } 191 | return; 192 | } 193 | 194 | void irq14_handler() 195 | { 196 | ata_irq_handler(0); //ATA Bus 0 197 | if(!isapicenabled) 198 | { 199 | outportb(0xA0, 0x20); 200 | outportb(0x20, 0x20); 201 | } else { 202 | lapicSendEOI(); 203 | } 204 | return; 205 | } 206 | 207 | void irq15_handler() 208 | { 209 | if(!isapicenabled) 210 | { 211 | outportb(0xA0, 0x20); 212 | outportb(0x20, 0x20); 213 | } else { 214 | lapicSendEOI(); 215 | } 216 | ata_irq_handler(1); //ATA Bus 1 217 | return; 218 | } 219 | -------------------------------------------------------------------------------- /kernel/src/arch/x86/irq.h: -------------------------------------------------------------------------------- 1 | #ifndef IRQ_H 2 | #define IRQ_H 3 | 4 | #include "../../string/types.h" 5 | #include "../../drivers/kb/kb.h" 6 | #include "../../drivers/pit/pit.h" 7 | #include "../../drivers/sleep/sleep.h" 8 | #include "../../drivers/ata/ata.h" 9 | #include "lapic.h" 10 | 11 | void lapic_spurious(); 12 | void irq0_handler(); 13 | void irq1_handler(); 14 | void irq3_handler(); 15 | void irq4_handler(); 16 | void irq5_handler(); 17 | void irq6_handler(); 18 | void irq7_handler(); 19 | void irq8_handler(); 20 | void irq9_handler(); 21 | void irq10_handler(); 22 | void irq11_handler(); 23 | void irq12_handler(); 24 | void irq13_handler(); 25 | void irq14_handler(); 26 | void irq15_handler(); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /kernel/src/arch/x86/isr.h: -------------------------------------------------------------------------------- 1 | #ifndef ISR_H 2 | #define ISR_H 3 | 4 | #include "../../string/types.h" 5 | #include "../../console/console.h" 6 | #include "cpu.h" 7 | 8 | struct cpu_regs_t 9 | { 10 | uint64 ds, es, fs, gs; 11 | uint64 rdi, rsi, rbp, rdx, rcx, rbx, rax; 12 | uint64 error_code, rip, cs, rflags, rsp, ss; 13 | } __attribute__((packed)); 14 | 15 | void isr0_handler(struct cpu_regs_t cpu_regs); 16 | void isr1_handler(struct cpu_regs_t cpu_regs); 17 | void isr2_handler(struct cpu_regs_t cpu_regs); 18 | void isr3_handler(struct cpu_regs_t cpu_regs); 19 | void isr4_handler(struct cpu_regs_t cpu_regs); 20 | void isr5_handler(struct cpu_regs_t cpu_regs); 21 | void isr6_handler(struct cpu_regs_t cpu_regs); 22 | void isr7_handler(struct cpu_regs_t cpu_regs); 23 | void isr8_handler(struct cpu_regs_t cpu_regs); 24 | void isr9_handler(struct cpu_regs_t cpu_regs); 25 | void isr10_handler(struct cpu_regs_t cpu_regs); 26 | void isr11_handler(struct cpu_regs_t cpu_regs); 27 | void isr12_handler(struct cpu_regs_t cpu_regs); 28 | void isr13_handler(struct cpu_regs_t cpu_regs); 29 | void isr14_handler(struct cpu_regs_t cpu_regs); 30 | void isr15_handler(struct cpu_regs_t cpu_regs); 31 | void isr16_handler(struct cpu_regs_t cpu_regs); 32 | void isr17_handler(struct cpu_regs_t cpu_regs); 33 | void isr18_handler(struct cpu_regs_t cpu_regs); 34 | void isr19_handler(struct cpu_regs_t cpu_regs); 35 | void isr20_handler(struct cpu_regs_t cpu_regs); 36 | void isr21_handler(struct cpu_regs_t cpu_regs); 37 | void isr22_handler(struct cpu_regs_t cpu_regs); 38 | void isr23_handler(struct cpu_regs_t cpu_regs); 39 | void isr24_handler(struct cpu_regs_t cpu_regs); 40 | void isr25_handler(struct cpu_regs_t cpu_regs); 41 | void isr26_handler(struct cpu_regs_t cpu_regs); 42 | void isr27_handler(struct cpu_regs_t cpu_regs); 43 | void isr28_handler(struct cpu_regs_t cpu_regs); 44 | void isr29_handler(struct cpu_regs_t cpu_regs); 45 | void isr30_handler(struct cpu_regs_t cpu_regs); 46 | void isr31_handler(struct cpu_regs_t cpu_regs); 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /kernel/src/arch/x86/lapic.c: -------------------------------------------------------------------------------- 1 | #include "lapic.h" 2 | 3 | extern void _ap_entry(); 4 | extern void _ap_pmode_trampoline(); 5 | extern int _ap_GDT32Pointer; 6 | 7 | /* */ 8 | /**************** Register Definition ****************/ 9 | /* */ 10 | 11 | #define LAPIC_ID_REG 0x20 12 | #define LAPIC_VER_REG 0x30//Version 13 | #define LAPIC_TPR 0x80//Task priority reg 14 | #define LAPIC_APR 0x90//Arbitration priority reg 15 | #define LAPIC_PPR 0xA0//Processor priority reg 16 | #define LAPIC_EOI 0xB0//End of interrupt reg 17 | #define LAPIC_RRD 0xC0//Remote read reg 18 | #define LAPIC_LDR 0xD0//Logical destination reg 19 | #define LAPIC_DFR 0xE0//Destination format reg 20 | #define LAPIC_SIVR 0xF0//Spurious interrupt vector reg 21 | #define LAPIC_ISR 0x100//In-service reg 22 | #define LAPIC_TMR 0x180//Trigger mode reg 23 | #define LAPIC_IRR 0x200//Interrupt request reg 24 | #define LAPIC_ESR 0x280//Error status reg 25 | #define LAPIC_CMCI 0x2F0//Corrected machine check interrupt reg 26 | #define LAPIC_LICR 0x300//(low)Interrupt command reg 27 | #define LAPIC_HICR 0x310//(high)Interrupt command reg 28 | #define LAPIC_TRR 0x320//Timer reg 29 | #define LAPIC_TSR 0x330//Thermal sensor reg 30 | #define LAPIC_PMCR 0x340//Performance monitoring counters reg 31 | #define LAPIC_LINT0 0x350//Local interrupt (type)0 //ExtINT 32 | #define LAPIC_LINT1 0x360//Local interrupt (type)1 //NMI 33 | #define LAPIC_ERR 0x370//Error reg 34 | #define LAPIC_TICR 0x380//Timer's initial count reg 35 | #define LAPIC_TCCR 0x390//Timer's current count reg 36 | #define LAPIC_TDCR 0x3E0//Timer's divider config reg 37 | #define LAPIC_INIT_IPI 5//Init IPI, bit 14 in ICR must be set, and bit 15 in ICR must be clear 38 | #define LAPIC_INITD_IPI 5//Init IPI Deassert, bit 14 in ICR must be clear, and bit 15 in ICR must be set 39 | #define LAPIC_SIPI 6//Startup IPI 40 | 41 | /* */ 42 | /**************** xApic ****************/ 43 | /* */ 44 | 45 | uint32 lapicGetBase(void) 46 | { 47 | uint32 a, b; 48 | rdmsr(0x1B, &a, &b); //0x1B is the msr address 49 | return (a & ~(0xFFF)) | ((b & 0xF) << 32); 50 | } 51 | 52 | void lapicSetBase(uint32 base) 53 | { 54 | //Base should in theory have the enable bit (11th) set 55 | uint32 b = (base >> 32) & 0xF; 56 | wrmsr(0x1B, base, b); 57 | } 58 | 59 | uint32 xApicReadReg(uint16 reg) 60 | { 61 | return *(volatile uint32*)(lapicGetBase() + reg); 62 | } 63 | 64 | void xApicWriteReg(uint16 reg, uint32 val) 65 | { 66 | *(volatile uint32*)(lapicGetBase() + reg) = val; 67 | return; 68 | } 69 | 70 | /* */ 71 | /**************** x2Apic ****************/ 72 | /* */ 73 | 74 | bool x2ApicEnabled = false; 75 | 76 | uint64 x2ApicReadReg(uint32 reg) 77 | { 78 | uint32 high, low; 79 | rdmsr(0x800 + reg / 16, &low, &high); 80 | return (high << 32) | low; 81 | } 82 | 83 | void x2ApicWriteReg(uint32 reg, uint64 val) 84 | { 85 | wrmsr(0x800 + reg / 16, val & 0xFFFFFFFF, val >> 32); //They must be inverted... 86 | return; 87 | } 88 | 89 | uint64 lapicReadReg(uint32 reg) 90 | { 91 | if(!x2ApicEnabled) 92 | { 93 | return xApicReadReg(reg); 94 | } else { 95 | return x2ApicReadReg(reg); 96 | } 97 | } 98 | 99 | void lapicWriteReg(uint32 reg, uint64 val) 100 | { 101 | if(!x2ApicEnabled) 102 | { 103 | uint32 low = val & 0xFFFFFFFF; //Sanity 104 | xApicWriteReg(reg, low); 105 | } else { 106 | x2ApicWriteReg(reg, val); 107 | } 108 | } 109 | 110 | void lapicSendEOI(void) 111 | { 112 | if(!x2ApicEnabled) 113 | { 114 | xApicWriteReg(LAPIC_EOI, 0); 115 | } else { 116 | x2ApicWriteReg(LAPIC_EOI, 0); 117 | } 118 | return; 119 | } 120 | 121 | void lapicEnable(uint32 flags) 122 | { 123 | if(flags & 1) PIC_Unmap(); 124 | uint32 ecx, unused; 125 | cpuid(1, unused, unused, ecx, unused); 126 | if(ecx & (1 << 21)) 127 | { 128 | x2ApicEnabled = true; 129 | lapicSetBase(lapicGetBase() | 0xD00); 130 | } else { 131 | x2ApicEnabled = false; 132 | lapicSetBase(lapicGetBase() | 0x900); 133 | } 134 | lapicWriteReg(LAPIC_SIVR, lapicReadReg(LAPIC_SIVR) | 0x1FF); //Spurious interrupt 135 | lapicWriteReg(LAPIC_TRR, 0x10000); //LVT Timer register 136 | lapicWriteReg(LAPIC_PMCR, 0x10000); //Performance counter 137 | lapicWriteReg(LAPIC_ERR, 0); //Clear error reg 138 | lapicWriteReg(LAPIC_ERR, 0); //Back to back! 139 | lapicSendEOI(); //EOI If any interrupt has not been ack'ed 140 | if(flags != 0) //Only if not BSP 141 | { 142 | lapicWriteReg(LAPIC_LINT0, 0x700); //Lint0 143 | lapicWriteReg(LAPIC_LINT1, 0x400); //Lint1 144 | } 145 | lapicWriteReg(LAPIC_TPR, 0); //Task priority register 146 | return; 147 | } 148 | 149 | void lapicConfigureNMI(uint8 lint, uint16 flags) 150 | { 151 | if(lint == 0) 152 | { 153 | lapicWriteReg(LAPIC_LINT0, (flags << 12) | (4 << 8)); 154 | } else { 155 | lapicWriteReg(LAPIC_LINT1, (flags << 12) | (4 << 8)); 156 | } 157 | } 158 | 159 | void lapicIPI(uint32 apicID, uint32 value) 160 | { 161 | if(!x2ApicEnabled) 162 | { 163 | lapicWriteReg(LAPIC_HICR, apicID << 24); 164 | lapicWriteReg(LAPIC_LICR, value); 165 | } else { 166 | lapicWriteReg(LAPIC_LICR, ((uint64)apicID << 32) | value); //With x2Apic, we'll always use logical destination 167 | } 168 | } 169 | 170 | void APWakeup(uint32 apicID, uint32 StartAddr) //We'll make an INIT-SIPI-SIPI Sequence. 171 | { 172 | volatile bool *check_start = 0x500; 173 | volatile bool *fully_started = 0x501; 174 | *check_start = false; 175 | lapicIPI(apicID, LAPIC_INIT_IPI << 8 | (1 << 14)); //Init 176 | lapicIPI(apicID, LAPIC_INITD_IPI << 8 | (1 << 15)); //Init-Deassert 177 | sleep(10, SleepMili);//milisecs 178 | if(lapicReadReg(LAPIC_LICR) & (1 << 12)) 179 | { 180 | printf("\nCPU With Apic ID %x failed to init.\n", apicID); 181 | return; 182 | } 183 | lapicIPI(apicID, (StartAddr / 0x1000) | LAPIC_SIPI << 8 | (1 << 14) | (1 << 15)); //Startup 184 | sleep(2, SleepMili);//milisecs 185 | if(*check_start == false) 186 | { 187 | lapicIPI(apicID, (StartAddr / 0x1000) | LAPIC_SIPI << 8 | (1 << 14) | (1 << 15)); //Startup 188 | sleep(2, SleepMili); 189 | if(*check_start == false) 190 | { 191 | printf("["); 192 | printcolor("PANIC", 0, 0xFFE00000); //red 193 | printf("] CPU%i failed to start\n", apicID); 194 | } 195 | } 196 | if(*check_start == false) return; 197 | while(!(*fully_started)); 198 | *fully_started = 0; 199 | } 200 | 201 | void SMP_Start(void) //Start all AP's (if any) 202 | { 203 | if(acpi_pm_info->cpus > 1) 204 | { 205 | id_vmmap(0x1000, 0x5000, 3); 206 | memcpy_fast(0x1000, &_ap_GDT32Pointer, 8); 207 | memcpy_fast(0x2000, &_ap_pmode_trampoline, 32); 208 | memcpy_fast(0x3000, &_ap_entry, 24); //Put the initialization code at a lower address 209 | for(int i = 1; i < acpi_pm_info->cpus; i++) 210 | { 211 | if((acpi_pm_info->lapic[i]->flags & 1) == 0) continue; 212 | uint64 Stack_Addr = kmalloc(0x20000); 213 | memcpy_fast(0x4000, &Stack_Addr, 8); 214 | APWakeup(acpi_pm_info->lapic[i]->apic_id, 0x3000); //Init AP 215 | } 216 | } 217 | } 218 | 219 | /* */ 220 | /**************** Timer stuff ****************/ 221 | /* */ 222 | 223 | uint32 timetillnext = 0; 224 | uint32 tickRate = 0; 225 | 226 | void lapicTimerStart(void) 227 | { 228 | lapicWriteReg(LAPIC_TDCR, 3); //Lapic timer's divisor, set to 16 229 | lapicWriteReg(LAPIC_TICR, 0xFFFFFFFF); //Lapic timer's init count, set to 0xFFFFFFFF 230 | lapicWriteReg(LAPIC_TRR, 0x20000); //unmask lapic's timer 231 | sleep(1, SleepMili); 232 | lapicWriteReg(LAPIC_TRR, 0x10000); //mask lapic's timer 233 | timetillnext = 0xFFFFFFFF - (lapicReadReg(LAPIC_TCCR) & 0xFFFFFFFF); //Current count, calculate the amount of ticks passed 234 | tickRate = 1000000 / (timetillnext/*timetillnext is 1ms*/); //In ns 235 | lapicWriteReg(LAPIC_TDCR, 3); //Lapic timer's divisor, set to 16 236 | lapicWriteReg(LAPIC_TICR, timetillnext); //Initial count; 237 | lapicWriteReg(LAPIC_TRR, 34 | 0x20000); //unmask timer and put it on periodic mode 238 | lapicSendEOI(); 239 | ChangeTimer("APIC"); 240 | } 241 | 242 | bool lapic_sleeping = false; 243 | uint32 lapic_countdown = 0; 244 | 245 | void lapicTimerHandler(void) 246 | { 247 | if(lapic_sleeping) 248 | { 249 | if(lapic_countdown) 250 | { 251 | if(lapic_countdown < tickRate) 252 | { 253 | lapic_countdown = 0; 254 | lapic_sleeping = false; 255 | } else { 256 | lapic_countdown-=tickRate; 257 | } 258 | } else { 259 | lapic_sleeping = false; 260 | } 261 | } 262 | return; 263 | } 264 | 265 | void lapicTimerSleep(uint32 time, uint8 type) 266 | { 267 | return; 268 | //The best i can say is, PLEASE DONT USE THIS SHIT 269 | lapic_countdown = time; 270 | lapic_sleeping = true; 271 | while(lapic_sleeping) asm volatile("hlt"); //Halt CPU until next interrupt arrives 272 | return; 273 | } 274 | -------------------------------------------------------------------------------- /kernel/src/arch/x86/lapic.h: -------------------------------------------------------------------------------- 1 | #ifndef LAPIC_H 2 | #define LAPIC_H 3 | 4 | #include "../../console/console.h" 5 | #include "../../string/types.h" 6 | #include "cpu.h" 7 | #include "../../drivers/acpi/acpi.h" 8 | #include "ioapic.h" 9 | #include "../../drivers/sleep/sleep.h" 10 | 11 | void lapicEnable(uint32 flags); 12 | void lapicConfigureNMI(uint8 lint, uint16 flags); 13 | void lapicIPI(uint32 apicID, uint32 value); 14 | void APWakeup(uint32 apicID, uint32 StartAddr); 15 | void SMP_Start(void); 16 | void lapicTimerStart(void); 17 | void lapicTimerHandler(void); 18 | void lapicTimerSleep(uint32 time, uint8 type); 19 | void lapicSendEOI(void); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /kernel/src/arch/x86/smp.asm: -------------------------------------------------------------------------------- 1 | [bits 16] 2 | section .uarch 3 | global _ap_entry 4 | _ap_entry: 5 | mov BYTE [0x500], 1 6 | cli 7 | lgdt [0x1000] 8 | mov eax, cr0 9 | or al, 1 10 | mov cr0, eax 11 | jmp 0x8:0x2000 12 | 13 | [bits 32] 14 | global _ap_pmode_trampoline ;It is in the lower mem, lets use this for jumping to 1Meg 15 | _ap_pmode_trampoline: 16 | mov ax, 0x10 17 | mov ds, ax 18 | mov es, ax 19 | mov fs, ax 20 | mov gs, ax 21 | mov ss, ax 22 | lea eax, [_ap_pmode] ; If we don't do this, then the address will be a lil' greater than _ap_pmode_trampoline (and thus, stays around address 0x2000) 23 | jmp eax 24 | 25 | _ap_pmode: 26 | mov eax, 0x103000 27 | mov cr3, eax 28 | mov eax, cr4 29 | or eax, 1 << 5 30 | mov cr4, eax 31 | mov ecx, 0xC0000080 32 | rdmsr 33 | or eax, 1 << 8 34 | wrmsr 35 | mov eax, cr0 36 | or eax, 1 << 31 37 | mov cr0, eax 38 | lgdt [_ap_low_GDT64.pointer] 39 | jmp 0x8:_ap_lmode_trampoline 40 | 41 | [bits 64] 42 | _ap_lmode_trampoline: 43 | mov ax, 0x10 44 | mov ds, ax 45 | mov es, ax 46 | mov fs, ax 47 | mov gs, ax 48 | mov ss, ax 49 | mov rax, qword _ap_lmode 50 | jmp rax 51 | 52 | extern _ap_main 53 | 54 | section .text 55 | extern kmalloc 56 | _ap_lmode: 57 | mov rax, qword [0x4000] 58 | mov rbp, rax 59 | add rax, 0x1000 60 | mov rsp, rax 61 | push rax 62 | push rbx 63 | push rcx 64 | push rdx 65 | call AVX512Enable 66 | pop rdx 67 | pop rcx 68 | pop rbx 69 | pop rax 70 | call _ap_main 71 | cli 72 | hlt 73 | 74 | AVX512Enable: 75 | mov rax, cr4 76 | or rax, 1 << 9 ;enable fxsave fxstor 77 | or rax, 1 << 10 ;enable unmasked SIMD floating point exceptions 78 | mov cr4, rax 79 | 80 | mov rax, 7 81 | xor rcx, rcx 82 | xor rbx, rbx 83 | cpuid 84 | and rbx, 1 << 16 85 | cmp rbx, 1 << 16 86 | je .enable 87 | jne AVXEnable 88 | ret 89 | 90 | .enable: 91 | mov rax, cr4 92 | or rax, 1 << 18 93 | mov cr4, rax 94 | 95 | xor rcx, rcx 96 | xor rax, rax 97 | xgetbv 98 | or rax, 7 99 | or rax, 7 << 5 100 | xsetbv 101 | ret 102 | 103 | AVXEnable: 104 | mov rax, 7 105 | xor rcx, rcx 106 | xor rbx, rbx 107 | cpuid 108 | and rbx, 1 << 5 109 | cmp rbx, 1 << 5 110 | je .enable 111 | 112 | mov rax, 1 113 | xor rcx, rcx 114 | cpuid 115 | and rcx, 1 << 28 116 | cmp rcx, 1 << 28 117 | je .enable 118 | jne SSE_Enable 119 | ret 120 | 121 | .enable: 122 | mov rax, cr4 123 | or eax, 0x40000 124 | or eax, 1 << 9 ;enable fxsave fxstor 125 | or eax, 1 << 10 ;enable unmasked SIMD floating point exceptions 126 | mov cr4, rax 127 | 128 | xor rcx, rcx 129 | xor rax, rax 130 | xgetbv 131 | or rax, 7 132 | xsetbv 133 | ret 134 | 135 | SSE_Enable: 136 | mov rax, cr0 137 | and rax, ~(1 << 2) ; clear Emulation bit 138 | or rax, 1 << 1 ;enable Monitor co-processor 139 | mov cr0, rax 140 | ret 141 | 142 | section .pregdt 143 | global _ap_GDT32 144 | _ap_GDT32: 145 | dq 0 146 | .code: 147 | dw 0xFFFF 148 | dw 0 149 | dd 0x00CF9A00 150 | .data: 151 | dw 0xFFFF 152 | dw 0 153 | dd 0x00CF9200 154 | .end: 155 | 156 | global _ap_GDT32Pointer 157 | _ap_GDT32Pointer: 158 | dw _ap_GDT32.end - _ap_GDT32 - 1 159 | dd _ap_GDT32 160 | 161 | _ap_low_GDT64: 162 | dq 0 163 | .code: equ $ - _ap_low_GDT64 164 | dw 0xFFFF 165 | dw 0 166 | dd 0x00209A00 167 | .data: equ $ - _ap_low_GDT64 168 | dw 0xFFFF 169 | dw 0 170 | dd 0x00009200 171 | .pointer: 172 | dw $ - _ap_low_GDT64 - 1 173 | dq _ap_low_GDT64 174 | 175 | section .rodata 176 | _ap_GDT64: 177 | dq 0 178 | .code: equ $ - _ap_GDT64 179 | dw 0xFFFF 180 | dw 0 181 | dd 0x00209A00 182 | .data: equ $ - _ap_GDT64 183 | dw 0xFFFF 184 | dw 0 185 | dd 0x00009200 186 | .pointer: 187 | dw $ - _ap_GDT64 - 1 188 | dq _ap_GDT64 189 | 190 | ;Continue on lmode set up 191 | -------------------------------------------------------------------------------- /kernel/src/arch/x86/smp.c: -------------------------------------------------------------------------------- 1 | #include "smp.h" 2 | 3 | void _ap_main() 4 | { 5 | uint32 ebx = 0, unused = 0; 6 | cpuid(1, unused, ebx, unused, unused); 7 | idtInit(); //Idt has already been configured 8 | lapicEnable(0); 9 | printf("[INFO] CPU%i startup - Done!\n",(ebx & 0xFF000000) >> 24); 10 | volatile bool *fully_started = 0x501; 11 | *fully_started = true; 12 | while(1) //In case of an NMI / isr 13 | { 14 | asm("cli; hlt"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /kernel/src/arch/x86/smp.h: -------------------------------------------------------------------------------- 1 | #ifndef SMP_H 2 | #define SMP_H 3 | 4 | #include "../../string/types.h" 5 | #include "../../console/console.h" 6 | #include "cpu.h" 7 | #include "idt.h" 8 | #include "lapic.h" 9 | 10 | void _ap_main(); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /kernel/src/console/Font.psf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alberinfo/Slidoor-OS/e37cc96e86b6e4b43ae82ec263b716451ad7f72f/kernel/src/console/Font.psf -------------------------------------------------------------------------------- /kernel/src/console/Font10x10.psf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alberinfo/Slidoor-OS/e37cc96e86b6e4b43ae82ec263b716451ad7f72f/kernel/src/console/Font10x10.psf -------------------------------------------------------------------------------- /kernel/src/console/Font16x16.psf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alberinfo/Slidoor-OS/e37cc96e86b6e4b43ae82ec263b716451ad7f72f/kernel/src/console/Font16x16.psf -------------------------------------------------------------------------------- /kernel/src/console/Font8x8.psf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alberinfo/Slidoor-OS/e37cc96e86b6e4b43ae82ec263b716451ad7f72f/kernel/src/console/Font8x8.psf -------------------------------------------------------------------------------- /kernel/src/console/console.c: -------------------------------------------------------------------------------- 1 | #include "console.h" 2 | 3 | bool ConsoleInitialized = false; 4 | uint32 FontBytesPerLine; 5 | uint16 CursorPosX, CursorPosY, ScreenWidth, ScreenHeight, ScreenBPP; 6 | uint32 *restrict fb_addr; 7 | struct Font_t *font; 8 | struct multiboot_tag_framebuffer *fb; 9 | 10 | void ConsoleInit() 11 | { 12 | fb = get_mboot_info(multiboot_tag_TYPE_FRAMEBUFFER); 13 | vmmap((uint64)&_binary_Font_psf_start - 0xFFFF800000000000, &_binary_Font_psf_start, &_binary_Font_psf_end - &_binary_Font_psf_start, 3); 14 | font = &_binary_Font_psf_start; 15 | FontBytesPerLine = (font->width + 7) / 8; 16 | CursorPosX = 0; 17 | CursorPosY = 0; 18 | ScreenWidth = fb->common.framebuffer_width; 19 | ScreenHeight = fb->common.framebuffer_height; 20 | ScreenBPP = (fb->common.framebuffer_bpp + 7) / 8; 21 | fb_addr = fb->common.framebuffer_addr; 22 | ConsoleInitialized = true; 23 | } 24 | 25 | void ClearLine(void) 26 | { 27 | memzero(fb_addr+CursorPosY*ScreenWidth, CursorPosX); 28 | } 29 | 30 | void ClearScreen(void) 31 | { 32 | CursorPosX = 0; 33 | CursorPosY = 0; 34 | memzero(fb_addr, ScreenWidth * ScreenHeight * ScreenBPP); 35 | } 36 | 37 | void NewLineCheck() 38 | { 39 | if(CursorPosY >= ScreenHeight) 40 | { 41 | memcpy_fast((uint64)fb_addr, (uint64)fb_addr + ScreenWidth * font->height * ScreenBPP, ScreenWidth * (ScreenHeight-font->height) * ScreenBPP); 42 | memzero((uint64)fb_addr + (ScreenHeight - font->height) * ScreenWidth * ScreenBPP, font->height * ScreenWidth * ScreenBPP); 43 | CursorPosY = ScreenHeight - font->height; 44 | CursorPosX = 0; 45 | } 46 | } 47 | 48 | 49 | void printchcolor(uint8 c, uint32 fgcolor, uint32 bgcolor) 50 | { 51 | if(!ConsoleInitialized) return; 52 | if(c == 8) //Backslash 53 | { 54 | if(CursorPosX == 0) 55 | { 56 | CursorPosX = ScreenWidth - font->width; 57 | CursorPosY -= font->height; 58 | } else { 59 | CursorPosX -= font->width; 60 | } 61 | for(int i = CursorPosY; i < CursorPosY + font->height; i++) 62 | { 63 | VesaPutLine(CursorPosX, i, 0, font->width); 64 | } 65 | return; 66 | } else if(c == '\r') { 67 | ClearLine(); //Clear the current line 68 | CursorPosX = 0; 69 | return; 70 | } else if(c == '\n') { 71 | CursorPosX = 0; 72 | CursorPosY += font->height; 73 | NewLineCheck(); 74 | return; 75 | } 76 | uint32 broadcast_src[font->width]; //I dont know if there's a better name, but basically here we'll store the font, but instead of a bitmap we will store the color for each bit in succession 77 | uint8 *restrict glyph = &_binary_Font_psf_start + font->HeaderSize + (c > 0 && c < font->glyphs ? c : 0) * font->BytesPerGlyph; 78 | uint32 pixel_offset = CursorPosY * ScreenWidth + CursorPosX; 79 | for(int height = 0; height < font->height; height++) 80 | { 81 | uint64 actual_font = 0; 82 | if(font->width <= 8) actual_font = *glyph; 83 | else if(font->width <= 16) actual_font = *(uint16*)glyph; 84 | else if(font->width <= 32) actual_font = *(uint32*)glyph; //Unlikely. 85 | else actual_font = *(uint64*)glyph; //unlikely, to say the least. 86 | 87 | uint32 mask = 1 << (font->width - 1); 88 | 89 | for(int width = 0; width < font->width; width++, mask >>= 1) broadcast_src[width] = actual_font & mask ? fgcolor : bgcolor; 90 | 91 | memcpy_fast(fb_addr + pixel_offset, &broadcast_src, font->width * (fb->common.framebuffer_bpp / 8)); //Font width is multiplied by bpp / 8 because we converted each bit in the font to a bpp-bit integer 92 | //Note: Now i use this "broadcast" method for writing each line, because we're writing less times to the framebuffer.\ 93 | Before, we would do a 4-byte write for each bit in the bitmap of the character, and then the gfx card would read that and print it on the screen\ 94 | with what we're doing now, i send all the line in one burst with SSE / Avx instructions, which takes less time. I'd still like to find more optimizations, so this might not be\ 95 | left alone for a very long time i guess. 96 | 97 | pixel_offset += ScreenWidth; 98 | glyph += FontBytesPerLine; 99 | } 100 | CursorPosX += font->width; 101 | if(CursorPosX >= ScreenWidth) 102 | { 103 | printchcolor('\n', 0, 0); 104 | return; 105 | } 106 | NewLineCheck(); 107 | } 108 | 109 | void printch(uint8 c) 110 | { 111 | printchcolor(c, 0xFFFFFFFF, 0); //White fg on Black bg 112 | } 113 | 114 | void printf(string str, ...) 115 | { 116 | va_list args; 117 | va_start(args, str); 118 | for(int i = 0; str[i] != '\0'; i++) 119 | { 120 | if(str[i] == '%') 121 | { 122 | i++; 123 | if(str[i] == 'x') 124 | { 125 | print("0x"); 126 | string str = base_convert(va_arg(args, uint64), 16); 127 | print(str); 128 | free(str); 129 | } else if(str[i] == 's') { 130 | print(va_arg(args, string)); 131 | } else if(str[i] == 'c') { 132 | printch((char)va_arg(args, int)); //This shit ain't working\ 133 | in the kbd driver. WTF? 134 | } else if(str[i] == 'i') { 135 | string str = base_convert(va_arg(args, uint64), 10); 136 | print(str); 137 | free(str); 138 | } else if(str[i] == 'o') { 139 | string str = base_convert(va_arg(args, uint64), 8); 140 | print(str); 141 | free(str); 142 | } else if(str[i] == 'b') { 143 | string str = base_convert(va_arg(args, uint64), 2); 144 | print(str); 145 | free(str); 146 | } else if(str[i] == '%') { 147 | print('%'); //Good lord, it prints something i cant even recognize. just why. 148 | } 149 | } else { 150 | printch(str[i]); 151 | } 152 | } 153 | va_end(args); 154 | return; 155 | } 156 | 157 | void printcolor(string str, uint32 background, uint32 foreground) 158 | { 159 | uint16 length = strlen(str); 160 | for(uint16 i = 0;i 9 | 10 | void ConsoleInit(void); 11 | void ClearScreen(void); 12 | void printf(string ch, ...); 13 | void printcolor(string str, uint32 background, uint32 foreground); 14 | void printhexcolor(uint64 hex, uint32 backgroud, uint32 foreground); 15 | 16 | #endif -------------------------------------------------------------------------------- /kernel/src/console/fonts.h: -------------------------------------------------------------------------------- 1 | #ifndef FONTS_H 2 | #define FONTS_H 3 | 4 | #include "../drivers/vesa/vesa.h" 5 | #include "../string/types.h" 6 | #include "../grub/multiboot.h" 7 | 8 | #define FONT_MAGIC 0x864AB572 9 | 10 | extern char _binary_Font_psf_start; 11 | extern char _binary_Font_psf_end; 12 | extern char _binary_Font_psf_size; 13 | 14 | struct Font_t 15 | { 16 | uint32 magic; 17 | uint32 version; 18 | uint32 HeaderSize; 19 | uint32 flags; 20 | uint32 glyphs; //Amount of glyphs 21 | uint32 BytesPerGlyph; 22 | uint32 height; 23 | uint32 width; 24 | } __attribute__((packed)); 25 | 26 | #endif -------------------------------------------------------------------------------- /kernel/src/drivers/acpi/acpi.c: -------------------------------------------------------------------------------- 1 | #include "acpi.h" 2 | 3 | // checks for a given header and validates checksum 4 | int acpiCheckHeader(uint32 *ptr, char *sig) 5 | { 6 | if(memcmp(ptr, sig, 4) == 0) return 0; 7 | return -1; 8 | } 9 | 10 | int acpiEnable(void) 11 | { 12 | // check if acpi can be enabled 13 | if (acpi_pm_info->facp->SMI_CommandPort != 0 && acpi_pm_info->facp->AcpiEnable != 0) 14 | { 15 | outportb((uint32) acpi_pm_info->facp->SMI_CommandPort, acpi_pm_info->facp->AcpiEnable); // send acpi enable command 16 | // give 3 seconds time to enable acpi 17 | uint16 i = 0; 18 | for (; i<300; i++ ) 19 | { 20 | if ( (inportw((uint32) acpi_pm_info->facp->PM1aControlBlock) & acpi_pm_info->SCI_EN) & 1 ) break; 21 | if(acpi_pm_info->facp->PM1bControlBlock != 0) 22 | { 23 | if ( (inportw((uint32) acpi_pm_info->facp->PM1bControlBlock) & acpi_pm_info->SCI_EN) & 1 ) break; 24 | } 25 | sleep(10, SleepMili); //10 Miliseconds per each try 26 | } 27 | if (i<300) 28 | { 29 | AcpiEnablePWR_SLPBTN(); 30 | return 0; 31 | } else { 32 | printf("[INFO] Couldn't enable ACPI\n"); 33 | return -1; 34 | } 35 | } else { 36 | printf("[INFO] No known way to enable ACPI.\n"); 37 | return -1; 38 | } 39 | return 0; 40 | } 41 | 42 | void AcpiEnablePWR_SLPBTN() /*Acpi enable power and/or sleep button*/ 43 | { 44 | if((acpi_pm_info->facp->Flags & 1 << 4) /*PWRBTN*/ == 0) 45 | { 46 | //Enable 47 | outportw(acpi_pm_info->facp->PM1aEventBlock + acpi_pm_info->facp->PM1EventLength / 2, inportw(acpi_pm_info->facp->PM1aEventBlock + acpi_pm_info->facp->PM1EventLength / 2) | 1 << 8 /*PWRBTN_EN*/); 48 | if(acpi_pm_info->facp->PM1bEventBlock) 49 | { 50 | outportw(acpi_pm_info->facp->PM1bEventBlock + acpi_pm_info->facp->PM1EventLength / 2, inportw(acpi_pm_info->facp->PM1bEventBlock + acpi_pm_info->facp->PM1EventLength / 2) | 1 << 8 /*PWRBTN_EN*/); 51 | } 52 | } 53 | if((acpi_pm_info->facp->Flags & 1 << 5) /*SLPBTN*/ == 0) 54 | { 55 | //Enable 56 | outportw(acpi_pm_info->facp->PM1aEventBlock + acpi_pm_info->facp->PM1EventLength / 2, inportw(acpi_pm_info->facp->PM1aEventBlock + acpi_pm_info->facp->PM1EventLength / 2) | 1 << 9 /*SLPBTN_EN*/); 57 | if(acpi_pm_info->facp->PM1bEventBlock) 58 | { 59 | outportw(acpi_pm_info->facp->PM1bEventBlock + acpi_pm_info->facp->PM1EventLength / 2, inportw(acpi_pm_info->facp->PM1bEventBlock + acpi_pm_info->facp->PM1EventLength / 2) | 1 << 9 /*SLPBTN_EN*/); 60 | } 61 | } 62 | return; 63 | } 64 | 65 | int initAcpi(void) 66 | { 67 | AcpiInitNamespace(); 68 | uint32 *rsdp = acpiGetRSDPtr(); 69 | if(rsdp == 0) return -1; 70 | int stat = acpiParseRSDT(rsdp); //RSDP Contains a pointer to RSDT 71 | if(stat == 0) return -1; 72 | //AcpiDumpNamespace(); 73 | return acpiEnable(); 74 | } 75 | 76 | void AcpiSCIHandler(void) 77 | { 78 | if(inportw(acpi_pm_info->facp->PM1aEventBlock) & 1 << 8) //Has PWRBTN been pressed? 79 | { 80 | outportw(acpi_pm_info->facp->PM1aEventBlock, inportw(acpi_pm_info->facp->PM1aEventBlock) | 1 << 8); //Acknoledge 81 | shutdown(); 82 | } 83 | } 84 | 85 | void acpiPowerOff(void) 86 | { 87 | // SCI_EN is set to 1 if acpi shutdown is possible 88 | if(acpi_pm_info->SCI_EN == 0) return; 89 | struct AcpiNamespaceBlock_t *S5_Node = AcpiWalkNamespace("\\_S5_"); 90 | 91 | uint8 *S5_Data = S5_Node->addr+1; //Lets point directly to the info, we already know whats in the packet (hoping its a packet, i think it as School-R-Lea that said it could just as well be a method so...) 92 | 93 | uint8 *S5_SLPYP = kmalloc(2); //a,b 94 | if (*S5_Data == 0x0A) S5_Data++; // skip byteprefix 95 | S5_SLPYP[0] = *S5_Data; 96 | S5_Data++; 97 | if (*S5_Data == 0x0A) S5_Data++; // skip byteprefix 98 | S5_SLPYP[1] = *S5_Data; 99 | // send the shutdown command 100 | outportw(acpi_pm_info->facp->PM1aControlBlock, S5_SLPYP[0] << 10 | acpi_pm_info->SLP_EN); 101 | if(acpi_pm_info->facp->PM1bControlBlock != 0) 102 | { 103 | outportw(acpi_pm_info->facp->PM1bControlBlock, S5_SLPYP[1] << 10 | acpi_pm_info->SLP_EN); 104 | } 105 | } 106 | 107 | void acpiReboot(void) 108 | { 109 | if(acpi_pm_info->Revision >= 2 && acpi_pm_info->facp->Flags & (1 << 10)/*10th bit*/) 110 | { 111 | if(acpi_pm_info->facp->ResetReg.AddressSpace == 0) //The address is part of the memory space 112 | { 113 | uint8* resaddr = acpi_pm_info->facp->ResetReg.Address; 114 | id_vmmap(resaddr, 1024, 3); 115 | kill_pmm(); 116 | *resaddr = acpi_pm_info->facp->ResetValue; 117 | } else if(acpi_pm_info->facp->ResetReg.AddressSpace == 1) { //The address is part of the I/O space 118 | kill_pmm(); 119 | outportb(acpi_pm_info->facp->ResetReg.Address, acpi_pm_info->facp->ResetValue); 120 | } else if(acpi_pm_info->facp->ResetReg.AddressSpace == 2) { //The address is part of the PCI config space 121 | kill_pmm(); 122 | pciWrite8(acpi_pm_info->facp->ResetReg.Address, acpi_pm_info->facp->ResetValue); //NOTE:THIS IS WRONG.\ 123 | we should write to the bus number 0, etc etc. 124 | } 125 | } 126 | printf("ACPI reboot failed.\n"); 127 | return; 128 | } -------------------------------------------------------------------------------- /kernel/src/drivers/acpi/acpi.h: -------------------------------------------------------------------------------- 1 | #ifndef ACPI_H 2 | #define ACPI_H 3 | 4 | #include "../../string/types.h" 5 | #include "../../arch/x86/cpu.h" 6 | #include "../../console/console.h" 7 | 8 | struct GenericAddressStructure_t 9 | { 10 | uint8 AddressSpace; 11 | uint8 BitWidth; 12 | uint8 BitOffset; 13 | uint8 AccessSize; 14 | uint64 Address; 15 | } __attribute__((packed)); 16 | 17 | struct ACPI_SDTHeader_t 18 | { 19 | char Signature[4]; 20 | uint32 length; 21 | uint8 Revision; 22 | uint8 Checksum; 23 | char OEMID[6]; 24 | char OEMTableID[8]; 25 | uint32 OEMRevision; 26 | uint32 CreatorID; 27 | uint32 CreatorRevision; 28 | } __attribute__((packed)); 29 | 30 | struct ACPI_Sx_t 31 | { 32 | uint16 SLPYPa; 33 | uint16 SLPYPb; 34 | } __attribute__((packed)); 35 | 36 | 37 | struct acpi_pm_info_t 38 | { 39 | uint8 Revision; 40 | uint32 cpus; 41 | struct FACP *facp; 42 | struct MADT *madt; 43 | struct HPET *hpet; 44 | struct LAPIC **lapic; 45 | struct IOAPIC **ioapic; 46 | struct LAPIC_OVERRIDE *lapic_override; 47 | uint16 SLP_EN; 48 | uint16 SCI_EN; 49 | struct ACPI_Sx_t ACPI_S5; 50 | struct ACPI_Sx_t ACPI_S4; 51 | struct ACPI_Sx_t ACPI_S3; 52 | struct ACPI_Sx_t ACPI_S2; 53 | struct ACPI_Sx_t ACPI_S1; 54 | struct ACPI_Sx_t ACPI_S0; 55 | } __attribute__((packed)); 56 | 57 | struct acpi_pm_info_t *acpi_pm_info; 58 | 59 | int acpiEnable(void); 60 | int initAcpi(void); 61 | void AcpiSCIHandler(void); 62 | void acpiReboot(void); 63 | void acpiPowerOff(void); 64 | 65 | //NOTE: These are declared here, bc if not gcc will throw an "incomplete type" error when compiling 66 | #include "interpreter/namespace.h" 67 | #include "interpreter/opcode.h" 68 | #include "../hpet/hpet.h" 69 | #include "madt.h" 70 | #include "fadt.h" 71 | #include "rsdt.h" 72 | #include "dsdt.h" 73 | #include "../pcie/pcie.h" 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /kernel/src/drivers/acpi/dsdt.c: -------------------------------------------------------------------------------- 1 | #include "dsdt.h" 2 | 3 | //this func also supports SSDT parsing, since they're pretty much the same structure 4 | 5 | bool acpiParseDSDT(uint32 *ptr) 6 | { 7 | char* packagePtr = ((char*)ptr + 36); //The first 36 bytes are not aml encoded, but normal DSDT header info. 8 | int dsdtLength = (*(uint32*)((char*)ptr + 4)) - 36; 9 | 10 | AcpiEvalAML(packagePtr, dsdtLength); //Lets parse this table! 11 | 12 | setRTCenturyReg(acpi_pm_info->facp->Century); 13 | acpi_pm_info->SLP_EN = 1<<13; 14 | acpi_pm_info->SCI_EN = 1; 15 | return true; //Assuming its ok. Might want to do a check (if so, how?). 16 | } -------------------------------------------------------------------------------- /kernel/src/drivers/acpi/dsdt.h: -------------------------------------------------------------------------------- 1 | #ifndef DSDT_H 2 | #define DSDT_H 3 | 4 | #include "acpi.h" 5 | 6 | bool acpiParseSx(char *ptr, struct ACPI_Sx_t *Sx); 7 | bool acpiParseDSDT(uint32 *ptr); 8 | 9 | #endif -------------------------------------------------------------------------------- /kernel/src/drivers/acpi/fadt.c: -------------------------------------------------------------------------------- 1 | #include "fadt.h" 2 | 3 | bool acpiParseFacp(uint32 *ptr) 4 | { 5 | bool parsed_S5 = false; 6 | 7 | struct FACP *facp = (struct FACP*) ((uint64)*ptr + 0xFFFF800000000000); 8 | if(acpi_pm_info->Revision > 1) facp->DSDT = facp->X_Dsdt; 9 | 10 | acpi_pm_info->facp = kmalloc(sizeof(struct FACP)); 11 | memcpy_fast(acpi_pm_info->facp, facp, sizeof(struct FACP)); 12 | //vmmap(facp->DSDT , facp->DSDT + 0xFFFF800000000000, 8*1024, 3); 13 | 14 | if (acpiCheckHeader(facp->DSDT + 0xFFFF800000000000, "DSDT") == 0) 15 | { 16 | parsed_S5 = acpiParseDSDT(facp->DSDT + 0xFFFF800000000000); 17 | } else { 18 | printf("[INFO] DSDT invalid\n"); 19 | } 20 | 21 | return parsed_S5; 22 | } -------------------------------------------------------------------------------- /kernel/src/drivers/acpi/fadt.h: -------------------------------------------------------------------------------- 1 | #ifndef FADT_H 2 | #define FADT_H 3 | 4 | #include "acpi.h" 5 | 6 | struct FACP 7 | { 8 | struct ACPI_SDTHeader_t h; 9 | uint32 FirmwareCtrl; 10 | uint32 DSDT; 11 | 12 | // field used in ACPI 1.0; no longer in use, for compatibility only 13 | uint8 Reserved; 14 | 15 | uint8 PreferredPowerManagementProfile; 16 | uint16 SCI_Interrupt; 17 | uint32 SMI_CommandPort; 18 | uint8 AcpiEnable; 19 | uint8 AcpiDisable; 20 | uint8 S4BIOS_REQ; 21 | uint8 PSTATE_Control; 22 | uint32 PM1aEventBlock; 23 | uint32 PM1bEventBlock; 24 | uint32 PM1aControlBlock; 25 | uint32 PM1bControlBlock; 26 | uint32 PM2ControlBlock; 27 | uint32 PMTimerBlock; 28 | uint32 GPE0Block; 29 | uint32 GPE1Block; 30 | uint8 PM1EventLength; 31 | uint8 PM1ControlLength; 32 | uint8 PM2ControlLength; 33 | uint8 PMTimerLength; 34 | uint8 GPE0Length; 35 | uint8 GPE1Length; 36 | uint8 GPE1Base; 37 | uint8 CStateControl; 38 | uint16 WorstC2Latency; 39 | uint16 WorstC3Latency; 40 | uint16 FlushSize; 41 | uint16 FlushStride; 42 | uint8 DutyOffset; 43 | uint8 DutyWidth; 44 | uint8 DayAlarm; 45 | uint8 MonthAlarm; 46 | uint8 Century; 47 | 48 | // reserved in ACPI 1.0; used since ACPI 2.0+ 49 | uint16 BootArchitectureFlags; 50 | 51 | uint8 Reserved2; 52 | uint32 Flags; 53 | 54 | // 12 byte structure; see below for details 55 | struct GenericAddressStructure_t ResetReg; 56 | 57 | uint8 ResetValue; 58 | uint8 Reserved3[3]; 59 | 60 | // 64bit pointers - Available on ACPI 2.0+ 61 | uint64 X_FirmwareControl; 62 | uint64 X_Dsdt; 63 | 64 | struct GenericAddressStructure_t X_PM1aEventBlock; 65 | struct GenericAddressStructure_t X_PM1bEventBlock; 66 | struct GenericAddressStructure_t X_PM1aControlBlock; 67 | struct GenericAddressStructure_t X_PM1bControlBlock; 68 | struct GenericAddressStructure_t X_PM2ControlBlock; 69 | struct GenericAddressStructure_t X_PMTimerBlock; 70 | struct GenericAddressStructure_t X_GPE0Block; 71 | struct GenericAddressStructure_t X_GPE1Block; 72 | } __attribute__((packed)); 73 | 74 | bool acpiParseFacp(uint32 *ptr); 75 | 76 | #endif -------------------------------------------------------------------------------- /kernel/src/drivers/acpi/interpreter/eval.c: -------------------------------------------------------------------------------- 1 | #include "eval.h" 2 | 3 | /* 4 | For reference on AML Encodings, look at uefi.org/sites/default/files/resources/ACPI_6_3_final_Jan30.pdf at section 20 5 | */ 6 | 7 | void /*for now void, may be an int*/ AcpiEvalAMLCustomRoot(void *CRoot, uint8 *ptr, uint32 size) 8 | { 9 | struct AcpiNamespaceBlock_t *current_node = CRoot; 10 | for(int i = 0; i < size; i++, ptr++) 11 | { 12 | if(AML_CheckIsScope(ptr)) 13 | { 14 | struct AcpiNamespaceBlock_t *block = kmalloc(sizeof(struct AcpiNamespaceBlock_t)); 15 | memzero(block, sizeof(struct AcpiNamespaceBlock_t)); 16 | 17 | uint8 PkgLeadByte = (*(ptr+1) >> 6) + 1; ////This is just the amount of extra pkgSize, actually. >> 6 to get the last 2 bits 18 | 19 | string name = AML_GetName(ptr+PkgLeadByte+1); 20 | block->name = name; 21 | 22 | block->type = AML_ScopeOp; 23 | block->size = *(ptr+1)-1; 24 | block->addr = ptr+PkgLeadByte+4+1; //Lets point directly to the data. might change. 25 | 26 | AcpiCreateNamespaceBlock(current_node, block); 27 | AcpiEvalAMLCustomRoot(block, block->addr, block->size); 28 | 29 | ptr += block->size+1; 30 | i += block->size+1; 31 | } else if(AML_CheckIsDevice(ptr)) { 32 | struct AcpiNamespaceBlock_t *block = kmalloc(sizeof(struct AcpiNamespaceBlock_t)); 33 | memzero(block, sizeof(struct AcpiNamespaceBlock_t)); 34 | 35 | uint8 PkgLeadByte = (*(ptr+2) >> 6) + 1; 36 | 37 | string name = AML_GetName(ptr+PkgLeadByte+2); 38 | block->name = name; 39 | 40 | block->type = AML_DeviceOp; 41 | block->size = *(ptr+2)-1; 42 | block->addr = ptr+PkgLeadByte+4+2; //Lets point directly to the data. might change. 43 | 44 | AcpiCreateNamespaceBlock(current_node, block); 45 | AcpiEvalAMLCustomRoot(block, block->addr, block->size); 46 | 47 | ptr += block->size+2;//two bytes for the type 48 | i += block->size+2; 49 | } else if(AML_CheckIsPackage(ptr)) { //We may have a package inside this package. Search / think how to handle it. 50 | struct AcpiNamespaceBlock_t *block = kmalloc(sizeof(struct AcpiNamespaceBlock_t)); 51 | memzero(block, sizeof(struct AcpiNamespaceBlock_t)); 52 | 53 | uint8 PkgLeadByte = (*(ptr+6) >> 6) + 1; 54 | 55 | string name = AML_GetName(ptr+1); 56 | block->name = name; 57 | 58 | block->type = AML_PackageOp; 59 | block->size = *(ptr+6)-1; 60 | block->addr = ptr+6+PkgLeadByte; //We first point to the amount of values in the package. 61 | 62 | AcpiCreateNamespaceBlock(current_node, block); 63 | 64 | ptr += block->size+6;//The size of the NameOp 65 | i += block->size+6; 66 | } else if(AML_CheckIsMethod(ptr)) { //We also need to find a way of executing whats inside this 67 | struct AcpiNamespaceBlock_t *block = kmalloc(sizeof(struct AcpiNamespaceBlock_t)); 68 | memzero(block, sizeof(struct AcpiNamespaceBlock_t)); 69 | 70 | uint8 PkgLeadByte = (*(ptr+1) >> 6) + 1; 71 | 72 | string name = AML_GetName(ptr+PkgLeadByte+1); 73 | block->name = name; 74 | 75 | block->type = AML_MethodOp; 76 | block->size = *(ptr+1)-1; 77 | block->addr = ptr+1+PkgLeadByte+4+AML_GetMethodArgCount(ptr)+1; //Base + Op offset + Length offset + Name offset + Argument_count offset + Method Flag offset 78 | 79 | AcpiCreateNamespaceBlock(current_node, block); 80 | 81 | ptr += block->size+1; 82 | i += block->size+1; 83 | } 84 | } 85 | } 86 | 87 | void AcpiEvalAML(uint8 *ptr, uint32 size) 88 | { 89 | void *root = AcpiWalkNamespace("\\"); 90 | AcpiEvalAMLCustomRoot(root, ptr, size); 91 | } -------------------------------------------------------------------------------- /kernel/src/drivers/acpi/interpreter/eval.h: -------------------------------------------------------------------------------- 1 | #ifndef ACPI_EVAL_H 2 | #define ACPI_EVAL_H 3 | 4 | #include "../acpi.h" 5 | #include "opcode.h" 6 | #include "namespace.h" 7 | 8 | void AcpiEvalAML(uint8 *ptr, uint32 size); 9 | 10 | #endif -------------------------------------------------------------------------------- /kernel/src/drivers/acpi/interpreter/namespace.c: -------------------------------------------------------------------------------- 1 | #include "namespace.h" 2 | 3 | struct AcpiNamespaceBlock_t *root; 4 | 5 | void AcpiInitNamespace(void) 6 | { 7 | root = kmalloc(sizeof(struct AcpiNamespaceBlock_t)); 8 | memzero(root, sizeof(struct AcpiNamespaceBlock_t)); 9 | root->name = kmalloc(2); 10 | strncpy(root->name, "\\\0", 2); 11 | root->full_name = kmalloc(2); 12 | strncpy(root->full_name, "\\\0", 2); 13 | } 14 | 15 | void *AcpiWalkNamespaceCustomRoot(void *CRoot, string destination) 16 | { 17 | struct AcpiNamespaceBlock_t *current_node = CRoot; //Custom Root 18 | if(strEql(current_node->full_name, destination)) return current_node; 19 | struct AcpiNamespaceBlockChildList_t *current_childs = current_node->childs; 20 | 21 | for(int i = 0; i < current_node->child_amount; i++, current_childs = current_childs->next) 22 | { 23 | void *ptr = AcpiWalkNamespaceCustomRoot(current_childs->child_ptr, destination); 24 | if(ptr) return ptr; 25 | } 26 | return 0; //DESTINATION DOES NOT EXIST IN THE NAMESPACE! 27 | } 28 | 29 | void *AcpiWalkNamespace(string destination) 30 | { 31 | return AcpiWalkNamespaceCustomRoot(root, destination); //We always start in the root 32 | } 33 | 34 | void AcpiCreateNamespaceBlock(struct AcpiNamespaceBlock_t *parent, struct AcpiNamespaceBlock_t *block) 35 | { 36 | struct AcpiNamespaceBlock_t *current_node = parent; 37 | current_node->child_amount++; 38 | 39 | uint32 n = strlen(current_node->full_name); 40 | block->full_name = kmalloc(strlen(current_node->full_name) + strlen(block->name)+1); 41 | 42 | memcpy_fast(block->full_name, current_node->full_name, n); 43 | if(current_node != root) {char dot = '.'; strncpy(block->full_name+n, &dot, 1);n++;} 44 | memcpy_fast(block->full_name+n, block->name, 4); 45 | block->full_name[n+4] = '\0'; 46 | block->parent = current_node; 47 | 48 | struct AcpiNamespaceBlockChildList_t *current_childs; 49 | if(current_node->child_amount > 1) 50 | { 51 | current_childs = current_node->last_child; 52 | current_childs->next = kmalloc(8); 53 | current_node->last_child = current_childs = current_childs->next; 54 | } else { 55 | current_node->childs = kmalloc(8); 56 | current_node->last_child = current_node->childs; 57 | current_childs = current_node->childs; 58 | } 59 | current_childs->child_ptr = block; 60 | 61 | return; 62 | } 63 | 64 | void AcpiDeleteNamespaceBlockCustomRoot(void *CRoot) 65 | { 66 | struct AcpiNamespaceBlock_t *current_node = CRoot; 67 | struct AcpiNamespaceBlockChildList_t *current_childs = current_node->childs; 68 | for(int i = 0; i < current_node->child_amount; i++, current_childs = current_childs->next) 69 | { 70 | AcpiDeleteNamespaceBlockCustomRoot(current_childs->child_ptr); 71 | } 72 | free(current_childs); 73 | free(current_node->parent); 74 | memzero(current_node, sizeof(struct AcpiNamespaceBlock_t)); 75 | return; 76 | } 77 | 78 | void AcpiDeleteNamespaceBlock(string node) 79 | { 80 | struct AcpiNamespaceBlock_t *current_node = AcpiWalkNamespace(node); 81 | struct AcpiNamespaceBlock_t *parent_node = current_node->parent; 82 | struct AcpiNamespaceBlockChildList_t *current_childs = current_node->childs, *prev_child = 0; 83 | 84 | for(int i = 0; i < parent_node->child_amount; i++, current_childs = current_childs->next) 85 | { 86 | if(current_childs->child_ptr == node) 87 | { 88 | AcpiDeleteNamespaceBlockCustomRoot(current_childs->child_ptr); 89 | if(prev_child == 0) 90 | { 91 | if(i < current_node->child_amount) current_node->childs = current_childs->next; 92 | else {current_node->childs = 0; current_node->last_child = 0;} 93 | } else { 94 | if(i < current_node->child_amount) prev_child->next = current_childs->next; 95 | else {prev_child->next = 0; current_node->last_child = prev_child;} 96 | } 97 | parent_node->child_amount--; 98 | memzero(current_childs->child_ptr, sizeof(struct AcpiNamespaceBlock_t)); 99 | break; 100 | } 101 | } 102 | 103 | return; 104 | } 105 | 106 | void AcpiDumpCustomRoot(void *root) 107 | { 108 | struct AcpiNamespaceBlock_t *current_node = root; 109 | struct AcpiNamespaceBlockChildList_t *current_childs = current_node->childs; 110 | for(int i = 0; i < current_node->child_amount; i++, current_childs = current_childs->next) 111 | { 112 | AcpiDumpCustomRoot(current_childs->child_ptr); 113 | } 114 | } 115 | 116 | void AcpiDumpNamespace(void) 117 | { 118 | AcpiDumpCustomRoot(root); 119 | } -------------------------------------------------------------------------------- /kernel/src/drivers/acpi/interpreter/namespace.h: -------------------------------------------------------------------------------- 1 | #ifndef ACPI_NAMESPACE_H 2 | #define ACPI_NAMESPACE_H 3 | 4 | #include "../../../string/types.h" 5 | #include "../../../string/string.h" 6 | #include "../../../memory/pmm.h" 7 | #include "../../../console/console.h" 8 | #include "../acpi.h" 9 | #include "opcode.h" 10 | #include "eval.h" 11 | 12 | struct AcpiNamespaceBlockChildList_t //FUCK. THAT. NAME. Thanks, i hate it. 13 | { 14 | struct AcpiNamespaceBlockChildList_t *next; 15 | uint64 child_ptr; 16 | } __attribute__ ((packed)); 17 | 18 | struct AcpiNamespaceBlock_t 19 | { 20 | uint16 child_amount; 21 | uint64 last_child; 22 | struct AcpiNamespaceBlockChildList_t *childs; 23 | uint64 *parent; 24 | string name; //i.e PCI0 25 | string full_name; //i.e _SB_.PCI0 26 | uint16 type; //Most likely a packet, method, scope, data or device. Well use the normal PacketOp, MethodOp etc for codes. 27 | uint64 size; 28 | uint8 *addr; //Where Acpi Machine code is located (probably DSDT or SSDT, and since it is reserved memory, there's no need to allocate memory and memcpy the AML) 29 | } __attribute__((packed)); 30 | 31 | void AcpiInitNamespace(void); //Create the root. 32 | 33 | void *AcpiWalkNamespace(string destination); //Destination is what we're searching. This will return a pointer what we were searching 34 | void AcpiCreateNamespaceBlock(struct AcpiNamespaceBlock_t *parent, struct AcpiNamespaceBlock_t *block); //Self explaining 35 | void AcpiDeleteNamespaceBlock(string node); //self explanatory 36 | 37 | void AcpiDumpNamespace(void); 38 | uint8 *AcpiGetAml(void); 39 | 40 | #endif -------------------------------------------------------------------------------- /kernel/src/drivers/acpi/interpreter/opcode.h: -------------------------------------------------------------------------------- 1 | #ifndef ACPI_OPCODE_H 2 | #define ACPI_OPCODE_H 3 | 4 | #include "../../../string/types.h" 5 | #include "../../../string/string.h" 6 | #include "../../../memory/pmm.h" 7 | #include "../../../console/console.h" 8 | 9 | #define AML_ZeroOp 0 10 | #define AML_OneOp 1 11 | #define AML_AliasOp 6 12 | #define AML_NameOp 8 13 | #define AML_BytePrefix 0xA 14 | #define AML_WordPrefix 0xB 15 | #define AML_DwordPrefix 0xC 16 | #define AML_StringPrefix 0xD 17 | #define AML_QwordPrefix 0xE 18 | #define AML_ScopeOp 0x10 19 | #define AML_BufferOp 0x11 20 | #define AML_PackageOp 0x12 21 | #define AML_VarPackageOp 0x13 22 | #define AML_MethodOp 0x14 23 | #define AML_DualnamePrefix 0x2E // '.' 24 | #define AML_MultinamePrefix 0x2F // '/' 25 | #define AML_IsDigitChar(x) (x >= 0x30 && x <= 0x39) // '0' - '9' 26 | #define AML_IsNameChar(x) (x >= 0x41 && x <= 0x5A) // 'A' - 'Z' 27 | #define AML_ExtOpPrefix 0x5B // '[' 28 | #define AML_DeviceOp 0x5B82 29 | #define AML_RootChar 0x5C // '\' 30 | #define AML_ParentPrefixChar 0x5E // '^' 31 | #define AML_NameChar 0x5F // '_' 32 | #define AML_Local0Op 0x60 33 | #define AML_Local1Op 0x61 34 | #define AML_Local2Op 0x62 35 | #define AML_Local3Op 0x63 36 | #define AML_Local4Op 0x64 37 | #define AML_Local5Op 0x65 38 | #define AML_Local6Op 0x66 39 | #define AML_Local7Op 0x67 40 | #define AML_Arg0Op 0x68 41 | #define AML_Arg1Op 0x69 42 | #define AML_Arg2Op 0x6A 43 | #define AML_Arg3Op 0x6B 44 | #define AML_Arg4Op 0x6C 45 | #define AML_Arg5Op 0x6D 46 | #define AML_Arg6Op 0x6E 47 | #define AML_StoreOp 0x70 48 | #define AML_RefOfOp 0x71 49 | #define AML_AddOp 0x72 50 | #define AML_ConcatOp 0x73 51 | #define AML_SubstractOp 0x74 52 | #define AML_IncrementOp 0x75 53 | #define AML_DecrementOp 0x76 54 | #define AML_MultiplyOp 0x77 55 | #define AML_DivideOp 0x78 56 | #define AML_ShiftLeftOp 0x79 57 | #define AML_ShiftRightOp 0x7A 58 | #define AML_AndOp 0x7B 59 | #define AML_NandOp 0x7C 60 | #define AML_OrOp 0x7D 61 | #define AML_NorOp 0x7E 62 | #define AML_XorOp 0x7F 63 | #define AML_NotOp 0x80 64 | #define AML_FindSetLeftBitOp 0x81 65 | #define AML_FindSetRightBitOp 0x82 66 | #define AML_DerefOfOp 0x83 67 | #define AML_ConcatResOp 0x84 68 | #define AML_ModOp 0x85 69 | #define AML_NotifyOp 0x86 70 | #define AML_SizeofOp 0x87 71 | #define AML_IndexOp 0x88 72 | #define AML_MatchOp 0x89 73 | #define AML_CreateDwordFieldOp 0x8A 74 | #define AML_CreateWordFieldOp 0x8B 75 | #define AML_CreateByteFieldOp 0x8C 76 | #define AML_CreateBitFieldOp 0x8D 77 | #define AML_TypeOp 0x8E 78 | #define AML_CreateQwordFieldOp 0x8F 79 | #define AML_LandOp 0x90 80 | #define AML_LorOp 0x91 81 | #define AML_LnotOp 0x92 82 | #define AML_LNotEqualOp 0x9293 83 | #define AML_LLessEqualOp 0x9294 84 | #define AML_LGreaterEqualOp 0x9295 85 | #define AML_LEqeualOp 0x93 86 | #define AML_LGreaterOp 0x94 87 | #define AML_LLessOp 0x95 88 | #define AML_ToBufferOp 0x96 89 | #define AML_ToDecimalStringOp 0x97 90 | #define AML_ToHexStringOp 0x98 91 | #define AML_ToIntegerOp 0x99 92 | #define AML_ToStringOp 0x9C 93 | #define AML_CopyObjectOp 0x9D 94 | #define AML_MidOp 0x9E 95 | #define AML_ContinueOp 0x9F 96 | #define AML_IfOp 0xA0 97 | #define AML_ElseOp 0xA1 98 | #define AML_WhileOp 0xA2 99 | #define AML_NoopOp 0xA3 100 | #define AML_ReturnOp 0xA4 101 | #define AML_BreakOp 0xA5 102 | #define AML_BreakPointOp 0xCC 103 | #define AML_OnesOp 0xFF 104 | 105 | static inline string AML_GetName(uint8 *x) 106 | { 107 | string ret = kmalloc(4); 108 | int top = 4, retidx = 0; 109 | for(int i = 0; i < top; i++) //Names are always 4 characters 110 | { 111 | if(x[i] == AML_RootChar || x[i] == AML_ParentPrefixChar || x[i] == AML_DualnamePrefix || x[i] == AML_MultinamePrefix) { top++; continue;} 112 | if(!(AML_IsDigitChar(x[i]) || AML_IsNameChar(x[i]) || x[i] == AML_RootChar || x[i] == AML_ParentPrefixChar || x[i] == AML_NameChar)) return 0; 113 | ret[retidx++] = (char)x[i]; 114 | } 115 | ret[retidx] = '\0'; 116 | return ret; 117 | } 118 | 119 | static inline bool AML_CheckIsName(uint8 *x) 120 | { 121 | int top = 4; 122 | for(int i = 0; i < top; i++) //Names are always 4 characters 123 | { 124 | if(x[i] == AML_RootChar || x[i] == AML_ParentPrefixChar || x[i] == AML_DualnamePrefix || x[i] == AML_MultinamePrefix) { top++; continue;} 125 | if(!(AML_IsDigitChar(x[i]) || AML_IsNameChar(x[i]) || x[i] == AML_NameChar)) return false; 126 | } 127 | return true; 128 | } 129 | 130 | static inline bool AML_CheckIsScope(uint8 *ptr) 131 | { 132 | uint8 PkgLeadByte = (*(ptr+1) >> 6) + 1; //>> 6 to get the last 2 bits 133 | return *ptr == AML_ScopeOp && AML_CheckIsName(ptr+PkgLeadByte+1); 134 | } 135 | 136 | static inline bool AML_CheckIsDevice(uint8 *ptr) 137 | { 138 | uint8 PkgLeadByte = (*(ptr+2) >> 6) + 1; //>> 6 to get the last 2 bits 139 | return *ptr == (AML_DeviceOp >> 8) && *(ptr+1) == (AML_DeviceOp & 0xFF) && AML_CheckIsName(ptr+PkgLeadByte+2+1); 140 | } 141 | 142 | static inline bool AML_CheckIsPackage(uint8 *ptr) 143 | { 144 | return *ptr == AML_NameOp && AML_CheckIsName(ptr+1) && *(ptr+5) == AML_PackageOp; 145 | } 146 | 147 | static inline bool AML_CheckIsMethod(uint8 *ptr) 148 | { 149 | uint8 PkgLeadByte = (*(ptr+1) >> 6) + 1; //>> 6 to get the last 2 bits 150 | return *ptr == AML_MethodOp && AML_CheckIsName(ptr+PkgLeadByte+1); 151 | } 152 | 153 | static inline int AML_GetMethodArgCount(uint8 *ptr) 154 | { 155 | uint8 PkgLeadByte = (*(ptr+1) >> 6) + 1; //>> 6 to get the last 2 bits 156 | return (*(ptr+1+PkgLeadByte+4)) & 7; //bits 0-3 represent the amount of arguments for this function 157 | } 158 | 159 | #endif -------------------------------------------------------------------------------- /kernel/src/drivers/acpi/madt.c: -------------------------------------------------------------------------------- 1 | #include "madt.h" 2 | 3 | void acpiParseMadt(uint32 *ptr) 4 | { 5 | acpi_pm_info->madt = ((uint32)(struct MADT*)*ptr) + 0xFFFF800000000000; 6 | uint8 *start = (uint8*)&acpi_pm_info->madt->rest_fields; 7 | uint64 end = (uint64)start + (acpi_pm_info->madt->Length - sizeof(struct MADT)); 8 | id_vmmap(acpi_pm_info->madt->local_controller_addr, 0x10000, 3); 9 | id_vmmap(0xFEC00000, 0x2000, 3); 10 | bool finished = false; 11 | int cpus = 0, ioapics = 0; 12 | acpi_pm_info->cpus = 0; 13 | int entries = end - (uint64)start; 14 | void *new_addr = 0; 15 | while(entries-- && !finished) 16 | { 17 | switch(*start) 18 | { 19 | case 0: ; 20 | struct LAPIC *lapic = (struct LAPIC*) start; 21 | if(!lapic->length) 22 | { 23 | finished = true; 24 | break; 25 | } 26 | if(cpus == 0) 27 | { 28 | lapicEnable(lapic->flags); 29 | } 30 | 31 | new_addr = kmalloc((cpus+1)*8); //Each addr is 8 bytes wide 32 | memcpy_fast(new_addr, acpi_pm_info->lapic, cpus * sizeof(struct LAPIC)); 33 | acpi_pm_info->lapic = new_addr; 34 | 35 | acpi_pm_info->lapic[cpus] = kmalloc(sizeof(struct LAPIC)); 36 | memcpy_fast(acpi_pm_info->lapic[cpus++], lapic, sizeof(struct LAPIC)); 37 | 38 | start += lapic->length; 39 | break; 40 | case 1: ; 41 | struct IOAPIC *ioapic = (struct IOAPIC*)start; 42 | if(!ioapic->length) 43 | { 44 | finished = true; 45 | break; 46 | } 47 | id_vmmap(ioapic->address, 1, 3); 48 | ioapicEnable(ioapic->address, 0); 49 | 50 | new_addr = kmalloc((ioapics+1)*8); //Each addr is 8 bytes wide 51 | memcpy_fast(new_addr, acpi_pm_info->ioapic, ioapics * sizeof(struct IOAPIC)); 52 | acpi_pm_info->ioapic = new_addr; 53 | 54 | acpi_pm_info->ioapic[ioapics] = kmalloc(sizeof(struct IOAPIC)); 55 | memcpy_fast(acpi_pm_info->ioapic[ioapics++], ioapic, sizeof(struct IOAPIC)); 56 | start += ioapic->length; 57 | break; 58 | case 2: ; 59 | struct APIC_ISO *apic_iso = (struct APIC_ISO*)start; 60 | if(!apic_iso->length) 61 | { 62 | finished = true; 63 | break; 64 | } 65 | ioapicMapIrq(apic_iso->irq_src, apic_iso->interrupt, 0); 66 | start += apic_iso->length; 67 | break; 68 | case 3: ; 69 | struct IOAPIC_NMI *ioapic_nmi = (struct IOAPIC_NMI*)start; 70 | if(!ioapic_nmi->length) 71 | { 72 | finished = true; 73 | break; 74 | } 75 | IOApicConfigureNMI(ioapic_nmi->GSI, ioapic_nmi->flags); 76 | start += ioapic_nmi->length; 77 | break; 78 | case 4: ; 79 | struct LAPIC_NMI *lapic_nmi = (struct LAPIC_NMI*)start; 80 | if(!lapic_nmi->length) 81 | { 82 | finished = true; 83 | break; 84 | } 85 | lapicConfigureNMI(lapic_nmi->lint, lapic_nmi->flags); 86 | start += lapic_nmi->length; 87 | break; 88 | case 5: ; 89 | struct LAPIC_OVERRIDE *lapic_ovr = (struct LAPIC_OVERRIDE*)start; 90 | if(!lapic_ovr->length) 91 | { 92 | finished = true; 93 | break; 94 | } 95 | acpi_pm_info->lapic_override = lapic_ovr; 96 | start += lapic_ovr->length; 97 | break; 98 | default: 99 | start++; 100 | break; 101 | } 102 | } 103 | acpi_pm_info->cpus = cpus; 104 | //lapicTimerStart(); 105 | } -------------------------------------------------------------------------------- /kernel/src/drivers/acpi/madt.h: -------------------------------------------------------------------------------- 1 | #ifndef MADT_H 2 | #define MADT_H 3 | 4 | #include "acpi.h" 5 | #include "../../arch/x86/lapic.h" 6 | #include "../../arch/x86/ioapic.h" 7 | 8 | struct MADT 9 | { 10 | char Signature[4]; 11 | uint32 Length; 12 | uint8 revision; 13 | uint8 checksum; 14 | char OEMID[6]; 15 | char OEMable_id[8]; 16 | uint32 OEMRevision; 17 | uint32 CreatorID; 18 | uint32 CreatorREV; 19 | uint32 local_controller_addr; 20 | uint32 flags; 21 | uint8 rest_fields; 22 | }__attribute__((packed)); 23 | 24 | struct LAPIC 25 | { 26 | uint8 type; 27 | uint8 length; 28 | uint8 processor_id; 29 | uint8 apic_id; 30 | uint32 flags; 31 | } __attribute__((packed)); 32 | 33 | struct IOAPIC 34 | { 35 | uint8 type; 36 | uint8 length; 37 | uint8 ioapic_id; 38 | uint8 reserved; 39 | uint32 address; 40 | uint32 global_sib; //System interrupt base 41 | } __attribute__((packed)); 42 | 43 | struct APIC_ISO //Interrupt source override 44 | { 45 | uint8 type; 46 | uint8 length; 47 | uint8 bus_src; 48 | uint8 irq_src; 49 | uint32 interrupt; 50 | uint16 flags; 51 | } __attribute__((packed)); 52 | 53 | struct IOAPIC_NMI 54 | { 55 | uint8 type; 56 | uint8 length; 57 | uint16 flags; 58 | uint32 GSI; //Global_System_Interrupt 59 | } __attribute__((packed)); 60 | 61 | struct LAPIC_NMI 62 | { 63 | uint8 type; 64 | uint8 length; 65 | uint8 processor_id; 66 | uint16 flags; 67 | uint8 lint; 68 | } __attribute__((packed)); 69 | 70 | struct LAPIC_OVERRIDE 71 | { 72 | uint8 type; 73 | uint8 length; 74 | uint16 reserved; 75 | uint64 addr; 76 | } __attribute__((packed)); 77 | 78 | void acpiParseMadt(uint32 *ptr); 79 | 80 | #endif -------------------------------------------------------------------------------- /kernel/src/drivers/acpi/rsdp.c: -------------------------------------------------------------------------------- 1 | #include "rsdp.h" 2 | 3 | uint32 *acpiCheckRSDPtr(uint32 *ptr) 4 | { 5 | char *sig = "RSD PTR"; 6 | struct RSDP *rsdp = (struct RSDP*) ptr; 7 | volatile uint8 *bptr; 8 | uint8 check = 0; 9 | uint32 i; 10 | if(memcmp(sig, rsdp, 7) == 0) 11 | { 12 | // check RSPD's checksum 13 | bptr = (uint8*) ptr; 14 | for (i=0; iRevision = rsdp->Revision; 33 | if (rsdp->Revision == 0) 34 | { 35 | return (uint32*) rsdp->RsdtAddress; 36 | } else { 37 | struct RSDP2 *rsdp2 = (struct RSDP2*) ptr; 38 | return (uint32*) rsdp2->XsdtAddress; 39 | } 40 | } 41 | } 42 | return NULL; 43 | } 44 | 45 | uint32 *acpiGetRSDPtr(void) 46 | { 47 | uint32 *rsdp = NULL; 48 | acpi_pm_info = kmalloc(sizeof(struct acpi_pm_info_t)); 49 | 50 | //Try using rsdp given by multiboot 51 | rsdp = ((struct multiboot_tag_acpi*)get_mboot_info(multiboot_tag_TYPE_ACPI_OLD))->rsdp; //It does not really matter if we use type old or type new 52 | if(acpiCheckRSDPtr(rsdp) != NULL) 53 | { 54 | return acpiCheckRSDPtr(rsdp); 55 | } 56 | 57 | //Maybe multiboot is not good enough. Lets try to search it ourselves (and may just be usless as well, but whatever) 58 | for(uint8 *addr = 0xE0000 + 0xFFFF800000000000; (uint64) addr < 0x100000 + 0xFFFF800000000000; addr++) 59 | { 60 | rsdp = acpiCheckRSDPtr(addr); 61 | if (rsdp != NULL) return rsdp; 62 | } 63 | printf("[INFO] No RSD PTR found\n"); 64 | return NULL; 65 | } -------------------------------------------------------------------------------- /kernel/src/drivers/acpi/rsdp.h: -------------------------------------------------------------------------------- 1 | #ifndef RSDP_H 2 | #define RSDP_H 3 | 4 | #include "acpi.h" 5 | 6 | struct RSDP 7 | { 8 | uint8 Signature[8]; 9 | uint8 CheckSum; 10 | uint8 OemID[6]; 11 | uint8 Revision; 12 | uint32 RsdtAddress; 13 | } __attribute__((packed)); 14 | 15 | struct RSDP2 16 | { 17 | struct RSDP RSDP1; 18 | uint32 length; 19 | uint64 XsdtAddress; 20 | uint8 ExtendedChecksum; 21 | uint8 reserved[3]; 22 | } __attribute__((packed)); 23 | 24 | 25 | uint32 *acpiCheckRSDPtr(uint32 *ptr); 26 | uint32 *acpiGetRSDPtr(void); 27 | 28 | #endif -------------------------------------------------------------------------------- /kernel/src/drivers/acpi/rsdt.c: -------------------------------------------------------------------------------- 1 | #include "rsdt.h" 2 | 3 | int acpiParseRSDT(uint32 *ptr) 4 | { 5 | bool parsed_facp = false; 6 | ptr = (uint64)ptr + 0xFFFF800000000000; 7 | // check if address is correct ( if acpi is available on this pc ) 8 | if (acpiCheckHeader(ptr, "RSDT") == 0 || acpiCheckHeader(ptr, "XSDT") == 0) 9 | { 10 | // the RSDT contains an unknown number of pointers to acpi tables 11 | uint32 entrys = *(ptr + 1); 12 | entrys = (entrys-36) / 4; 13 | ptr += 9; // skip header information 14 | while (0io_base + CMD_REG, 0xA1); //#IDENTIFY PACKET 8 | 9 | if(inportb(ata_device->ctrl_base + ALT_STT_REG) == 0) { ata_delete_drive(drive_num); return; } //The device does not exist 10 | ata_wait_irq(ata_device); 11 | if(inportb(ata_device->ctrl_base + ALT_STT_REG) == 0 || inportb(ata_device->ctrl_base + ALT_STT_REG) & 1) { ata_delete_drive(drive_num); return; } 12 | 13 | uint16 *buffer = kmalloc(256*2); //256 Words, each word being two bytes. 14 | 15 | for(int i = 0; i < 256; i++) 16 | { 17 | buffer[i] = inportw(ata_device->io_base + DATA_REG); 18 | } 19 | 20 | struct ata_identify_packet_t *IDENTIFY_PACKET = kmalloc(sizeof(struct ata_identify_packet_t)); 21 | IDENTIFY_PACKET->GCBSI = buffer[0]; 22 | IDENTIFY_PACKET->Sconf = buffer[2]; 23 | IDENTIFY_PACKET->SerNum = ata_identify_word2ascii(buffer, 10, 19); 24 | IDENTIFY_PACKET->FirmRev = ata_identify_word2ascii(buffer, 23, 26); 25 | IDENTIFY_PACKET->ModNum = ata_identify_word2ascii(buffer, 27, 46); 26 | IDENTIFY_PACKET->Capabilities0 = buffer[49]; 27 | IDENTIFY_PACKET->Capabilities1 = buffer[50]; 28 | IDENTIFY_PACKET->FRV = buffer[53]; 29 | IDENTIFY_PACKET->DMASup0 = buffer[62]; 30 | IDENTIFY_PACKET->DMASup1 = buffer[63]; 31 | IDENTIFY_PACKET->PIOSup = buffer[64]; 32 | IDENTIFY_PACKET->MMDTC = buffer[65]; 33 | IDENTIFY_PACKET->MRMDTC = buffer[66]; 34 | IDENTIFY_PACKET->MPTCwoutFC = buffer[67]; 35 | IDENTIFY_PACKET->MPTCwFC = buffer[68]; 36 | IDENTIFY_PACKET->MajorRevNum = buffer[80]; 37 | IDENTIFY_PACKET->MinorRevNum = buffer[81]; 38 | IDENTIFY_PACKET->CMDSet_FtSup0 = buffer[82]; 39 | IDENTIFY_PACKET->CMDSet_FtSup1 = buffer[83]; 40 | IDENTIFY_PACKET->CMDSet_FtSupExt = buffer[84]; 41 | IDENTIFY_PACKET->CMDSet_FtEn1 = buffer[85]; 42 | IDENTIFY_PACKET->CMDSet_FtEn2 = buffer[86]; 43 | IDENTIFY_PACKET->CMDSet_FtEn2 = buffer[87]; 44 | IDENTIFY_PACKET->UDMASup = buffer[88]; 45 | IDENTIFY_PACKET->TSEUC = buffer[89]; 46 | IDENTIFY_PACKET->TESEC = buffer[90]; 47 | IDENTIFY_PACKET->MPasswdID = buffer[92]; 48 | IDENTIFY_PACKET->HRR = buffer[93]; 49 | IDENTIFY_PACKET->VRAMVal = buffer[94]; 50 | IDENTIFY_PACKET->NAA_IEEIDlo = buffer[108]; 51 | IDENTIFY_PACKET->IEEODhi_UIDlo = buffer[109]; 52 | IDENTIFY_PACKET->UIDmid = buffer[110]; 53 | IDENTIFY_PACKET->UIDhi = buffer[111]; 54 | IDENTIFY_PACKET->ATAPINullByteCnt = buffer[125]; 55 | IDENTIFY_PACKET->SecuritySTT = buffer[128]; 56 | IDENTIFY_PACKET->IntegrityWord = buffer[255]; 57 | ata_device->IDENTIFY_addr = (uint64)IDENTIFY_PACKET; 58 | free(buffer); 59 | 60 | atapi_read_capacity(ata_device); 61 | 62 | ata_device->sectorSize = 2048; //Apparently its the only sector size allowed. But i highly doubt about that, despite not finding documentation that says otherwise 63 | 64 | if((IDENTIFY_PACKET->UDMASup >> 8 & ((1 << 7)-1)) || (IDENTIFY_PACKET->DMASup1 >> 8 & ((1 << 3)-1))) { ata_device->DMA = true; return; } 65 | 66 | for(int i = 6, ander = 1 << 6; i >= 0; i--) 67 | { 68 | if(IDENTIFY_PACKET->UDMASup & ander) //Is UDMA mode (i) supported? 69 | { 70 | //Enable UDMA mode (i) 71 | outportb(ata_device->io_base + DRV_REG, ata_device->slave << 4); //Drive was already selected 72 | ata_400ns_delay(ata_device); 73 | outportb(ata_device->io_base + SEC_CNT_REG, 8 /*0b1000*/ << 3 | i); //UDMA Mode (i) 74 | outportb(ata_device->io_base + FT_REG, 3); //Change drive's transfer mode 75 | outportb(ata_device->io_base + CMD_REG, 0xEF); //Set features 76 | ata_wait_irq(ata_device); 77 | ata_device->DMA = true; 78 | return; 79 | } 80 | ander >>= 1; 81 | } 82 | for(int i = 2, ander = 1 << 2; i >= 0; i--) 83 | { 84 | if(IDENTIFY_PACKET->DMASup1 & ander) //Is MDMA mode (i) supported? 85 | { 86 | //Enable MDMA mode (i) 87 | outportb(ata_device->io_base + DRV_REG, ata_device->slave << 4); //Drive was already selected 88 | ata_400ns_delay(ata_device); 89 | outportb(ata_device->io_base + SEC_CNT_REG, 4 /*0b100*/ << 3 | i); //MDMA Mode (i) 90 | outportb(ata_device->io_base + FT_REG, 3); //Change drive's transfer mode 91 | outportb(ata_device->io_base + CMD_REG, 0xEF); //Set features 92 | ata_wait_irq(ata_device); 93 | ata_device->DMA = true; 94 | return; 95 | } 96 | ander >>= 1; 97 | } 98 | return; 99 | } 100 | 101 | void atapi_read_capacity(struct ata_dev_t *ata_device) 102 | { 103 | outportb(ata_device->io_base + FT_REG, 0); 104 | outportb(ata_device->io_base + LBA_MID, 8); 105 | outportb(ata_device->io_base + LBA_HI, 8); 106 | outportb(ata_device->io_base + CMD_REG, 0xA0); 107 | 108 | //Wait for the device to be ready for accepting the packet 109 | uint8 stat = inportb(ata_device->ctrl_base + ALT_STT_REG); 110 | while(stat & (1 << STT_BSY) && !(stat & (1 << STT_DRQ))) stat = inportb(ata_device->ctrl_base + ALT_STT_REG); 111 | 112 | atapi_send_command(ata_device, 0x25, 0, 0); 113 | ata_wait_irq(ata_device); 114 | 115 | uint32 lba = 0, block_size = 0; 116 | uint16 read = inportw(ata_device->io_base + DATA_REG); 117 | lba |= ((read & 0xFF) << 8) | (read >> 8); 118 | read = inportw(ata_device->io_base + DATA_REG); 119 | lba <<= 16; 120 | lba |= ((read & 0xFF) << 8) | (read >> 8); 121 | 122 | read = inportw(ata_device->io_base + DATA_REG); 123 | block_size |= ((read & 0xFF) << 8) | (read >> 8); 124 | read = inportw(ata_device->io_base + DATA_REG); 125 | block_size <<= 16; 126 | block_size |= ((read & 0xFF) << 8) | (read >> 8); 127 | 128 | ata_device->sectorCount = lba+1; 129 | ata_device->size = (lba+1)*block_size / 1024 / 1024; 130 | } 131 | 132 | void atapi_prepare_command(struct ata_dev_t *ata_device, uint8 DMA) 133 | { 134 | outportb(ata_device->io_base + DRV_REG, ata_device->slave << 4); 135 | ata_400ns_delay(ata_device); 136 | outportb(ata_device->io_base + FT_REG, DMA); 137 | if(DMA) //When using dma transfers, maximal byte count must be 0 138 | { 139 | outportb(ata_device->io_base + LBA_MID, 0); 140 | outportb(ata_device->io_base + LBA_HI, 0); 141 | } else { 142 | outportb(ata_device->io_base + LBA_MID, (uint8)ata_device->sectorSize); 143 | outportb(ata_device->io_base + LBA_HI, (uint8)(ata_device->sectorSize >> 8)); 144 | } 145 | outportb(ata_device->io_base + CMD_REG, 0xA0); //Tell that we're sending an ATA Packet 146 | 147 | //Wait for the device to be ready for accepting the packet 148 | uint8 stat = inportb(ata_device->ctrl_base + ALT_STT_REG); 149 | while(stat & (1 << STT_BSY) && !(stat & (1 << STT_DRQ))) stat = inportb(ata_device->ctrl_base + ALT_STT_REG); 150 | } 151 | 152 | void atapi_send_command(struct ata_dev_t *ata_device, uint8 command, uint32 lba, uint8 sectors) 153 | { 154 | uint8 packet[12] = { 0 }; //12 bytes 155 | packet[0] = command; 156 | packet[2] = (lba >> 24) & 0xFF; 157 | packet[3] = (lba >> 16) & 0xFF; 158 | packet[4] = (lba >> 8) & 0xFF; 159 | packet[5] = lba & 0xFF; 160 | packet[9] = sectors; 161 | 162 | for(int i = 0; i < 6; i++) outportw(ata_device->io_base + DATA_REG, ((uint16*)&packet)[i]); 163 | } -------------------------------------------------------------------------------- /kernel/src/drivers/ata/atapi.h: -------------------------------------------------------------------------------- 1 | #ifndef ATAPI_H 2 | #define ATAPI_H 3 | 4 | #include "ata.h" 5 | #include "../../memory/pmm.h" 6 | 7 | void atapi_identify(struct ata_dev_t *ata_device, int drive_num); 8 | void atapi_prepare_command(struct ata_dev_t *ata_device, uint8 DMA); 9 | void atapi_send_command(struct ata_dev_t *ata_device, uint8 command, uint32 lba, uint8 sectors); 10 | 11 | #endif -------------------------------------------------------------------------------- /kernel/src/drivers/ata/dma/ata_dma.c: -------------------------------------------------------------------------------- 1 | #include "ata_dma.h" 2 | 3 | uint16 *ata_dma_read(struct ata_dev_t *ata_device, uint64 lba, uint16 sectors) 4 | { 5 | void *dma_addr = kmalloc_aligned(ata_device->sectorSize * sectors, 64*1024); 6 | 7 | uint32 *prdt = kmalloc(8); //two 4-byte fields 8 | prdt[0] = dma_addr - 0xFFFF800000000000; 9 | prdt[1] = ((ata_device->sectorSize * sectors) % (64 * 1024)) | (1 << 31); //Byte size % 64kb is done because when doing a 64kb transfer (maximum possible for dma), the byte count should be zero 10 | 11 | outportb(ata_device->busmaster + BM_STT_REG, inportb(ata_device->busmaster + BM_STT_REG)); //Clear interrupt and error bits 12 | outportl(ata_device->busmaster + BM_PRD_REG, (uint64)(prdt)-0xFFFF800000000000); //PRDT 13 | 14 | free(prdt); 15 | 16 | if(!ata_device->LBA48) ata28_prepare_command(ata_device, lba, sectors); 17 | else ata48_prepare_command(ata_device, lba, sectors); 18 | outportb(ata_device->io_base + CMD_REG, ata_device->LBA48 ? 0x25 /*read ext*/ : 0xC8 /*read*/); 19 | 20 | outportb(ata_device->busmaster + BM_CMD_REG, 1 | (1 << 3)); //Read 21 | ata_wait_irq(ata_device); 22 | outportb(ata_device->busmaster + BM_CMD_REG, 0); //Clear direction bit and start/stop bit 23 | 24 | return dma_addr; 25 | } 26 | 27 | void ata_dma_write(struct ata_dev_t *ata_device, uint64 lba, uint16 sectors, uint16 *buffer) 28 | { 29 | void *dma_addr = kmalloc_aligned(ata_device->sectorSize * sectors, 64*1024); 30 | memcpy_fast(dma_addr, buffer, ata_device->sectorSize*sectors); 31 | 32 | uint32 *prdt = kmalloc(8); //two 4-byte fields 33 | prdt[0] = dma_addr - 0xFFFF800000000000; 34 | prdt[1] = ((ata_device->sectorSize * sectors) % (64 * 1024)) | (1 << 31); //Byte size % 64kb is done because when doing a 64kb transfer (maximum possible for dma), the byte count should be zero 35 | 36 | outportb(ata_device->busmaster + BM_STT_REG, inportb(ata_device->busmaster + BM_STT_REG)); //Clear interrupt and error bits 37 | outportl(ata_device->busmaster + BM_PRD_REG, (uint64)(prdt)-0xFFFF800000000000); //PRDT 38 | 39 | free(prdt); 40 | 41 | if(!ata_device->LBA48) ata28_prepare_command(ata_device, lba, sectors); 42 | else ata48_prepare_command(ata_device, lba, sectors); 43 | outportb(ata_device->io_base + CMD_REG, ata_device->LBA48 ? 0x35 /*Write ext*/ : 0xCA /*Write*/); 44 | 45 | outportb(ata_device->busmaster + BM_CMD_REG, 1); //Write 46 | ata_wait_irq(ata_device); 47 | outportb(ata_device->busmaster + BM_CMD_REG, 0); //Clear direction bit and start/stop bit 48 | 49 | free(dma_addr); 50 | 51 | return; 52 | } -------------------------------------------------------------------------------- /kernel/src/drivers/ata/dma/ata_dma.h: -------------------------------------------------------------------------------- 1 | #ifndef ATA_DMA_H 2 | #define ATA_DMA_H 3 | 4 | #include "../ata.h" 5 | 6 | #define BM_CMD_REG 0 7 | #define BM_STT_REG 2 8 | #define BM_PRD_REG 4 9 | 10 | uint16 *ata_dma_read(struct ata_dev_t *ata_device, uint64 lba, uint16 sectors); 11 | void ata_dma_write(struct ata_dev_t *ata_device, uint64 lba, uint16 sectors, uint16 *buffer); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /kernel/src/drivers/ata/dma/atapi_dma.c: -------------------------------------------------------------------------------- 1 | #include "atapi_dma.h" 2 | 3 | uint16 *atapi_dma_read(struct ata_dev_t *ata_device, uint32 lba, uint8 sectors) 4 | { 5 | void *dma_addr = kmalloc_aligned(ata_device->sectorSize * sectors, 64*1024); 6 | 7 | uint32 *prdt = kmalloc(8); //two 4-byte entries 8 | prdt[0] = dma_addr - 0xFFFF800000000000; 9 | prdt[1] = ((ata_device->sectorSize * sectors) % (64 * 1024)) | (1 << 31); //Byte size % 64kb is done because when doing a 64kb transfer (maximum possible for dma), the byte count should be zero 10 | 11 | outportb(ata_device->busmaster + BM_STT_REG, inportb(ata_device->busmaster + BM_STT_REG)); //Clear interrupt and error bits 12 | outportl(ata_device->busmaster + BM_PRD_REG, (uint64)(prdt)-0xFFFF800000000000); //PRDT 13 | 14 | free(prdt); 15 | 16 | atapi_prepare_command(ata_device, 1 /*DMA*/); 17 | atapi_send_command(ata_device, 0xA8 /*READ*/, lba, sectors); 18 | 19 | outportb(ata_device->busmaster + BM_CMD_REG, 1 | (1 << 3)); //Read 20 | ata_wait_irq(ata_device); 21 | outportb(ata_device->busmaster + BM_CMD_REG, 0); //Clear direction bit and start/stop bit 22 | 23 | 24 | return dma_addr; 25 | } -------------------------------------------------------------------------------- /kernel/src/drivers/ata/dma/atapi_dma.h: -------------------------------------------------------------------------------- 1 | #ifndef ATAPI_DMA_H 2 | #define ATAPI_DMA_H 3 | 4 | #include "../atapi.h" 5 | 6 | uint16 *atapi_dma_read(struct ata_dev_t *ata_device, uint32 lba, uint8 sector); 7 | 8 | #endif -------------------------------------------------------------------------------- /kernel/src/drivers/ata/pio/ata_pio.c: -------------------------------------------------------------------------------- 1 | #include "ata_pio.h" 2 | 3 | /********* SEND COMMAND PIO *********/ 4 | 5 | uint16 *ata_pio_read(struct ata_dev_t *ata_device, uint64 lba, uint16 sectors) 6 | { 7 | uint16 *buffer = kmalloc(ata_device->sectorSize*sectors); 8 | 9 | if(!ata_device->LBA48) ata28_prepare_command(ata_device, lba, sectors); 10 | else ata48_prepare_command(ata_device, lba, sectors); 11 | outportb(ata_device->io_base + CMD_REG, ata_device->LBA48 ? 0x24 /*Read ext*/ : 0x20 /*Read*/); 12 | 13 | uint8 stat = inportb(ata_device->ctrl_base + ALT_STT_REG); 14 | while(stat & (1 << STT_BSY) && !(stat & (1 << STT_DRQ))) 15 | { 16 | stat = inportb(ata_device->ctrl_base + ALT_STT_REG); 17 | } 18 | 19 | for(int i = 0; i < sectors; i++) 20 | { 21 | ata_wait_irq(ata_device); 22 | for(int j = 0; j < ata_device->sectorSize / 2; j++) 23 | { 24 | buffer[i*(ata_device->sectorSize / 2) + j] = inportw(ata_device->io_base + DATA_REG); 25 | } 26 | } 27 | return buffer; 28 | } 29 | 30 | void ata_pio_write(struct ata_dev_t *ata_device, uint64 lba, uint16 sectors, uint16 *buffer) 31 | { 32 | if(!ata_device->LBA48) ata28_prepare_command(ata_device, lba, sectors); 33 | else ata48_prepare_command(ata_device, lba, sectors); 34 | outportb(ata_device->io_base + CMD_REG, ata_device->LBA48 ? 0x34 /*Write ext*/ : 0x30 /*Write*/); 35 | for(int i = 0; i < sectors; i++) 36 | { 37 | //ata_wait_irq(ata_device); 38 | for(int j = 0; j < ata_device->sectorSize / 2; j++) 39 | { 40 | outportw(ata_device->io_base + DATA_REG, buffer[i*(ata_device->sectorSize / 2) + j]); 41 | } 42 | ata_wait_irq(ata_device); 43 | outportb(ata_device->io_base + CMD_REG, 0xE7); //Cache Flush 44 | ata_wait_irq(ata_device); 45 | } 46 | return; 47 | } 48 | -------------------------------------------------------------------------------- /kernel/src/drivers/ata/pio/ata_pio.h: -------------------------------------------------------------------------------- 1 | #ifndef ATA_PIO_H 2 | #define ATA_PIO_H 3 | 4 | #include "../ata.h" 5 | 6 | uint16 *ata_pio_read(struct ata_dev_t *ata_device, uint64 lba, uint16 sectors); 7 | void ata_pio_write(struct ata_dev_t *ata_device, uint64 lba, uint16 sectors, uint16 *buffer); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /kernel/src/drivers/ata/pio/atapi_pio.c: -------------------------------------------------------------------------------- 1 | #include "atapi_pio.h" 2 | 3 | uint16 *atapi_pio_read(struct ata_dev_t *ata_device, uint32 lba, uint8 sectors) 4 | { 5 | atapi_prepare_command(ata_device, 0 /*PIO*/); 6 | atapi_send_command(ata_device, 0xA8 /*READ (12)*/, lba, sectors); 7 | 8 | uint8 stat = inportb(ata_device->ctrl_base + ALT_STT_REG); 9 | while(stat & (1 << STT_BSY) && !(stat & (1 << STT_DRQ))) 10 | { 11 | stat = inportb(ata_device->ctrl_base + ALT_STT_REG); 12 | } 13 | 14 | uint16 *buffer = kmalloc(ata_device->sectorSize*sectors); 15 | for(int i = 0; i < sectors; i++) 16 | { 17 | ata_wait_irq(ata_device); 18 | for(int j = 0; j < ata_device->sectorSize / 2; j++) 19 | { 20 | buffer[i*(ata_device->sectorSize / 2)+j] = inportw(ata_device->io_base + DATA_REG); 21 | } 22 | } 23 | 24 | return buffer; 25 | } 26 | -------------------------------------------------------------------------------- /kernel/src/drivers/ata/pio/atapi_pio.h: -------------------------------------------------------------------------------- 1 | #ifndef ATAPI_PIO_H 2 | #define ATAPI_PIO_H 3 | 4 | #include "../atapi.h" 5 | 6 | uint16 *atapi_pio_read(struct ata_dev_t *ata_device, uint32 lba, uint8 sectors); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /kernel/src/drivers/energy/energy.c: -------------------------------------------------------------------------------- 1 | #include "energy.h" 2 | 3 | void reboot() 4 | { 5 | ioapicDisable(); //We may have situations in which the IOAPIC is not set to masked, thus causing faults 6 | acpiReboot(); 7 | kill_pmm(); 8 | uint8 check = 0; 9 | do 10 | { 11 | check = inportb(0x64); 12 | if(check & 1) 13 | { 14 | inportb(0x60); 15 | continue; 16 | } 17 | } while(check & (1 << 1)); 18 | outportb(0x64, 0xFE); 19 | 20 | outportb(0x70, 0x8F); 21 | outportb(0x71, 0x00); 22 | outportb(0x70, 0x00); 23 | outportb(0x92, inportb(0x92) | 1); 24 | printf("[ "); 25 | printcolor("PANIC", 0, 0xFFE00000); 26 | printf(" ] Couldn't reboot the computer. System Halted.\n"); 27 | asm("cli;hlt"); 28 | } 29 | 30 | void shutdown() 31 | { 32 | acpiPowerOff(); 33 | printf("[ "); 34 | printcolor("PANIC", 0, 0xFFE00000); 35 | printf(" ] ACPI Shutdown failed! System Halted.\n"); 36 | asm("cli;hlt"); 37 | } -------------------------------------------------------------------------------- /kernel/src/drivers/energy/energy.h: -------------------------------------------------------------------------------- 1 | #ifndef ENERGY_H 2 | #define ENERGY_H 3 | 4 | #include "../acpi/acpi.h" 5 | #include "../../console/console.h" 6 | 7 | void reboot(); 8 | void shutdown(); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /kernel/src/drivers/hpet/hpet.c: -------------------------------------------------------------------------------- 1 | #include "hpet.h" 2 | 3 | #define HpetCapabilitiesReg 0 4 | #define HpetConfigReg 0x10 5 | #define HpetIntStatusReg 0x20 6 | #define HpetMainCounterReg 0xF0 7 | #define HpetTimerConfigCapReg(n) (0x100 + 0x20 * n) 8 | #define HpetTimerComparatorVal(n) (0x108 + 0x20 * n) 9 | #define HpetFSBIntRouteReg(n) (0x110 + 0x20 * n) 10 | 11 | uint64 HpetAddr = 0; 12 | uint64 CounterClockPeriod = 0; 13 | 14 | static inline uint64 HpetReadMMIO(uint32 offset) 15 | { 16 | return *(uint64*)(HpetAddr + offset); 17 | } 18 | 19 | static inline void HpetWriteMMIO(uint32 offset, uint64 value) 20 | { 21 | *(uint64*)(HpetAddr + offset) = value; 22 | } 23 | 24 | void EnableHpet() 25 | { 26 | uint64 config = HpetReadMMIO(HpetConfigReg); 27 | config |= 1 << 0 | 1 << 1; //Overall enable and legacy replacement bit 28 | HpetWriteMMIO(HpetConfigReg, config); 29 | } 30 | 31 | void DisableHpet() 32 | { 33 | uint64 config = HpetReadMMIO(HpetConfigReg); 34 | config &= ~(1 << 0); //Overall enable (but zeroed :/) 35 | HpetWriteMMIO(HpetConfigReg, config); 36 | } 37 | 38 | void HpetEnableComparator(uint32 ComparatorNum, bool fsb, bool Enable32Bits, bool periodic, bool LevelTriggered) 39 | { 40 | uint32 CompOffset = HpetTimerConfigCapReg(ComparatorNum); //Get the comparator's offset 41 | 42 | if(fsb && HpetReadMMIO(CompOffset) & (1 << 15)) HpetWriteMMIO(CompOffset, HpetReadMMIO(CompOffset) | (1 << 14)); //If FSB can be used (bit 15), and we want to use FSB Mapping, then enable FSB (set bit 14) 43 | else HpetWriteMMIO(CompOffset, HpetReadMMIO(CompOffset) & ~(1 << 14)); //Otherwise, set it off. This should be the default, but just in case. 44 | 45 | if(Enable32Bits && HpetReadMMIO(CompOffset) & (1 << 5)) HpetWriteMMIO(CompOffset, HpetReadMMIO(CompOffset) | (1 << 8)); //Enable 32 bit mode if we want it and the comparator supports it 46 | 47 | if(periodic && HpetReadMMIO(CompOffset) & (1 << 4)) HpetWriteMMIO(CompOffset, HpetReadMMIO(CompOffset) | (1 << 6)); //Enable periodic mode if we want it and the comparator supports its 48 | else HpetWriteMMIO(CompOffset, HpetReadMMIO(CompOffset) & ~(1 << 6)); //Otherwise make sure to leave it disabled (its not specified whether its defaulted to false or not) 49 | 50 | if(LevelTriggered) HpetWriteMMIO(CompOffset, HpetReadMMIO(CompOffset) | 1); 51 | else HpetWriteMMIO(CompOffset, HpetReadMMIO(CompOffset) & ~1); 52 | 53 | HpetWriteMMIO(CompOffset, HpetReadMMIO(CompOffset) | (1 << 2)); //Enable interrupt triggering 54 | } 55 | 56 | void StartHpet() 57 | { 58 | pitDisable(); 59 | HpetEnableComparator(0, false, false, false, false); //We will, for now, only enable the first comparator without fsb mapping, with 64-bit counter, without periodic accumulator, and edge triggered. 60 | EnableHpet(); 61 | ChangeTimer("HPET"); 62 | } 63 | 64 | void acpiParseHpet(uint32 *ptr) 65 | { 66 | struct HPET *hpet = (struct HPET*)(*ptr + 0xFFFF800000000000); 67 | HpetAddr = hpet->Address.Address; 68 | uint64 *addr = HpetAddr; 69 | id_vmmap(addr,2048,3); 70 | CounterClockPeriod = HpetReadMMIO(HpetCapabilitiesReg) >> 32; 71 | //StartHpet(); //Until here, Hpet will start working but no IRQ's will be generated\ 72 | since no comparator has been set up 73 | } 74 | 75 | bool HpetSleeping = false; 76 | 77 | void HpetHandler() 78 | { 79 | HpetSleeping = false; //If we have an hpet int, then we finished sleeping (since we use one-shot mode) 80 | } 81 | 82 | void HpetSleep(uint64 time, uint8 type) 83 | { 84 | uint64 actualTime = 0; 85 | if(type == SleepFemto) 86 | { 87 | actualTime = time; 88 | } else if(type == SleepPico) { 89 | actualTime = time * 1000; //Picosec to Femtosec (multiply time by 1000) 90 | } else if(type == SleepNano) { 91 | actualTime = time * 1000000; //Nanosec to Femtosec (multiply nanosecs 1e6) 92 | } else if(type == SleepMicro) { 93 | actualTime = time * 1000000000; //Microsec Femtosec (multiply microsecs by 1e9) 94 | } else if(type == SleepMili) { 95 | actualTime = time * 1000000000000; //Milisec to Femtosec (multiply milisecs by 1e12) 96 | } 97 | if(actualTime < CounterClockPeriod) 98 | { 99 | actualTime = CounterClockPeriod; //Bc why not 100 | } 101 | HpetWriteMMIO(HpetTimerConfigCapReg(0), (2 /*IoApic irq 2*/ << 9) | (1 << 2) /*Irq Enable interrupt*/); 102 | HpetWriteMMIO(HpetTimerComparatorVal(0), (uint64)HpetReadMMIO(HpetMainCounterReg) + (actualTime / CounterClockPeriod)); 103 | HpetSleeping = true; 104 | while(HpetSleeping) asm volatile("hlt"); //Wait until next interrupt 105 | return; 106 | } -------------------------------------------------------------------------------- /kernel/src/drivers/hpet/hpet.h: -------------------------------------------------------------------------------- 1 | #ifndef HPET_H 2 | #define HPET_H 3 | 4 | #include "../acpi/acpi.h" 5 | 6 | struct HPET 7 | { 8 | struct ACPI_SDTHeader_t h; 9 | uint8 HwRevID; //Hardware revision id 10 | uint8 ComparatorCount : 5; 11 | uint8 CounterSize : 1; 12 | uint8 reserved : 1; 13 | uint8 LegacyReplacement : 1; 14 | uint16 PciVendorID; 15 | struct GenericAddressStructure_t Address; 16 | uint8 HpetNumber; 17 | uint16 MinimumTick; //Periodic mode only 18 | uint8 PageProtection; 19 | } __attribute__((packed)); 20 | 21 | void acpiParseHpet(uint32 *ptr); 22 | void HpetHandler(); 23 | void HpetSleep(uint64 Time, uint8 type); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /kernel/src/drivers/kb/kb.c: -------------------------------------------------------------------------------- 1 | #include "kb.h" 2 | 3 | //Now, What in the actual F***. For some reason, if i execute printf in this file, it goes 4 | //absolutely crazy. But that does not happen if printf is called outside. H-E-L-P. 5 | 6 | int shift = 0; 7 | int str_buff_pos = 0; 8 | string str_buffer = 0; //up to 100 chars. 9 | 10 | uint8 kbd_map[0x56] = { 11 | 0/*null*/, 27/*escape*/, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 12 | '-', '=', 13 | 0/*backsace*/, 14 | 0/*tab*/, 15 | 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n' /*enter*/, 16 | 0 /*LEFT CTRL*/, 17 | 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', ((char)0x27)/*single quote*/, ((char)0x60)/*back tick*/, 18 | 0 /*LEFT SHIFT*/, 19 | ((char)0x5C)/*inverse slash*/, 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/'/*slash*/, 20 | 0 /*RIGHT SHIFT*/, 21 | '*', 22 | 0/*LEFT ALT*/, 23 | ' ', 24 | 0/*CAPS LOCK*/, 25 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /*F1-F10*/, 26 | 0 /*NUMBER LOCK*/, 27 | 0 /*SCROLL LOCK*/, //71 28 | //FROM HERE 'TILL THE LAST ONE, WE HAVE SOME NUMBERS FROM THE KEYOADM ABD THEN LAST 'F' KEYS 29 | '7', '8', '9', 30 | '-', 31 | '4', '5', '6', 32 | '+', 33 | '1', '2', '3', '0', 34 | '.', //84 35 | //NOW WE HAVE THE LAST TWO KEYS, F11 AND F12 36 | 0, 0 37 | }; 38 | 39 | signed char shift_kbd_map[] = { 40 | 0, 27, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', 41 | 0, 0, 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', 42 | 0, 0, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~', 43 | 0, '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', 0, 0, 0, ' ' 44 | }; 45 | 46 | void kbBufferInit() 47 | { 48 | str_buffer = kmalloc(100); 49 | } 50 | 51 | void kbd_handler() 52 | { 53 | unsigned char kcod; 54 | unsigned char status = inportb(0x64); 55 | if(status & 0x1) 56 | { 57 | kcod = inportb(0x60); 58 | if(kcod < 0x58) 59 | { 60 | if(kcod == 0x2A || kcod == 0x36) 61 | { 62 | shift = 1; 63 | } 64 | if(kbd_map[kcod] != 0) 65 | { 66 | if(!shift) 67 | { 68 | printch(kbd_map[kcod]); 69 | str_buffer[str_buff_pos++] = kbd_map[kcod]; 70 | if(kbd_map[kcod] == '\n') 71 | { 72 | last_str = str_buffer; 73 | last_str[str_buff_pos-1] = '\0'; 74 | str_buffer = ""; 75 | str_buff_pos = 0; 76 | end_str = 1; 77 | } 78 | } else { 79 | printch(shift_kbd_map[kcod]); 80 | str_buffer[str_buff_pos++] = shift_kbd_map[kcod]; 81 | if(shift_kbd_map[kcod] == '\n') 82 | { 83 | last_str = str_buffer; 84 | last_str[str_buff_pos-1] = NULL; 85 | str_buffer = ""; 86 | str_buff_pos = 0; 87 | end_str = 1; 88 | } 89 | } 90 | } else if(kcod == 0xE) { 91 | if(str_buff_pos > 0) 92 | { 93 | str_buff_pos--; 94 | str_buffer[str_buff_pos] = NULL; 95 | printch('\b'); 96 | } 97 | } else if(kcod == 0xF) { 98 | for(int i = 0; i < 4; i++, str_buff_pos++) 99 | { 100 | printch(' '); 101 | str_buffer[str_buff_pos] = ' '; 102 | } 103 | } 104 | } else if(kcod == 0xAA || kcod == 0xB6) { 105 | shift = 0; 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /kernel/src/drivers/kb/kb.h: -------------------------------------------------------------------------------- 1 | #ifndef KB_H 2 | #define KB_H 3 | 4 | #include "../../console/console.h" 5 | #include "../../arch/x86/cpu.h" 6 | #include "../../string/types.h" 7 | 8 | string last_str; 9 | int end_str; 10 | 11 | void kbd_handler(); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /kernel/src/drivers/pci/pci.c: -------------------------------------------------------------------------------- 1 | #include "pci.h" 2 | 3 | #define CONFIG_ADDR 0xCF8 4 | #define CONFIG_DATA 0xCFC 5 | 6 | uint32 pciRead32(uint32 addr); 7 | uint16 pciRead16(uint32 addr); 8 | uint8 pciRead8(uint32 addr); 9 | void pciWrite32(uint32 addr, uint32 value); 10 | void pciWrite16(uint32 addr, uint16 value); 11 | void pciWrite8(uint32 addr, uint8 value); 12 | void ReadConfigData(struct PciDevice_t *PciDevice, uint32 address); 13 | void CheckDevice(uint8 bus, uint8 device); 14 | void CheckFunction(uint8 bus, uint8 device, uint8 function); 15 | void CheckBus(uint8 bus); 16 | 17 | uint32 pciRead32(uint32 addr) 18 | { 19 | outportl(CONFIG_ADDR, addr); 20 | uint32 data = inportl(CONFIG_DATA); 21 | return data; 22 | } 23 | 24 | uint16 pciRead16(uint32 addr) 25 | { 26 | outportl(CONFIG_ADDR, addr); 27 | uint32 data = inportl(CONFIG_DATA); 28 | return data & ((1 << 16)-1); 29 | } 30 | 31 | uint8 pciRead8(uint32 addr) 32 | { 33 | outportl(CONFIG_ADDR, addr); 34 | uint32 data = inportl(CONFIG_DATA); 35 | return data & ((1 << 8) - 1); 36 | } 37 | 38 | void pciWrite32(uint32 addr, uint32 value) 39 | { 40 | outportl(CONFIG_ADDR, addr); 41 | outportl(CONFIG_DATA, value); 42 | } 43 | 44 | void pciWrite16(uint32 addr, uint16 value) 45 | { 46 | outportl(CONFIG_ADDR, addr); 47 | outportw(CONFIG_DATA, value); 48 | } 49 | 50 | void pciWrite8(uint32 addr, uint8 value) 51 | { 52 | outportl(CONFIG_ADDR, addr); 53 | outportb(CONFIG_DATA, value); 54 | } 55 | 56 | void ReadConfigData(struct PciDevice_t *PciDevice, uint32 address) 57 | { 58 | address &= ~(0xFF); 59 | int offset = 0; 60 | uint32 tmp = pciRead32(address | offset); //(31:16) Device ID, (15:0) Vendor ID 61 | offset += 4; 62 | PciDevice->VendorID = (uint16)tmp; //Lower 16Bits 63 | PciDevice->DeviceID = (uint16)(tmp >> 16); //Higher 16Bits 64 | tmp = pciRead32(address | offset); //(31:16) Status, (15:0) Command 65 | offset += 4; 66 | PciDevice->Command = (uint16)tmp; //Lower 16Bits 67 | PciDevice->Status = (uint16)(tmp >> 16); //Higher 16Bits 68 | tmp = pciRead32(address | offset); //(31:24) Class, (23:16) SubClass, (15:8) Prog IF, (7:0) Rev ID 69 | offset += 4; 70 | PciDevice->RevisionID = (uint8)tmp; //First byte 71 | PciDevice->ProgIF = (uint8)(tmp >> 8); //Second byte 72 | PciDevice->SubClass = (uint8)(tmp >> 16); //Third byte 73 | PciDevice->Class = (uint8)(tmp >> 24); //Fourth byte 74 | tmp = pciRead32(address | offset); //(31:24) BIST, (23:16) Header Type, (15:8) Latency timer, (7:0)Cache line size 75 | offset += 4; 76 | PciDevice->CacheLineSize = (uint8)tmp; //First byte 77 | PciDevice->LatencyTimer = (uint8)(tmp >> 8); //Second byte 78 | PciDevice->HeaderType = (uint8)(tmp >> 16); //Third byte 79 | PciDevice->BIST = (uint8)(tmp >> 24); //Fourth byte 80 | 81 | if((PciDevice->HeaderType & ~(0b01111111)) /*mask bit 7 (device is multifunc)*/ == 0) 82 | { 83 | for(int i = 0; i < 6; i++) //BARs 84 | { 85 | PciDevice->PciDefaultHeader.BAR[i] = pciRead32(address + offset); 86 | offset += 4; 87 | } 88 | PciDevice->PciDefaultHeader.CardbusCISPointer = pciRead32(address | offset); //Offset was already incremented in BAR parsing 89 | offset += 4; 90 | tmp = pciRead32(address | offset); 91 | offset += 4; 92 | PciDevice->PciDefaultHeader.SubsystemID = (uint16)(tmp >> 16); //Higher 16Bits 93 | PciDevice->PciDefaultHeader.SubsystemVendorID = (uint16)tmp; //Lower 16Bits 94 | PciDevice->PciDefaultHeader.ExpansionRomBAR = pciRead32(address | offset); 95 | offset += 4; 96 | //There should be a reserved thing, so we just aint fill it 97 | tmp = pciRead32(address | offset); 98 | offset += 8; //The next field is reserved, so we pass on to the second next one :D 99 | PciDevice->PciDefaultHeader.CapabilitiesPointer = (uint8)tmp; 100 | tmp = pciRead32(address | offset); 101 | PciDevice->PciDefaultHeader.MaxLatency = (uint8)(tmp >> 24); 102 | PciDevice->PciDefaultHeader.MinGrant = (uint8)(tmp >> 16); 103 | PciDevice->PciDefaultHeader.InterruptPIN = (uint8)(tmp >> 8); 104 | PciDevice->PciDefaultHeader.InterruptLine = (uint8)tmp; 105 | } else if((PciDevice->HeaderType & ~(0b01111111)) /*mask bit 7 (device is multifunc)*/ == 1) { 106 | for(int i = 0; i < 2; i++) 107 | { 108 | PciDevice->PCItoPCIHeader.BAR[i] = pciRead32(address | offset); 109 | offset += 4; 110 | } 111 | tmp = pciRead32(address | offset); //Offset was already incremented in BAR parsing 112 | offset += 4; 113 | PciDevice->PCItoPCIHeader.SecondaryLatencyTimer = (uint8)(tmp >> 24); 114 | PciDevice->PCItoPCIHeader.SubordinateBusNumber = (uint8)(tmp >> 16); 115 | PciDevice->PCItoPCIHeader.SecondaryBusNumber = (uint8)(tmp >> 8); 116 | PciDevice->PCItoPCIHeader.PrimaryBusNumber = (uint8)tmp; 117 | tmp = pciRead32(address | offset); 118 | offset += 4; 119 | PciDevice->PCItoPCIHeader.SecondaryStatus = (uint16)(tmp >> 16); 120 | PciDevice->PCItoPCIHeader.IOLimit = (uint8)(tmp >> 8); 121 | PciDevice->PCItoPCIHeader.IOBase = (uint8)tmp; 122 | tmp = pciRead32(address | offset); 123 | offset += 4; 124 | PciDevice->PCItoPCIHeader.MemoryLimit = (uint16)(tmp >> 16); 125 | PciDevice->PCItoPCIHeader.MemoryBase = (uint16)tmp; 126 | tmp = pciRead32(address | offset); 127 | offset += 4; 128 | PciDevice->PCItoPCIHeader.PrefetchMemoryLimit = (uint16)(tmp >> 16); 129 | PciDevice->PCItoPCIHeader.PrefetchMemoryBase = (uint16)tmp; 130 | PciDevice->PCItoPCIHeader.PrefetchBaseUpper = pciRead32(address | offset); 131 | offset += 4; 132 | PciDevice->PCItoPCIHeader.PrefetchLimitUpper = pciRead32(address | offset); 133 | offset += 4; 134 | tmp = pciRead32(address | offset); 135 | offset += 8; //Next entry is reserved, so we go to the second next :D 136 | PciDevice->PCItoPCIHeader.IOLimitUpper = (uint16)(tmp >> 16); 137 | PciDevice->PCItoPCIHeader.IOBaseUpper = (uint16)tmp; 138 | tmp = pciRead32(address | offset); 139 | offset += 4; 140 | PciDevice->PCItoPCIHeader.CapabilityPointer = (uint8)tmp; 141 | PciDevice->PCItoPCIHeader.ExpansionRomBAR = pciRead32(address | offset); 142 | offset += 4; 143 | tmp = pciRead32(address | offset); 144 | PciDevice->PCItoPCIHeader.BridgeControl = (uint16)(tmp >> 16); 145 | PciDevice->PCItoPCIHeader.InterruptPin = (uint8)(tmp >> 8); 146 | PciDevice->PCItoPCIHeader.InterruptLine = (uint8)tmp; 147 | } else { 148 | PciDevice->PCItoCardbus.CardBusBAR = pciRead32(address | offset); 149 | offset += 4; 150 | tmp = pciRead32(address | offset); 151 | offset += 4; 152 | PciDevice->PCItoCardbus.SecondaryStatus = (uint16)(tmp >> 16); 153 | PciDevice->PCItoCardbus.CapabilitesOffset = (uint8)tmp; 154 | tmp = pciRead32(address | offset); 155 | offset += 4; 156 | PciDevice->PCItoCardbus.CardbusLatencyTimer = (uint8)(tmp >> 24); 157 | PciDevice->PCItoCardbus.SubordinateBusNumber = (uint8)(tmp >> 16); 158 | PciDevice->PCItoCardbus.CardbusBusNumber = (uint8)(tmp >> 8); 159 | PciDevice->PCItoCardbus.PciBusNumber = (uint8)tmp; 160 | PciDevice->PCItoCardbus.MemoryBase0 = pciRead32(address | offset); 161 | offset += 4; 162 | PciDevice->PCItoCardbus.MemoryLimit0 = pciRead32(address | offset); 163 | offset += 4; 164 | PciDevice->PCItoCardbus.MemoryBase1 = pciRead32(address | offset); 165 | offset += 4; 166 | PciDevice->PCItoCardbus.MemoryLimit1 = pciRead32(address | offset); 167 | offset += 4; 168 | PciDevice->PCItoCardbus.IOBar0 = pciRead32(address | offset); 169 | offset += 4; 170 | PciDevice->PCItoCardbus.IOLimit0 = pciRead32(address | offset); 171 | offset += 4; 172 | PciDevice->PCItoCardbus.IOBar1 = pciRead32(address | offset); 173 | offset += 4; 174 | PciDevice->PCItoCardbus.IOLimit1 = pciRead32(address | offset); 175 | offset += 4; 176 | tmp = pciRead32(address | offset); 177 | offset += 4; 178 | PciDevice->PCItoCardbus.BridgeControl = (uint16)(tmp >> 16); 179 | PciDevice->PCItoCardbus.InterruptPin = (uint8)(tmp >> 8); 180 | PciDevice->PCItoCardbus.InterruptLine = (uint8)tmp; 181 | tmp = pciRead32(address | offset); 182 | offset += 4; 183 | PciDevice->PCItoCardbus.SubsystemVendorID = (uint16)(tmp >> 16); 184 | PciDevice->PCItoCardbus.SubsystemDeviceID = (uint16)tmp; 185 | PciDevice->PCItoCardbus.LegacyBAR = pciRead32(address | offset); 186 | } 187 | } 188 | 189 | void CheckDevice(uint8 bus, uint8 device) 190 | { 191 | uint8 function = 0; 192 | struct PciDevice_t PciDevice; 193 | PciDevice.VendorID = pciRead32(0x80000000 | (bus << 16) | (device << 11)) & 0xFFFF; 194 | if(PciDevice.VendorID == 0xFFFF) return; 195 | for(uint8 function = 0; function < 8 && PciDevice.VendorID != 0xFFFF; function++) 196 | { 197 | CheckFunction(bus, device, function); 198 | } 199 | } 200 | 201 | void CheckBus(uint8 bus) 202 | { 203 | for(uint8 device = 0; device < 32; device++) 204 | { 205 | CheckDevice(bus, device); 206 | } 207 | } 208 | 209 | void CheckFunction(uint8 bus, uint8 device, uint8 function) 210 | { 211 | PciDevices[lastPciDevice] = kmalloc(sizeof(struct PciDevice_t)); 212 | 213 | uint32 address = 0x80000000 | (bus << 16) | ((device & 0x1F) << 11) | ((function & 7) << 8); 214 | ReadConfigData(PciDevices[lastPciDevice], address); 215 | 216 | if(PciDevices[lastPciDevice]->VendorID == 0xFFFF || PciDevices[lastPciDevice]->VendorID == 0x0000) 217 | { 218 | free(PciDevices[lastPciDevice]); 219 | return; 220 | } 221 | 222 | PciDevices[lastPciDevice]->Bus = bus; 223 | PciDevices[lastPciDevice]->Device = device; 224 | PciDevices[lastPciDevice]->Function = function; 225 | PciDevices[lastPciDevice]->MMIO = false; //We will say false, until MCFG says otherwise 226 | PciDevices[lastPciDevice]->Address = address; 227 | 228 | //Here we will check whatever pci device we want to check 229 | if(PciDevices[lastPciDevice]->Class == 1 && PciDevices[lastPciDevice]->SubClass == 1) 230 | { 231 | pciWrite16(address | 4, 5); //Enable I/O Flag & Bus master Enable flag on channel 0 232 | pciWrite16(address | 5, 5); //Enable I/O Flag & Bus master Enable flag on channel 5 233 | 234 | init_ata(PciDevices[lastPciDevice]->PciDefaultHeader.BAR[4] & 0xFFFFFFFC);//Initialize queue,etc but now we provide the busmaster information 235 | } 236 | 237 | //End of checking :) 238 | lastPciDevice++; 239 | if(PciDevices[lastPciDevice]->Class == 0x6 && PciDevices[lastPciDevice]->SubClass == 0x9) //PCI 2 PCI Bridge 240 | { 241 | CheckBus(PciDevices[lastPciDevice]->PCItoPCIHeader.SecondaryBusNumber); 242 | } 243 | } 244 | 245 | void PciInit() 246 | { 247 | lastPciDevice = 0; 248 | PciDevices = kmalloc(32 * 8); //Up to 32 devices per bus, 8 buses in total 249 | struct PciDevice_t PciDevice; 250 | ReadConfigData(&PciDevice, 0); 251 | if(!(PciDevice.HeaderType & 0x80)) //Single Pci host Controller 252 | { 253 | CheckBus(0); 254 | } else { //Multiple Pci host controllers 255 | for(uint32 function = 0; function < 8; function++) 256 | { 257 | if(pciRead32(0x80000000 | (function << 8)) == 0xFFFF) break; 258 | CheckBus(function); 259 | } 260 | } 261 | } 262 | -------------------------------------------------------------------------------- /kernel/src/drivers/pci/pci.h: -------------------------------------------------------------------------------- 1 | #ifndef PCI_H 2 | #define PCI_H 3 | 4 | #include "../../arch/x86/cpu.h" 5 | #include "../../string/types.h" 6 | #include "../../console/console.h" 7 | 8 | void PciInit(); 9 | /*The other functions are declared in the pci.c file, so they are private*/ 10 | 11 | int lastPciDevice; 12 | 13 | struct PciDefaultHeader_t 14 | { 15 | uint8 LatencyTimer; 16 | uint8 CacheLineSize; 17 | uint32 BAR[6]; 18 | uint32 CardbusCISPointer; 19 | uint16 SubsystemID; 20 | uint16 SubsystemVendorID; 21 | uint32 ExpansionRomBAR; 22 | uint8 Reserved[7]; 23 | uint8 CapabilitiesPointer; 24 | uint8 MaxLatency; 25 | uint8 MinGrant; 26 | uint8 InterruptPIN; 27 | uint8 InterruptLine; 28 | } __attribute__((packed)); 29 | 30 | struct PCItoPCIHeader_t 31 | { 32 | uint8 LatencyTimer; 33 | uint8 CacheLineSize; 34 | uint32 BAR[2]; 35 | uint8 SecondaryLatencyTimer; 36 | uint8 SubordinateBusNumber; 37 | uint8 SecondaryBusNumber; 38 | uint8 PrimaryBusNumber; 39 | uint16 SecondaryStatus; 40 | uint8 IOLimit; 41 | uint8 IOBase; 42 | uint16 MemoryLimit; 43 | uint16 MemoryBase; 44 | uint16 PrefetchMemoryLimit; //Prefetchable 45 | uint16 PrefetchMemoryBase; //Prefetchable 46 | uint32 PrefetchBaseUpper; 47 | uint32 PrefetchLimitUpper; 48 | uint16 IOLimitUpper; //Upper 16Bits 49 | uint16 IOBaseUpper; //Upper 16Bits 50 | uint8 reserved[3]; 51 | uint8 CapabilityPointer; 52 | uint32 ExpansionRomBAR; 53 | uint16 BridgeControl; 54 | uint8 InterruptPin; 55 | uint8 InterruptLine; 56 | } __attribute__((packed)); 57 | 58 | struct PCItoCardbus_t 59 | { 60 | uint8 LatencyTimer; 61 | uint8 CacheLineSize; 62 | uint32 CardBusBAR; 63 | uint16 SecondaryStatus; 64 | uint8 reserved; 65 | uint8 CapabilitesOffset; 66 | uint8 CardbusLatencyTimer; 67 | uint8 SubordinateBusNumber; 68 | uint8 CardbusBusNumber; 69 | uint8 PciBusNumber; 70 | uint32 MemoryBase0; 71 | uint32 MemoryLimit0; 72 | uint32 MemoryBase1; 73 | uint32 MemoryLimit1; 74 | uint32 IOBar0; 75 | uint32 IOLimit0; 76 | uint32 IOBar1; 77 | uint32 IOLimit1; 78 | uint16 BridgeControl; 79 | uint8 InterruptPin; 80 | uint8 InterruptLine; 81 | uint16 SubsystemVendorID; 82 | uint16 SubsystemDeviceID; 83 | uint32 LegacyBAR; 84 | } __attribute__((packed)); 85 | 86 | struct PciDevice_t 87 | { 88 | uint8 Bus; 89 | uint8 Device; 90 | uint8 Function; 91 | uint8 MMIO; //If we are/can use MMIO 92 | uint64 Address; 93 | //From here we'll have the Actual definition of the Pci fields. 94 | uint16 VendorID; 95 | uint16 DeviceID; 96 | uint16 Command; 97 | uint16 Status; 98 | uint8 RevisionID; 99 | uint8 ProgIF; 100 | uint8 SubClass; 101 | uint8 Class; 102 | uint8 CacheLineSize; 103 | uint8 LatencyTimer; 104 | uint8 HeaderType; 105 | uint8 BIST; 106 | struct PciDefaultHeader_t PciDefaultHeader; 107 | struct PCItoPCIHeader_t PCItoPCIHeader; 108 | struct PCItoCardbus_t PCItoCardbus; 109 | } __attribute__((packed)); 110 | 111 | struct PciDevice_t **PciDevices; 112 | 113 | #endif 114 | -------------------------------------------------------------------------------- /kernel/src/drivers/pcie/pcie.c: -------------------------------------------------------------------------------- 1 | #include "pcie.h" 2 | 3 | void acpiParsePCIe(uint32 *ptr) 4 | { 5 | struct MCFG *mcfg = (struct MCFG*) ((uint64)*ptr + 0xFFFF800000000000); 6 | int entries = (mcfg->h.length - 44) / 16; //The first entry is 44 byte from the start of\ 7 | the table, and each entry is 16 bytes long 8 | for(int i = 0; i < entries; i++) 9 | { 10 | struct ENCHANCED_CONFIG_BAR_t *config_bar = ((uint8*)mcfg) + 44 + 16*i; 11 | for(int bus = config_bar->StartPCIBusNum; bus < config_bar->EndPCIBusNum; bus++) 12 | { 13 | for(int device = 0; device < 32; device++) 14 | { 15 | uint64 *MMIOAddr = config_bar->BAR + ((bus - config_bar->StartPCIBusNum) << 20 | device << 15); 16 | struct PciDevice_t PciDevice; 17 | vmmap(MMIOAddr, (uint64)MMIOAddr + 0xFFFF800000000000, 4096, 3); //One extended configuration address space is now 4K 18 | MMIOAddr = (uint64)MMIOAddr + 0xFFFF800000000000; 19 | memcpy_fast(((uint64)&PciDevice) + 8, MMIOAddr, 16); //The size of the dev info is 16 bytes 20 | if(PciDevice.VendorID != 0xFFFF && PciDevice.VendorID) 21 | { 22 | for(int i = 0; i < lastPciDevice; i++) 23 | { 24 | if(PciDevices[i]->Bus == bus && PciDevices[i]->Device == device && PciDevices[i]->Function == 0) 25 | { 26 | PciDevices[i]->MMIO = true; 27 | PciDevices[i]->Address = MMIOAddr; 28 | break; 29 | } 30 | } 31 | } 32 | //Mem Addr = ECAM BAR + Bus num * 0x100000 + Dev num * 0x8000 + Func num * 0x1000 + Reg offset 33 | //For more information, look at http://www.csit-sun.pub.ro/~cpop/Documentatie_SMP/Intel_Microprocessor_Systems/Intel_ProcessorNew/Intel%20White%20Paper/Accessing%20PCI%20Express%20Configuration%20Registers%20Using%20Intel%20Chipsets.pdf 34 | } 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /kernel/src/drivers/pcie/pcie.h: -------------------------------------------------------------------------------- 1 | #ifndef PCIe_H 2 | #define PCIe_H 3 | 4 | #include "../acpi/acpi.h" 5 | #include "../pci/pci.h" 6 | 7 | struct MCFG 8 | { 9 | struct ACPI_SDTHeader_t h; 10 | //Aaaaaaaaaaaaaaaand here would be the BAR's for each enchanced access mechanism\ 11 | but, were going to use the ptr + x to calculate the address, and then access the data. LOL 12 | } __attribute__((packed)); 13 | 14 | struct ENCHANCED_CONFIG_BAR_t 15 | { 16 | uint64 BAR; 17 | uint16 PCISegNum; //PCI Segment group number 18 | uint8 StartPCIBusNum; //Start pci bus number decoded by this host bridge 19 | uint8 EndPCIBusNum; //End pci bus number decoded by this host bridge 20 | uint32 reserved; 21 | } __attribute__((packed)); 22 | 23 | void acpiParsePCIe(uint32 *ptr); 24 | 25 | #endif -------------------------------------------------------------------------------- /kernel/src/drivers/pit/pit.c: -------------------------------------------------------------------------------- 1 | #include "pit.h" 2 | 3 | bool pit_sleeping = false; 4 | uint32 pit_countdown = 0; 5 | 6 | void pitInit(uint16 freq) 7 | { 8 | outportb(0x43, 0x34); //Mode 4, lobyte/hibyte, channel 0 9 | uint16 div = (1193181 /*standard pit freq*/ / freq); 10 | outportb(0x40, div & 0xFF); 11 | outportb(0x40, div >> 8); 12 | ChangeTimer("PIT"); 13 | } 14 | 15 | void pitDisable() 16 | { 17 | outportb(0x43, 0b11000); //Irq in terminal count, lobyte/hibyte, channel 0 18 | uint16 div = 0xFFFF; 19 | outportb(0x40, div & 0xFF); 20 | outportb(0x40, div >> 8); 21 | pitSleep(1, 3); //Wait until next pit interrupt 22 | } 23 | 24 | void pitHandler() 25 | { 26 | if(pit_sleeping) 27 | { 28 | if(pit_countdown) 29 | { 30 | pit_countdown--; //We've passed ~1 milisecs 31 | } else { 32 | pit_sleeping = false; 33 | } 34 | } 35 | return; 36 | } 37 | 38 | void pitSleep(uint64 time, uint8 type) 39 | { 40 | if(type < 3) return; //With pit we can only sleep in miliseconds, sadly.... (i mean, we can do more, but not for the freq we have set up) 41 | pit_countdown = time; 42 | if(pit_countdown > 0) 43 | { 44 | pit_sleeping = true; 45 | while(pit_sleeping && pit_countdown) asm volatile("hlt"); //Halt CPU until next interrupt arrives 46 | } 47 | return; 48 | } 49 | -------------------------------------------------------------------------------- /kernel/src/drivers/pit/pit.h: -------------------------------------------------------------------------------- 1 | #ifndef PIT_H 2 | #define PIT_H 3 | 4 | #include "../../string/types.h" 5 | #include "../../arch/x86/cpu.h" 6 | 7 | void pitInit(uint16 div); 8 | void pitHandler(); 9 | void pitSleep(uint64 time, uint8 type); 10 | void pitDisable(); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /kernel/src/drivers/rtc/rtc.c: -------------------------------------------------------------------------------- 1 | #include "rtc.h" 2 | 3 | #define ADDRESS_REG 0x70 4 | #define DATA_REG 0x71 5 | 6 | /* Values/Commands for RTC Registers */ 7 | #define SECOND 0x00 //Second 00-59 8 | #define MINUTE 0x02 //Minute 00-59 9 | #define HOUR 0x04 //Hour 00-23 10 | #define DAY_OF_WEEK 0x06 //Day of Week 01-0DAY 11 | #define DAY 0x07 //Day 00-31 12 | #define MONTH 0x08 //Month 00-12 13 | #define YEAR 0x09 //Year 00-99 14 | 15 | uint8 Century_reg = 0; 16 | 17 | void setRTCenturyReg(uint8 value) 18 | { 19 | Century_reg = value; 20 | } 21 | 22 | uint8 uint_to_bcd(uint8 value) 23 | { 24 | uint8 hi, lo; 25 | if(value > 99) 26 | { 27 | return 0xFF; 28 | }; 29 | lo = value % 10; 30 | hi = (value / 10); 31 | hi *= 16; 32 | return hi | lo; 33 | } 34 | 35 | int bcd_to_int(uint8 bcd) 36 | { 37 | char characters[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; 38 | int ret = 0; 39 | ret = ((bcd & 0xF0) >> 4) * 10 + (bcd & 0xF); 40 | return ret; 41 | } 42 | 43 | /* Function to Get any RTC Parameter */ 44 | uint8 get_RTC_val(uint8 param) 45 | { 46 | CPUDisableInts(); 47 | outportb(ADDRESS_REG, param); 48 | CPUEnableInts(); 49 | return inportb(DATA_REG); 50 | } 51 | 52 | bool isupdateinprogress() 53 | { 54 | return get_RTC_val(0x0A) & 0x80; 55 | } 56 | 57 | /* Function to Set any RTC Parameter */ 58 | void set_RTC_val(uint8 setVal) 59 | { 60 | CPUDisableInts(); 61 | outportb(ADDRESS_REG, setVal); 62 | outportb(setVal, DATA_REG); 63 | CPUEnableInts(); 64 | } 65 | 66 | int getRtc(int option) 67 | { 68 | //Option; 0 = second, 1 = minute, 2 = hour, 3 = day, 4 = month, 5 = year 69 | uint8 second, lastsecond, minute, lastminute, hour,lasthour, day,lastday,month,lastmonth, year, lastyear, century, lastcentury; 70 | while(isupdateinprogress()); 71 | second = get_RTC_val(SECOND); 72 | minute = get_RTC_val(MINUTE); 73 | hour = get_RTC_val(HOUR); 74 | day = get_RTC_val(DAY); 75 | month = get_RTC_val(MONTH); 76 | year = get_RTC_val(YEAR); 77 | if(Century_reg != 0) 78 | { 79 | century = get_RTC_val(Century_reg); 80 | } 81 | do 82 | { 83 | lastsecond = second; 84 | lastminute = minute; 85 | lasthour = hour; 86 | lastday = day; 87 | lastmonth = month; 88 | lastyear = year; 89 | lastcentury = century; 90 | while(isupdateinprogress()); 91 | second = get_RTC_val(SECOND); 92 | minute = get_RTC_val(MINUTE); 93 | hour = get_RTC_val(HOUR); 94 | day = get_RTC_val(DAY); 95 | month = get_RTC_val(MONTH); 96 | year = get_RTC_val(YEAR); 97 | if(Century_reg != 0) 98 | { 99 | century = get_RTC_val(Century_reg); 100 | } 101 | } while((lastsecond != second) || (lastminute != minute) || (lasthour != hour) || (lastday !=day) || (lastmonth != month) || (lastyear != year) || (lastcentury != century)); 102 | if(option == 0) 103 | { 104 | return bcd_to_int(second); 105 | } else if(option == 1) { 106 | return bcd_to_int(minute); 107 | } else if(option == 2) { 108 | return bcd_to_int(hour); 109 | } else if(option == 3) { 110 | return bcd_to_int(day); 111 | } else if(option == 4) { 112 | return bcd_to_int(month); 113 | } else if(option == 5) { 114 | if(Century_reg) return (bcd_to_int(year) + bcd_to_int(century)*100); 115 | else 116 | { 117 | int Year = bcd_to_int(year) + (2021/100)*100; 118 | if(Year < 2021) return Year+100; 119 | return Year; 120 | } 121 | } 122 | return NULL; 123 | } 124 | -------------------------------------------------------------------------------- /kernel/src/drivers/rtc/rtc.h: -------------------------------------------------------------------------------- 1 | #ifndef BCD__H 2 | #define BCD__H 3 | 4 | #include "../../arch/x86/cpu.h" 5 | 6 | void setRTCenturyReg(uint8 value); 7 | uint8 get_RTC_val(uint8 param); 8 | void set_RTC_val(uint8 setVal); 9 | int getRtc(int option); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /kernel/src/drivers/sleep/sleep.c: -------------------------------------------------------------------------------- 1 | #include "sleep.h" 2 | 3 | string TimerUsed = ""; //None.... 4 | 5 | string getUsedTimer() 6 | { 7 | return TimerUsed; 8 | } 9 | 10 | void ChangeTimer(string timer) 11 | { 12 | if(TimerUsed == "") TimerUsed = kmalloc(16); 13 | memset(TimerUsed, 0, 16); 14 | memcpy(TimerUsed, timer, strlen(timer)); 15 | } 16 | 17 | void sleep(uint64 time, uint8 type) 18 | { 19 | if(memcmp(TimerUsed, "APIC",4) == 0) 20 | { 21 | lapicTimerSleep(time, type); 22 | } else if(memcmp(TimerUsed, "PIT",3) == 0){ 23 | pitSleep(time, type); 24 | } else if(memcmp(TimerUsed, "HPET",4) == 0) { 25 | HpetSleep(time, type); 26 | //Do what i gotta do 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /kernel/src/drivers/sleep/sleep.h: -------------------------------------------------------------------------------- 1 | #ifndef SLEEP_H 2 | #define SLEEP_H 3 | 4 | #define SleepFemto 0 //Smallest 5 | #define SleepPico 1 6 | #define SleepNano 2 7 | #define SleepMicro 3 8 | #define SleepMili 4 9 | 10 | #include "../../string/types.h" 11 | #include "../pit/pit.h" 12 | #include "../../arch/x86/lapic.h" 13 | 14 | void ChangeTimer(string val); 15 | string getUsedTimer(); 16 | void sleep(uint64 time, uint8 type); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /kernel/src/drivers/vesa/vesa.c: -------------------------------------------------------------------------------- 1 | #include "vesa.h" 2 | 3 | extern inline void VesaPutPixel(int x, int y, int color); 4 | extern inline void VesaPutLine(int x, int y, int color, int size); 5 | 6 | void VesaInit() 7 | { 8 | fb = get_mboot_info(multiboot_tag_TYPE_FRAMEBUFFER); 9 | framebuffer = fb->common.framebuffer_addr; 10 | //asm volatile("mov %0, %%r11\nxchgw %%bx, %%bx" : : "g" (framebuffer) : "r11", "ebx"); 11 | id_vmmap(fb->common.framebuffer_addr, fb->common.framebuffer_width*fb->common.framebuffer_height*(fb->common.framebuffer_bpp/*/8*/)/*bpp*/, 3 | (1 << 6) /*uncacheable*/); 12 | } 13 | -------------------------------------------------------------------------------- /kernel/src/drivers/vesa/vesa.h: -------------------------------------------------------------------------------- 1 | #ifndef VESA_H 2 | #define VESA_H 3 | 4 | #include "../../grub/multiboot.h" 5 | #include "../../memory/paging.h" 6 | 7 | //static inline void VesaPutPixel(int x, int y, int color); 8 | //static inline void VesaPutLine(int x, int y, int color, int size); 9 | 10 | struct multiboot_tag_framebuffer *fb; 11 | uint32 *framebuffer; 12 | 13 | inline void VesaPutPixel(int x, int y, int color) 14 | { 15 | uint32 pixel_offset = y * fb->common.framebuffer_width + x; 16 | framebuffer[pixel_offset] = color; 17 | } 18 | 19 | inline void VesaPutLine(int x, int y, int color, int size) 20 | { 21 | uint32 pixel_offset = y * fb->common.framebuffer_width + x; 22 | while(size--) framebuffer[pixel_offset++] = color; 23 | } 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /kernel/src/grub/multiboot.c: -------------------------------------------------------------------------------- 1 | #include "multiboot.h" 2 | 3 | struct mboot_info_t *mboot_info; 4 | 5 | void GetUsableMem(uint64 addr, uint64 kernel_end) 6 | { 7 | struct multiboot_tag *mtag = addr + 8; 8 | for(mtag = addr+8; mtag->type != multiboot_tag_TYPE_END; mtag = (uint8*)mtag + ((mtag->size + 7) & ~7)) 9 | { 10 | if(mtag->type == multiboot_tag_TYPE_MMAP) 11 | { 12 | multiboot_memory_map_t *mmap; 13 | for(mmap = ((struct multiboot_tag_mmap*)mtag)->entries; (uint8*)mmap < (uint8*)mtag + mtag->size; mmap = (multiboot_memory_map_t*)((uint64)mmap + ((struct multiboot_tag_mmap*)mtag)->entry_size)) 14 | { 15 | if(mmap->type != 5) 16 | { 17 | vmmap(mmap->addr, mmap->addr + 0xFFFF800000000000, mmap->len, 3); 18 | if(mmap->type == 1) 19 | { 20 | if(mmap->addr > kernel_end) 21 | { 22 | heapAddBlock((uint64)mmap->addr + 0xFFFF800000000000, mmap->len); 23 | } else if(mmap->len + mmap->addr > kernel_end) { 24 | heapAddBlock(kernel_end + 0xFFFF800000000000, mmap->len - kernel_end); 25 | } 26 | } 27 | } 28 | } 29 | break; 30 | } 31 | } 32 | } 33 | 34 | int parseMultiboot(uint64 addr, uint64 kernel_end) 35 | { 36 | kernel_end -= 0xFFFF800000000000; 37 | GetUsableMem(addr, kernel_end); 38 | mboot_info = kmalloc(sizeof(struct mboot_info_t)); 39 | memzero(mboot_info, sizeof(struct mboot_info_t)); 40 | struct multiboot_tag *mtag; 41 | for(mtag = addr+8; mtag->type != multiboot_tag_TYPE_END; mtag = (uint8*)mtag + ((mtag->size + 7) & ~7)) 42 | { 43 | switch(mtag->type) 44 | { 45 | case multiboot_tag_TYPE_CMDLINE: 46 | /*print("Command line is "); 47 | print(((struct multiboot_tag_string*)mtag)->string); 48 | print("\n");*/ 49 | break; 50 | case multiboot_tag_TYPE_BOOT_LOADER_NAME: 51 | mboot_info->name = ((struct multiboot_tag_string*)mtag)->string; 52 | break; 53 | case multiboot_tag_TYPE_MODULE: 54 | break; 55 | case multiboot_tag_TYPE_BASIC_MEMINFO: 56 | break; 57 | case multiboot_tag_TYPE_BOOTDEV: 58 | break; 59 | case multiboot_tag_TYPE_MMAP: 60 | { 61 | mboot_info->mboot_mmap = kmalloc(20 * sizeof(multiboot_memory_map_t)/*8*/); //Up to 20 maps (each one is a memory pointer, so counts as 8 bytes (64bits) per address) 62 | multiboot_memory_map_t *mmap; 63 | int tmp = 0; 64 | for(mmap = ((struct multiboot_tag_mmap*)mtag)->entries; (uint8*)mmap < (uint8*)mtag + mtag->size; mmap = (multiboot_memory_map_t*)((uint64)mmap + ((struct multiboot_tag_mmap*)mtag)->entry_size)) 65 | { 66 | //mboot_info->mboot_mmap[tmp] = kmalloc(sizeof(multiboot_memory_map_t)); 67 | multiboot_memory_map_t *map = &mboot_info->mboot_mmap[tmp]; 68 | map->addr = mmap->addr; 69 | map->len = mmap->len; 70 | map->type = mmap->type; 71 | tmp++; 72 | } 73 | mboot_info->maps = tmp; 74 | break; 75 | } 76 | case multiboot_tag_TYPE_VBE: ; 77 | mboot_info->mboot_vbe_info = kmalloc(sizeof(struct multiboot_tag_vbe)); 78 | struct multiboot_tag_vbe *vbetag = (struct multiboot_tag_vbe*)mtag; 79 | *mboot_info->mboot_vbe_info = *vbetag; 80 | break; 81 | case multiboot_tag_TYPE_FRAMEBUFFER: ; 82 | mboot_info->mboot_fb = kmalloc(sizeof(struct multiboot_tag_framebuffer)); 83 | struct multiboot_tag_framebuffer *fbtag = (struct multiboot_tag_framebuffer*)mtag; 84 | *mboot_info->mboot_fb = *fbtag; 85 | break; 86 | case multiboot_tag_TYPE_ELF_SECTIONS: 87 | break; 88 | case multiboot_tag_TYPE_APM: 89 | break; 90 | case multiboot_tag_TYPE_EFI32: 91 | break; 92 | case multiboot_tag_TYPE_EFI64: 93 | break; 94 | case multiboot_tag_TYPE_SMBIOS: 95 | break; 96 | case multiboot_tag_TYPE_ACPI_OLD: 97 | mboot_info->mboot_acpi = mtag; 98 | break; 99 | case multiboot_tag_TYPE_ACPI_NEW: 100 | mboot_info->mboot_acpi = mtag; 101 | break; 102 | case multiboot_tag_TYPE_NETWORK: 103 | break; 104 | case multiboot_tag_TYPE_EFI_MMAP: 105 | break; 106 | case multiboot_tag_TYPE_EFI_BS: 107 | break; 108 | case multiboot_tag_TYPE_EFI32_IH: 109 | break; 110 | case multiboot_tag_TYPE_EFI64_IH: 111 | break; 112 | case multiboot_tag_TYPE_LOAD_BASE_ADDR: 113 | break; 114 | } 115 | } 116 | } 117 | 118 | void *get_mboot_info(uint8 type) //Get a ptr to the info 119 | { 120 | if(type == multiboot_tag_TYPE_BOOT_LOADER_NAME) 121 | { 122 | return mboot_info->name; 123 | } else if(type == 23) { 124 | return (void*)mboot_info->maps; 125 | } else if(type == multiboot_tag_TYPE_MMAP) { 126 | return (void*)mboot_info->mboot_mmap; 127 | } else if(type == multiboot_tag_TYPE_VBE) { 128 | return (void*)mboot_info->mboot_vbe_info; 129 | } else if(type == multiboot_tag_TYPE_FRAMEBUFFER) { 130 | return (void*)mboot_info->mboot_fb; //Its already a pointer 131 | } else if(type == multiboot_tag_TYPE_ACPI_OLD || type == multiboot_tag_TYPE_ACPI_NEW) { 132 | return (void*)mboot_info->mboot_acpi; 133 | } 134 | return 0; 135 | } 136 | -------------------------------------------------------------------------------- /kernel/src/grub/multiboot.h: -------------------------------------------------------------------------------- 1 | #include "../string/types.h" 2 | #include "../memory/paging.h" 3 | #include "../memory/pmm.h" 4 | 5 | #ifndef HEADER 6 | #define HEADER 1 7 | 8 | /* How many bytes from the start of the file we search for the header. */ 9 | #define SEARCH 32768 10 | #define HEADER_ALIGN 8 11 | 12 | /* The magic field should contain this. */ 13 | #define MULTIBOOT2_HEADER_MAGIC 0xe85250d6 14 | 15 | /* This should be in %eax. */ 16 | #define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289 17 | 18 | /* Alignment of multiboot modules. */ 19 | #define MOD_ALIGN 0x00001000 20 | 21 | /* Alignment of the multiboot info structure. */ 22 | #define INFO_ALIGN 0x00000008 23 | 24 | /* Flags set in the ’flags’ member of the multiboot header. */ 25 | 26 | #define multiboot_tag_ALIGN 8 27 | #define multiboot_tag_TYPE_END 0 28 | #define multiboot_tag_TYPE_CMDLINE 1 29 | #define multiboot_tag_TYPE_BOOT_LOADER_NAME 2 30 | #define multiboot_tag_TYPE_MODULE 3 31 | #define multiboot_tag_TYPE_BASIC_MEMINFO 4 32 | #define multiboot_tag_TYPE_BOOTDEV 5 33 | #define multiboot_tag_TYPE_MMAP 6 34 | #define multiboot_tag_TYPE_VBE 7 35 | #define multiboot_tag_TYPE_FRAMEBUFFER 8 36 | #define multiboot_tag_TYPE_FRAMEBUFFER_ADDR 22 37 | #define multiboot_tag_TYPE_ELF_SECTIONS 9 38 | #define multiboot_tag_TYPE_APM 10 39 | #define multiboot_tag_TYPE_EFI32 11 40 | #define multiboot_tag_TYPE_EFI64 12 41 | #define multiboot_tag_TYPE_SMBIOS 13 42 | #define multiboot_tag_TYPE_ACPI_OLD 14 43 | #define multiboot_tag_TYPE_ACPI_NEW 15 44 | #define multiboot_tag_TYPE_NETWORK 16 45 | #define multiboot_tag_TYPE_EFI_MMAP 17 46 | #define multiboot_tag_TYPE_EFI_BS 18 47 | #define multiboot_tag_TYPE_EFI32_IH 19 48 | #define multiboot_tag_TYPE_EFI64_IH 20 49 | #define multiboot_tag_TYPE_LOAD_BASE_ADDR 21 50 | 51 | #define HEADER_TAG_END 0 52 | #define HEADER_TAG_INFORMATION_REQUEST 1 53 | #define HEADER_TAG_ADDRESS 2 54 | #define HEADER_TAG_ENTRY_ADDRESS 3 55 | #define HEADER_TAG_CONSOLE_FLAGS 4 56 | #define HEADER_TAG_FRAMEBUFFER 5 57 | #define HEADER_TAG_MODULE_ALIGN 6 58 | #define HEADER_TAG_EFI_BS 7 59 | #define HEADER_TAG_ENTRY_ADDRESS_EFI32 8 60 | #define HEADER_TAG_ENTRY_ADDRESS_EFI64 9 61 | #define HEADER_TAG_RELOCATABLE 10 62 | 63 | #define ARCHITECTURE_I386 0 64 | #define ARCHITECTURE_MIPS32 4 65 | #define HEADER_TAG_OPTIONAL 1 66 | 67 | #define LOAD_PREFERENCE_NONE 0 68 | #define LOAD_PREFERENCE_LOW 1 69 | #define LOAD_PREFERENCE_HIGH 2 70 | 71 | #define CONSOLE_FLAGS_CONSOLE_REQUIRED 1 72 | #define CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2 73 | 74 | int parseMultiboot(uint64 addr, uint64 kernel_end); 75 | 76 | #ifndef ASM_FILE 77 | 78 | struct multiboot_header 79 | { 80 | /* Must be MAGIC - see above. */ 81 | uint32 magic; 82 | 83 | /* ISA */ 84 | uint32 architecture; 85 | 86 | /* Total header length. */ 87 | uint32 header_length; 88 | 89 | /* The above fields plus this one must equal 0 mod 2^32. */ 90 | uint32 checksum; 91 | }; 92 | 93 | struct multiboot_header_tag 94 | { 95 | uint16 type; 96 | uint16 flags; 97 | uint32 size; 98 | }; 99 | 100 | struct multiboot_header_tag_information_request 101 | { 102 | uint16 type; 103 | uint16 flags; 104 | uint32 size; 105 | uint32 requests[0]; 106 | }; 107 | 108 | struct multiboot_header_tag_address 109 | { 110 | uint16 type; 111 | uint16 flags; 112 | uint32 size; 113 | uint32 header_addr; 114 | uint32 load_addr; 115 | uint32 load_end_addr; 116 | uint32 bss_end_addr; 117 | }; 118 | 119 | struct multiboot_header_tag_entry_address 120 | { 121 | uint16 type; 122 | uint16 flags; 123 | uint32 size; 124 | uint32 entry_addr; 125 | }; 126 | 127 | struct multiboot_header_tag_console_flags 128 | { 129 | uint16 type; 130 | uint16 flags; 131 | uint32 size; 132 | uint32 console_flags; 133 | }; 134 | 135 | struct multiboot_header_tag_framebuffer 136 | { 137 | uint16 type; 138 | uint16 flags; 139 | uint32 size; 140 | uint32 width; 141 | uint32 height; 142 | uint32 depth; 143 | }; 144 | 145 | struct multiboot_header_tag_module_align 146 | { 147 | uint16 type; 148 | uint16 flags; 149 | uint32 size; 150 | }; 151 | 152 | struct multiboot_header_tag_relocatable 153 | { 154 | uint16 type; 155 | uint16 flags; 156 | uint32 size; 157 | uint32 min_addr; 158 | uint32 max_addr; 159 | uint32 align; 160 | uint32 preference; 161 | }; 162 | 163 | struct color 164 | { 165 | uint8 red; 166 | uint8 green; 167 | uint8 blue; 168 | }; 169 | 170 | struct mmap_entry 171 | { 172 | uint64 addr; 173 | uint64 len; 174 | #define MEMORY_AVAILABLE 1 175 | #define MEMORY_RESERVED 2 176 | #define MEMORY_ACPI_RECLAIMABLE 3 177 | #define MEMORY_NVS 4 178 | #define MEMORY_BADRAM 5 179 | uint32 type; 180 | uint32 zero; 181 | }; 182 | 183 | typedef struct mmap_entry multiboot_memory_map_t; 184 | 185 | struct multiboot_tag 186 | { 187 | uint32 type; 188 | uint32 size; 189 | }; 190 | 191 | struct multiboot_tag_string 192 | { 193 | uint32 type; 194 | uint32 size; 195 | char string[0]; 196 | }; 197 | 198 | struct multiboot_tag_module 199 | { 200 | uint32 type; 201 | uint32 size; 202 | uint32 mod_start; 203 | uint32 mod_end; 204 | char cmdline[0]; 205 | }; 206 | 207 | struct multiboot_tag_basic_meminfo 208 | { 209 | uint32 type; 210 | uint32 size; 211 | uint32 mem_lower; 212 | uint32 mem_upper; 213 | }; 214 | 215 | struct multiboot_tag_bootdev 216 | { 217 | uint32 type; 218 | uint32 size; 219 | uint32 biosdev; 220 | uint32 slice; 221 | uint32 part; 222 | }; 223 | 224 | struct multiboot_tag_mmap 225 | { 226 | uint32 type; 227 | uint32 size; 228 | uint32 entry_size; 229 | uint32 entry_version; 230 | struct mmap_entry entries[0]; 231 | }; 232 | 233 | struct vbe_info_block 234 | { 235 | uint8 external_specification[512]; 236 | }; 237 | 238 | struct vbe_mode_info_block 239 | { 240 | uint8 external_specification[256]; 241 | }; 242 | 243 | struct multiboot_tag_vbe 244 | { 245 | uint32 type; 246 | uint32 size; 247 | 248 | uint16 vbe_mode; 249 | uint16 vbe_interface_seg; 250 | uint16 vbe_interface_off; 251 | uint16 vbe_interface_len; 252 | 253 | struct vbe_info_block vbe_control_info; 254 | struct vbe_mode_info_block vbe_mode_info; 255 | }; 256 | 257 | struct multiboot_tag_framebuffer_common 258 | { 259 | uint32 type; 260 | uint32 size; 261 | 262 | uint64 framebuffer_addr; 263 | uint32 framebuffer_pitch; 264 | uint32 framebuffer_width; 265 | uint32 framebuffer_height; 266 | uint8 framebuffer_bpp; 267 | #define FRAMEBUFFER_TYPE_INDEXED 0 268 | #define FRAMEBUFFER_TYPE_RGB 1 269 | #define FRAMEBUFFER_TYPE_EGA_TEXT 2 270 | uint8 framebuffer_type; 271 | uint16 reserved; 272 | }; 273 | 274 | struct multiboot_tag_framebuffer 275 | { 276 | struct multiboot_tag_framebuffer_common common; 277 | 278 | union 279 | { 280 | struct 281 | { 282 | uint16 framebuffer_palette_num_colors; 283 | struct color framebuffer_palette[0]; 284 | }; 285 | struct 286 | { 287 | uint8 framebuffer_red_field_position; 288 | uint8 framebuffer_red_mask_size; 289 | uint8 framebuffer_green_field_position; 290 | uint8 framebuffer_green_mask_size; 291 | uint8 framebuffer_blue_field_position; 292 | uint8 framebuffer_blue_mask_size; 293 | }; 294 | }; 295 | }; 296 | 297 | struct multiboot_tag_elf_sections 298 | { 299 | uint32 type; 300 | uint32 size; 301 | uint32 num; 302 | uint32 entsize; 303 | uint32 shndx; 304 | char sections[0]; 305 | }; 306 | 307 | struct multiboot_tag_apm 308 | { 309 | uint32 type; 310 | uint32 size; 311 | uint16 version; 312 | uint16 cseg; 313 | uint32 offset; 314 | uint16 cseg_16; 315 | uint16 dseg; 316 | uint16 flags; 317 | uint16 cseg_len; 318 | uint16 cseg_16_len; 319 | uint16 dseg_len; 320 | }; 321 | 322 | struct multiboot_tag_efi32 323 | { 324 | uint32 type; 325 | uint32 size; 326 | uint32 pointer; 327 | }; 328 | 329 | struct multiboot_tag_efi64 330 | { 331 | uint32 type; 332 | uint32 size; 333 | uint64 pointer; 334 | }; 335 | 336 | struct multiboot_tag_smbios 337 | { 338 | uint32 type; 339 | uint32 size; 340 | uint8 major; 341 | uint8 minor; 342 | uint8 reserved[6]; 343 | uint8 tables[0]; 344 | }; 345 | 346 | struct multiboot_tag_acpi 347 | { 348 | uint32 type; 349 | uint32 size; 350 | uint8 rsdp[0]; 351 | }; 352 | 353 | struct multiboot_tag_network 354 | { 355 | uint32 type; 356 | uint32 size; 357 | uint8 dhcpack[0]; 358 | }; 359 | 360 | struct multiboot_tag_efi_mmap 361 | { 362 | uint32 type; 363 | uint32 size; 364 | uint32 descr_size; 365 | uint32 descr_vers; 366 | uint8 efi_mmap[0]; 367 | }; 368 | 369 | struct multiboot_tag_efi32_ih 370 | { 371 | uint32 type; 372 | uint32 size; 373 | uint32 pointer; 374 | }; 375 | 376 | struct multiboot_tag_efi64_ih 377 | { 378 | uint32 type; 379 | uint32 size; 380 | uint64 pointer; 381 | }; 382 | 383 | struct multiboot_tag_load_base_addr 384 | { 385 | uint32 type; 386 | uint32 size; 387 | uint32 load_base_addr; 388 | }; 389 | 390 | struct mboot_info_t 391 | { 392 | uint32 name; 393 | uint32 maps; 394 | struct multiboot_tag_vbe *mboot_vbe_info; 395 | struct multiboot_tag_framebuffer *mboot_fb; 396 | struct multiboot_tag_acpi *mboot_acpi; 397 | multiboot_memory_map_t *mboot_mmap; 398 | }__attribute__((packed)); 399 | 400 | void *get_mboot_info(uint8 type); 401 | 402 | #endif /* ! ASM_FILE */ 403 | 404 | #endif /* ! HEADER */ 405 | -------------------------------------------------------------------------------- /kernel/src/kernel.c: -------------------------------------------------------------------------------- 1 | #include "kernel.h" 2 | #include "kernel/src/memory/pmm (pep).h" 3 | 4 | extern uint8 kernel_end; 5 | 6 | void kmain() 7 | { 8 | uint64 mboot_addr = 0; 9 | asm volatile("mov %%rbx, %0" : "=b" (mboot_addr) : :); 10 | dosetup(mboot_addr+0xFFFF800000000000, &kernel_end); 11 | 12 | printf("\nBooted with %s\n>", get_mboot_info(multiboot_tag_TYPE_BOOT_LOADER_NAME)); 13 | last_str = ""; 14 | end_str = 0; 15 | 16 | while(1) 17 | { 18 | if(end_str) 19 | { 20 | end_str = 0; 21 | string comm = last_str; 22 | if(strEql(comm, "help")) 23 | { 24 | comm += 4; //info characters 25 | if(comm[0] == '\0') //There's nothing specific to ask 26 | { 27 | printf("List of comands available:\n help - Shows information about one or all commands\n shutdown - Turns off the PC\n reboot - Reboots the PC\n clear - Clears the screen\n time - Show the actual time\n"); 28 | printf(" info - Show information about different things in the PC\n echo - Print what you write after the command\n install $a,$b - Copies the contents of drive $a into drive $b. It is assumed that drive $a contains the operating system from which the computer has booted on.\n"); 29 | } else { 30 | print("Command not recognized. Check for the syntax or if the command is available\n"); 31 | } 32 | } else if(strncmp(comm, "info", 4) == 0) { 33 | comm += 4; 34 | if(comm[0] == '\0') 35 | { 36 | printf("Use this command to show information. All the options to 'info' are:\n"); 37 | printf(" cpu - Show information about the cpu\n pci - Show information about pci devices & buses\n mem - Show memory map\n disks - Show general information about present ATA Devices\n disk $n - Show extended information about disk number n\n"); 38 | } else if(strEql(comm, " cpu")) { 39 | printf("Processor Brand: %s\nProcessor Name: %s\nCores: %i\nStepping: %i\n", cpu_info.brand, cpu_info.name, acpi_pm_info->cpus, cpu_info.stepping); 40 | } else if(strEql(comm, " devices")) { 41 | AcpiDumpNamespace(); 42 | } else if(strEql(comm, " pci")) { 43 | for(int i = 0; i < lastPciDevice; i++) 44 | { 45 | printf("Device ID:%x Vendor ID:%x Class:%x SubClass:%x Prog IF:%x\n", PciDevices[i]->DeviceID, PciDevices[i]->VendorID, PciDevices[i]->Class, PciDevices[i]->SubClass, PciDevices[i]->ProgIF); 46 | } 47 | } else if(strEql(comm, " mem")) { 48 | printf("Memory Map found:\n"); 49 | uint64 total_mem = 0; 50 | multiboot_memory_map_t *mmapp = get_mboot_info(multiboot_tag_TYPE_MMAP); 51 | for(uint64 i = 0; i < (uint64)get_mboot_info(23); i++) //Number of maps are returned as the pointer to the variable that contains the amount of maps 52 | { 53 | multiboot_memory_map_t *mmap = &mmapp[i]; 54 | printf("Address: %x Length: %iKB Type: ", mmap->addr, mmap->len / 1024); 55 | if(mmap->type == MEMORY_AVAILABLE) 56 | { 57 | printcolor("Free", 0, 0x1FFC00); 58 | total_mem += mmap->len; 59 | } else if(mmap->type == MEMORY_RESERVED) { 60 | printcolor("Reserved", 0, 0xFFFFFC00); 61 | } else if(mmap->type == MEMORY_ACPI_RECLAIMABLE) { 62 | printcolor("ACPI Claimed", 0, 0xFFFFFC00); 63 | } else if(mmap->type == MEMORY_NVS) { 64 | printcolor("NVS", 0, 0xFFFFFC00); 65 | } else { 66 | printcolor("Corrupted", 0, 0xFFE00000); 67 | } 68 | printf("\n"); 69 | } 70 | printf("Usable Memory: %iMB\n", total_mem / (1024 * 1024)); 71 | } else if(strEql(comm, " disks")) { //All disks present 72 | if(ata_devices.dev_amount == 0) 73 | { 74 | printf("No ATA Devices present!\n"); 75 | } else { 76 | for(int i = 0; i < ata_devices.dev_amount; i++) 77 | { 78 | printf("%iMB %s %s device on ATA Bus %i\n", ata_devices.devices[i].size, ata_devices.devices[i].type, ata_devices.devices[i].slave == false ? "Master" : "Slave", ata_devices.devices[i].channel); 79 | } 80 | } 81 | } else if(strncmp(comm, " disk ", 6) == 0) { //Disk number x 82 | comm += 6; 83 | int number = 0; 84 | for(int i = 0; comm[i]; i++) 85 | { 86 | number *= 10; 87 | number += comm[i]-48; //Conversion to int 88 | } 89 | if(number >= ata_devices.dev_amount) 90 | { 91 | printf("The ATA device number %i does not exist.\n", number); 92 | } else { 93 | printf("%s %s device on bus %i\n", ata_devices.devices[number].type, ata_devices.devices[number].slave ? "Slave" : "Master", ata_devices.devices[number].channel); 94 | printf("Size:%iMB\n", ata_devices.devices[number].size); 95 | if(strEql(ata_devices.devices[number].type, "PATA") || strEql(ata_devices.devices[number].type, "SATA")) 96 | { 97 | struct ata_identify_t *info = ata_devices.devices[number].IDENTIFY_addr; 98 | printf("Serial number: %s\nModel number: %s\nFirmware revision: %s\n", info->SerNum, info->ModNum, info->FirmRev); 99 | } else if(strEql(ata_devices.devices[number].type, "Unknown") || strEql(ata_devices.devices[number].type, "PATAPI") || strEql(ata_devices.devices[number].type, "SATAPI")) { 100 | struct ata_identify_packet_t *info = ata_devices.devices[number].IDENTIFY_addr; 101 | printf("Serial number: %s\nModel number: %s\nFirmware revision: %s\n", info->SerNum, info->ModNum, info->FirmRev); 102 | } 103 | } 104 | } else { 105 | printf("Command not recognized. Check for the syntax or if the command is available\n"); 106 | } 107 | } else if(strncmp(comm, "echo", 4) == 0) { 108 | comm += 4; 109 | if(comm[0] != ' ') 110 | { 111 | printf("Command not recognized. Check for the syntax or if the command is available\n"); 112 | } else if(comm[0] == ' ' && comm[1] == '\0') { 113 | printf("\n"); 114 | } else { 115 | printf("%s\n", comm+1); 116 | } 117 | } else if(strncmp(comm, "install ", 8) == 0) { 118 | comm += 8; 119 | int SourceDrive = 0, offset = 0; 120 | for(int i = 0; comm[i] && comm[i] != ','; i++, offset++) 121 | { 122 | SourceDrive *= 10; 123 | SourceDrive += comm[i]-48; //Conversion to int 124 | } 125 | 126 | comm += offset+1; 127 | int DestDrive = 0; offset = 0; 128 | for(int i = 0; comm[i]; i++, offset++) 129 | { 130 | DestDrive *= 10; 131 | DestDrive += comm[i]-48; //Conversion to int 132 | } 133 | comm += offset + 1; 134 | printf("SourceDrive: %i, DestDrive: %i\n", SourceDrive, DestDrive); 135 | /*if(strlen(comm)) printf("ERROR: Command not recognized\n"); 136 | else*/ if(SourceDrive > ata_devices.dev_amount || DestDrive > ata_devices.dev_amount) { 137 | printf("ERROR: Disk number cannot be higher than the amount of ata drives detected by the system\n"); 138 | } else if(SourceDrive == 0 || DestDrive == 0) { 139 | printf("ERROR: Disk number cannot be lower than 1\n"); 140 | } else { 141 | uint16 *readbuf = kmalloc(64 * 1024); 142 | uint8 *completion = kmalloc(8); 143 | 144 | int i = 0; 145 | for(i = 0; (i + 31) < ata_devices.devices[SourceDrive-1].sectorCount; i+=32) 146 | { 147 | ata_read(&ata_devices.devices[SourceDrive-1], i, 32, readbuf, completion); 148 | while(*completion == 0); 149 | *completion = 0; 150 | 151 | ata_write(&ata_devices.devices[DestDrive-1], i*4, 128, readbuf, completion); 152 | while(*completion == 0); 153 | *completion = 0; 154 | 155 | printf("\r%i sectors of %i written.", i, ata_devices.devices[SourceDrive-1].sectorCount); 156 | } 157 | 158 | for(i; i < ata_devices.devices[SourceDrive-1].sectorCount; i++) 159 | { 160 | ata_read(&ata_devices.devices[SourceDrive-1], i, 1, readbuf, completion); 161 | while(*completion == 0); 162 | *completion = 0; 163 | 164 | ata_write(&ata_devices.devices[DestDrive-1], i*4, 4, readbuf, completion); 165 | while(*completion == 0); 166 | *completion = 0; 167 | 168 | printf("\r%i sectors of %i written.", i, ata_devices.devices[SourceDrive-1].sectorCount); 169 | } 170 | 171 | free(readbuf); 172 | free(completion); 173 | } 174 | } else if(strEql(comm, "shutdown")) { 175 | shutdown(); 176 | } else if(strEql(comm, "reboot")) { 177 | reboot(); 178 | } else if(strEql(comm, "clear")) { 179 | ClearScreen(); 180 | } else if(strEql(comm, "time")) { 181 | for(int i = 2; i > 0; i--) 182 | { 183 | printf("%i:", getRtc(i)); 184 | } 185 | printf("%i %i/%i/%i\n", getRtc(0), getRtc(3), getRtc(4), getRtc(5)); 186 | } else if(strlen(comm)) { 187 | printf("ERROR: Command not recognized\n"); 188 | } 189 | comm = ""; 190 | last_str = ""; 191 | printf("\n>"); 192 | } 193 | } 194 | } -------------------------------------------------------------------------------- /kernel/src/kernel.h: -------------------------------------------------------------------------------- 1 | #ifndef KERNEL_H 2 | #define KERNEL_H 3 | 4 | #include "setup/setup.h" 5 | 6 | void kmain(); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /kernel/src/memory/paging.c: -------------------------------------------------------------------------------- 1 | #include "paging.h" 2 | 3 | #define PML4_IDX (0xFFFF800000000000 >> 39) & 0x1FF 4 | #define PDPT_IDX (0xFFFF800000000000 >> 30) & 0x1FF 5 | 6 | uint64 PT[512][512] __attribute__((section(".bss"), aligned(PAGE_SIZE))); //We have one PT for each PD entry, making 512 PT's. Thats around 2MB!! 7 | uint64 PD[512][512] __attribute__((section(".bss"), aligned(PAGE_SIZE))); //We have one PD for each PDPT entry, making 512 PD's. Thats around 2MB!! 8 | uint64 *PDPT = (uint64*)(0x104000 + 0xFFFF800000000000); 9 | uint64 *PML4 = (uint64*)(0x103000 + 0xFFFF800000000000); 10 | 11 | void invlpg(uint64 addr) 12 | { 13 | asm volatile("invlpg (%0)" : : "b" (addr) : "memory"); 14 | } 15 | 16 | void vmmap(uint64 paddr, uint64 vaddr, uint64 size, uint32 flags) //Size in (atleast) PAGE_SIZEK; 17 | { 18 | paddr &= (~0xFFF); 19 | vaddr &= (~0xFFF); 20 | int PML4_idx = (vaddr >> 39) & 0x1FF; 21 | int PDPT_idx = (vaddr >> 30) & 0x1FF; 22 | int PD_idx = (vaddr >> 21) & 0x1FF; 23 | int PT_idx = (vaddr >> 12) & 0x1FF; 24 | if(size < PAGE_SIZE) 25 | { 26 | size = PAGE_SIZE; 27 | } 28 | if(PD[PDPT_idx][PD_idx] == 0) 29 | { 30 | PD[PDPT_idx][PD_idx] = (uint32)((uint64)&PT[PD_idx] - 0xFFFF800000000000) | flags; 31 | } 32 | if(PDPT[PDPT_idx] == 0) 33 | { 34 | PDPT[PDPT_idx] = (uint32)((uint64)&PD[PDPT_idx] - 0xFFFF800000000000) | flags; 35 | } 36 | if(PML4[PML4_idx] == 0) 37 | { 38 | PML4[PML4_idx] = (uint32)((uint64)PDPT - 0xFFFF800000000000) | flags; 39 | } 40 | /*if(PT[PD_idx][PT_idx] != 0) 41 | { 42 | return; 43 | }*/ 44 | for(int i = 0; i < (int)(size / PAGE_SIZE); i++, PT_idx++, paddr += PAGE_SIZE) 45 | { 46 | if(PT_idx > 511) 47 | { 48 | if(PD[PDPT_idx][PD_idx] == 0) 49 | { 50 | PD[PDPT_idx][PD_idx] = (uint32)((uint64)&PT[PD_idx] - 0xFFFF800000000000) | flags; 51 | } 52 | PT_idx = 0; 53 | PD_idx++; 54 | } 55 | if(PD_idx > 511) 56 | { 57 | if(PDPT[PDPT_idx] == 0) 58 | { 59 | PDPT[PDPT_idx] = (uint32)((uint64)&PD[PDPT_idx] - 0xFFFF800000000000) | flags; 60 | } 61 | PD_idx = 0; 62 | PDPT_idx++; 63 | } 64 | if(PDPT_idx > 511) 65 | { 66 | if(PML4[PML4_idx] == 0) 67 | { 68 | PML4[PML4_idx] = (uint32)((uint64)PDPT - 0xFFFF800000000000) | flags; 69 | } 70 | PDPT_idx = 0; 71 | PML4_idx++; 72 | } 73 | PT[PD_idx][PT_idx] = paddr | flags; 74 | } 75 | return; 76 | } 77 | 78 | void id_vmmap(uint64 addr, uint64 size, uint32 flags) 79 | { 80 | vmmap(addr, addr, size, flags); 81 | } 82 | 83 | void vmmunmap(uint64 vaddr, uint64 size) //revisar (? 84 | { 85 | vaddr &= (~0xFFF); 86 | int PML4_idx = (vaddr >> 39) & 0x1FF; 87 | int PDPT_idx = (vaddr >> 30) & 0x1FF; 88 | int PD_idx = (vaddr >> 21) & 0x1FF; 89 | int PT_idx = (vaddr >> 12) & 0x1FF; 90 | for(int i = 0; i < (int)(size / PAGE_SIZE); i++, PT_idx++) 91 | { 92 | if(PT_idx > 511) 93 | { 94 | PD[PDPT_idx][PD_idx] = 0; 95 | PD_idx++; 96 | PT_idx = 0; 97 | } 98 | if(PD_idx > 511) 99 | { 100 | PDPT[PDPT_idx] = 0; 101 | PDPT_idx++; 102 | PD_idx = 0; 103 | } 104 | if(PDPT_idx > 511) 105 | { 106 | PML4[PML4_idx] = 0; 107 | PML4_idx++; 108 | PDPT_idx = 0; 109 | } 110 | PT[PD_idx][PT_idx] = 0; 111 | vaddr += PAGE_SIZE; 112 | invlpg(vaddr); 113 | } 114 | } 115 | 116 | bool is_page_present(uint64 vaddr) 117 | { 118 | vaddr &= (~0xFFF); 119 | int PML4_idx = (vaddr >> 39) & 0x1FF; 120 | int PDPT_idx = (vaddr >> 30) & 0x1FF; 121 | int PD_idx = (vaddr >> 21) & 0x1FF; 122 | int PT_idx = (vaddr >> 12) & 0x1FF; 123 | if(PML4[PML4_idx]) 124 | { 125 | if(PDPT[PDPT_idx]) 126 | { 127 | if(PD[PDPT_idx][PD_idx]) 128 | { 129 | if(PT[PD_idx][PT_idx]) 130 | { 131 | return true; 132 | } 133 | } 134 | } 135 | } 136 | return false; 137 | } 138 | -------------------------------------------------------------------------------- /kernel/src/memory/paging.h: -------------------------------------------------------------------------------- 1 | #ifndef PAGING_H 2 | #define PAGING_H 3 | 4 | #include "../string/types.h" 5 | #include "../string/string.h" 6 | 7 | #define PAGE_SIZE 4096 8 | 9 | void remap_kernel(uint64 kernel_end); 10 | void invlpg(uint64 addr); 11 | void vmmap(uint64 paddr, uint64 vaddr, uint64 size, uint32 flags); 12 | void id_vmmap(uint64 addr, uint64 size, uint32 flags); 13 | void vmmunmap(uint64 vaddr, uint64 size); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /kernel/src/memory/pmm (pep).c: -------------------------------------------------------------------------------- 1 | #include "pmm (pep).h" 2 | 3 | struct global_heap_t global_heap __attribute__((section(".heap"))); 4 | 5 | void heapInit(uint32 block_size) 6 | { 7 | global_heap.heap = 0; 8 | //global_heap.block_size = block_size; 9 | } 10 | 11 | void heapAddBlock(uint64 base_addr, uint64 size) 12 | { 13 | struct heap_block_t *heap_block = base_addr; 14 | heap_block->next = global_heap.heap; 15 | global_heap.heap = heap_block; 16 | 17 | heap_block->size = size - sizeof(struct heap_block_t); 18 | 19 | struct heap_entry_t *heap = &heap_block[1]; 20 | heap->next = 0; 21 | heap->prev = 0; 22 | heap->size = heap_block->size - sizeof(struct heap_entry_t); 23 | heap->used = false; 24 | } 25 | 26 | void *heap_alloc(uint64 size, uint64 alignment, uint32 flags) 27 | { 28 | if(size == 0) return 0; 29 | //if(size <= sizeof(struct heap_entry_t)) size = sizeof(struct heap_entry_t); 30 | 31 | struct heap_block_t *heap_block; 32 | uint64 ptr; 33 | for(heap_block = global_heap.heap; heap_block; heap_block = heap_block->next) 34 | { 35 | struct heap_entry_t *heap; 36 | for(heap = &heap_block[1]; heap; heap = heap->next) 37 | { 38 | if(heap->used || heap->size < size) continue; 39 | 40 | uint64 ptr = &heap[1]; //skip metadata 41 | 42 | if(ptr % alignment != 0) 43 | { 44 | uint64 aligned_ptr = ((ptr + (alignment - 1)) & ~(alignment-1)); 45 | uint32 difference = aligned_ptr - ptr; 46 | if(heap->size < size + difference) continue; 47 | 48 | heap->prev->next = aligned_ptr; 49 | heap->prev->size += difference; 50 | memcpy_fast(aligned_ptr-sizeof(struct heap_entry_t), heap, sizeof(struct heap_entry_t)); 51 | 52 | heap = aligned_ptr - sizeof(struct heap_entry_t); 53 | 54 | ptr = aligned_ptr; 55 | //size += difference; 56 | } 57 | 58 | heap->used = true; 59 | if(heap->size - size > sizeof(struct heap_entry_t)) 60 | { 61 | struct heap_entry_t *merge_heap = ptr + size; 62 | memzero(merge_heap, sizeof(struct heap_entry_t)); 63 | merge_heap->prev = heap; 64 | merge_heap->next = heap->next; 65 | merge_heap->size = heap->size - size - sizeof(struct heap_entry_t); 66 | merge_heap->used = false; 67 | 68 | if(heap->next != 0) heap->next->prev = merge_heap; 69 | 70 | heap->next = merge_heap; 71 | heap->size = size; 72 | } 73 | 74 | if(ptr < 0xFFFF800000000000) ptr += 0xFFFF800000000000; 75 | 76 | memzero(ptr, size); 77 | return (void*)ptr; 78 | } 79 | } 80 | 81 | printf("Concept list ran out of mem. May want to debug the whole list here.\n"); 82 | while(1); 83 | return 0; 84 | } 85 | 86 | void heap_free(void *addr) 87 | { 88 | if(addr < 0xFFFF800000000000) addr += 0xFFFF800000000000; 89 | 90 | struct heap_entry_t *heap = (uint64)addr - sizeof(struct heap_entry_t); 91 | heap->used = false; 92 | 93 | struct heap_entry_t *merge_heap = heap->next; 94 | while(merge_heap) 95 | { 96 | if(merge_heap->used) 97 | { 98 | merge_heap->prev = heap; 99 | break; 100 | } 101 | 102 | heap->next = merge_heap->next; 103 | heap->size += merge_heap->size + sizeof(struct heap_entry_t); 104 | 105 | memzero(merge_heap, sizeof(struct heap_entry_t)); 106 | 107 | merge_heap = heap->next; 108 | } 109 | 110 | merge_heap = heap->prev; 111 | while(merge_heap) 112 | { 113 | if(merge_heap->used) 114 | { 115 | if(merge_heap->next != 0) merge_heap->next->prev = merge_heap; 116 | break; 117 | } 118 | 119 | merge_heap->next = heap->next; 120 | merge_heap->size += heap->size + sizeof(struct heap_entry_t); 121 | 122 | memzero(heap, sizeof(struct heap_entry_t)); 123 | 124 | heap = merge_heap; 125 | merge_heap = merge_heap->prev; 126 | } 127 | return; 128 | } 129 | 130 | 131 | void *kmalloc(uint64 size) 132 | { 133 | return heap_alloc(size, 1, 3); 134 | } 135 | 136 | void *malloc(uint64 size) 137 | { 138 | return heap_alloc(size, 1, 7) - 0xFFFF800000000000; 139 | } 140 | 141 | void *kmalloc_aligned(uint64 size, uint64 alignment) 142 | { 143 | return heap_alloc(size, alignment, 3); 144 | } 145 | 146 | void *malloc_aligned(uint64 size, uint64 alignment) 147 | { 148 | return heap_alloc(size, alignment, 7) - 0xFFFF800000000000; 149 | } 150 | 151 | void free(void *ptr) 152 | { 153 | heap_free(ptr); 154 | } 155 | 156 | void kill_pmm(void) 157 | { 158 | struct heap_block_t *heap_block = global_heap.heap; 159 | while(heap_block) 160 | { 161 | uint64 next_addr = heap_block->next; 162 | memzero(heap_block, heap_block->size + sizeof(struct heap_block_t)); 163 | heap_block = next_addr; 164 | } 165 | } -------------------------------------------------------------------------------- /kernel/src/memory/pmm (pep).h: -------------------------------------------------------------------------------- 1 | #ifndef PMM_H 2 | #define PMM_H 3 | 4 | #include "../string/types.h" 5 | #include "paging.h" 6 | #include "../console/console.h" 7 | 8 | struct heap_entry_t 9 | { 10 | struct heap_entry_t *prev; 11 | struct heap_entry_t *next; 12 | uint64 size : 63; 13 | uint64 used : 1; 14 | } __attribute__((packed)); 15 | 16 | struct heap_block_t 17 | { 18 | struct heap_block_t *next; 19 | //uint32 start; 20 | //uint32 max; 21 | uint64 size; 22 | } __attribute__((packed)); 23 | 24 | struct global_heap_t 25 | { 26 | struct heap_block_t *heap; 27 | //uint32 block_size; 28 | } __attribute__((packed)); 29 | 30 | void heapInit(uint32 size); 31 | void heapAddBlock(uint64 base_addr, uint64 size); 32 | void *kmalloc(uint64 size); 33 | void *malloc(uint64 size); 34 | void *kmalloc_aligned(uint64 size, uint64 alignment); 35 | void *malloc_aligned(uint64 size, uint64 alignment); 36 | void free(void *ptr); 37 | void kill_pmm(void); 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /kernel/src/memory/pmm.c: -------------------------------------------------------------------------------- 1 | #include "pmm.h" 2 | 3 | struct global_heap_t global_heap __attribute__((section(".heap"))); 4 | 5 | void heapInit(uint32 block_size) 6 | { 7 | global_heap.heap = 0; 8 | global_heap.block_size = block_size; 9 | } 10 | 11 | void heapAddBlock(uint64 base_addr, uint64 size) 12 | { 13 | struct heap_block_t *heap_block = base_addr; 14 | heap_block->next = global_heap.heap; 15 | global_heap.heap = heap_block; 16 | 17 | size -= sizeof(struct heap_block_t); 18 | heap_block->size = size; 19 | heap_block->max = size / global_heap.block_size; 20 | heap_block->start = 0; 21 | 22 | uint32 *heap = &heap_block[1]; 23 | heap[heap_block->start] = (heap_block->max-1) << 1; 24 | } 25 | 26 | void *heap_alloc(uint64 size, uint64 alignment, uint32 flags) 27 | { 28 | struct heap_block_t *heap_block; 29 | uint64 ptr; 30 | for(heap_block = global_heap.heap; heap_block; heap_block = heap_block->next) 31 | { 32 | uint32 *heap = &heap_block[1]; 33 | for(int i = heap_block->start; i < heap_block->max;) 34 | { 35 | if(heap[i] & 1 || ((heap[i] >> 1)-i +1) * global_heap.block_size < size) 36 | { 37 | i = (heap[i] >> 1) +1; 38 | continue; 39 | } 40 | uint64 ptr = (uint64)heap + i * global_heap.block_size + heap_block->max * 4; 41 | 42 | if(ptr % alignment != 0) 43 | { 44 | uint64 aligned_ptr = ((ptr + (alignment - 1)) & ~(alignment-1)); 45 | uint32 difference = aligned_ptr - ptr; 46 | if(((heap[i] >> 1)-i +1) * global_heap.block_size < size + difference) 47 | { 48 | i = (heap[i] >> 1) + 1; 49 | continue; 50 | } 51 | ptr = aligned_ptr; 52 | size += difference; 53 | 54 | int aligned_i = (aligned_ptr - (uint64)heap - heap_block->max * 4) / global_heap.block_size; 55 | heap[aligned_i] = (i << 1) | 1; 56 | } 57 | uint32 blocks_to_allocate = (size / global_heap.block_size) * global_heap.block_size < size ? (size / global_heap.block_size) + 1 : size / global_heap.block_size; 58 | 59 | if(!(heap[i+blocks_to_allocate] & 1)) heap[i+blocks_to_allocate] = heap[i]; 60 | heap[i] = ((i+blocks_to_allocate-1)<<1) | 1; 61 | 62 | if(ptr < 0xFFFF800000000000) ptr += 0xFFFF800000000000; 63 | return (void*)ptr; 64 | } 65 | } 66 | 67 | printf("FATAL: OUT OF MEMORY\n(alberinfo, please implement a proper handler ffs)\n"); while(1); 68 | return 0; 69 | } 70 | 71 | void heap_free(void *addr) 72 | { 73 | if(addr < 0xFFFF800000000000) addr += 0xFFFF800000000000; 74 | for(struct heap_block_t *heap_block = global_heap.heap; heap_block; heap_block = heap_block->next) 75 | { 76 | uint32 *heap = &heap_block[1]; 77 | if(!(addr > heap && addr < (uint64)heap + heap_block->size)) continue; //If the address isnt in the current heap's range, go to the next heap 78 | 79 | addr = (uint64)addr - (uint64)heap - heap_block->max * 4; 80 | uint32 startpoint = (uint64)addr / global_heap.block_size; 81 | uint32 endpoint = heap[startpoint] >> 1; 82 | 83 | if(endpoint < startpoint && heap[startpoint] & 1) //aligned alloc 84 | { 85 | heap[startpoint] = 0; 86 | startpoint = endpoint; 87 | endpoint = heap[startpoint] >> 1; 88 | } 89 | 90 | heap[startpoint] &= ~((uint32)1); 91 | 92 | if(endpoint + 1 < heap_block->max) 93 | { 94 | if(!(heap[endpoint + 1] & 1)) 95 | { 96 | heap[startpoint] = heap[endpoint+1]; 97 | heap[endpoint+1] = 0; 98 | } 99 | } 100 | 101 | for(int i = startpoint-1; i >= heap_block->start; i--) 102 | { 103 | if(heap[i] == 0) continue; 104 | if(heap[i] & 1) break; 105 | heap[i] = heap[startpoint]; 106 | heap[startpoint] = 0; 107 | startpoint = i; 108 | } 109 | break; 110 | } 111 | return; 112 | } 113 | 114 | 115 | void *kmalloc(uint64 size) 116 | { 117 | return heap_alloc(size, 1, 3); 118 | } 119 | 120 | void *malloc(uint64 size) 121 | { 122 | return heap_alloc(size, 1, 7) - 0xFFFF800000000000; 123 | } 124 | 125 | void *kmalloc_aligned(uint64 size, uint64 alignment) 126 | { 127 | return heap_alloc(size, alignment, 3); 128 | } 129 | 130 | void *malloc_alignment(uint64 size, uint64 alignment) 131 | { 132 | return heap_alloc(size, alignment, 7) - 0xFFFF800000000000; 133 | } 134 | 135 | void free(void *ptr) 136 | { 137 | heap_free(ptr); 138 | } 139 | 140 | void kill_pmm(void) 141 | { 142 | for(struct heap_block_t *heap_block = global_heap.heap; heap_block; heap_block = heap_block->next) 143 | { 144 | uint64 heap = &heap_block[1]; 145 | memzero(heap, heap_block->max*4); 146 | } 147 | } -------------------------------------------------------------------------------- /kernel/src/memory/pmm.h: -------------------------------------------------------------------------------- 1 | #ifndef PMM_H 2 | #define PMM_H 3 | 4 | #include "../string/types.h" 5 | #include "paging.h" 6 | #include "../console/console.h" 7 | 8 | struct heap_block_t 9 | { 10 | struct heap_block_t *next; 11 | uint32 start; 12 | uint32 max; 13 | uint64 size; 14 | } __attribute__((packed)); 15 | 16 | struct global_heap_t 17 | { 18 | struct heap_block_t *heap; 19 | uint32 block_size; 20 | } __attribute__((packed)); 21 | 22 | void heapInit(uint32 size); 23 | void heapAddBlock(uint64 base_addr, uint64 size); 24 | void *kmalloc(uint64 size); 25 | void *malloc(uint64 size); 26 | void *kmalloc_aligned(uint64 size, uint64 alignment); 27 | void *malloc_aligned(uint64 size, uint64 alignment); 28 | void free(void *ptr); 29 | void kill_pmm(void); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /kernel/src/memory/vmm.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alberinfo/Slidoor-OS/e37cc96e86b6e4b43ae82ec263b716451ad7f72f/kernel/src/memory/vmm.c -------------------------------------------------------------------------------- /kernel/src/memory/vmm.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alberinfo/Slidoor-OS/e37cc96e86b6e4b43ae82ec263b716451ad7f72f/kernel/src/memory/vmm.h -------------------------------------------------------------------------------- /kernel/src/setup/setup.c: -------------------------------------------------------------------------------- 1 | #include "setup.h" 2 | 3 | void dosetup(uint64 mboot_addr, uint64 kernel_end) 4 | { 5 | PIC_Map(); 6 | SetIsr(); 7 | SetIrq(); 8 | SetLapicSpuriousIrq(); 9 | idtInit(); 10 | heapInit(16); 11 | parseMultiboot(mboot_addr, kernel_end); 12 | VesaInit(); 13 | ConsoleInit(); 14 | kbBufferInit(); 15 | printf("[ "); 16 | printcolor("OK", 0, 0x1FFC00); 17 | printf(" ] IDT Set-UP - Done!\n"); 18 | printf("[ "); 19 | printcolor("OK", 0, 0x1FFC00); 20 | printf(" ] PMM Set-UP - Done!\n"); 21 | printf("[ "); 22 | printcolor("OK", 0,0x1FFC00); 23 | printf(" ] Multiboot Parsing - Done!\n"); 24 | pitInit(1000); //hz 25 | int AcpiStatus = initAcpi(); 26 | if(!AcpiStatus) 27 | { 28 | printf("[ "); 29 | printcolor("OK", 0, 0x1FFC00); 30 | printf(" ] ACPI Enabling - Done!\n"); 31 | } else { 32 | printf("[ "); 33 | printcolor("PANIC", 0, 0xFFE00000); 34 | printf(" ] Can't use ACPI! - Continuing...\n"); 35 | } 36 | detectCpu(); 37 | PciInit(); 38 | printf("[ "); 39 | printcolor("OK", 0, 0x1FFC00); 40 | printf(" ] PCI Bus Init - Done!\n"); 41 | if(!AcpiStatus) SMP_Start(); 42 | } -------------------------------------------------------------------------------- /kernel/src/setup/setup.h: -------------------------------------------------------------------------------- 1 | #ifndef SETUP_H 2 | #define SETUP_H 3 | 4 | #include "../arch/x86/idt.h" 5 | #include "../memory/pmm.h" 6 | #include "../drivers/vesa/vesa.h" 7 | #include "../arch/x86/cpu.h" 8 | #include "../string/types.h" 9 | #include "../drivers/kb/kb.h" 10 | #include "../grub/multiboot.h" 11 | #include "../console/fonts.h" 12 | #include "../drivers/acpi/interpreter/namespace.h" 13 | #include "../drivers/energy/energy.h" 14 | #include "../arch/x86/isr.h" 15 | #include "../memory/paging.h" 16 | #include "../drivers/sleep/sleep.h" 17 | #include "../drivers/pit/pit.h" 18 | #include "../drivers/rtc/rtc.h" 19 | #include "../grub/multiboot.h" 20 | #include "../drivers/pci/pci.h" 21 | #include "../drivers/pit/pit.h" 22 | #include "../drivers/ata/ata.h" 23 | #include "../drivers/ata/atapi.h" 24 | #include "../console/console.h" 25 | 26 | void dosetup(uint64 mboot_addr, uint64 kernel_end); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /kernel/src/string/string.h: -------------------------------------------------------------------------------- 1 | #ifndef STRING_H 2 | #define STRING_H 3 | 4 | #include "types.h" 5 | #include "../arch/x86/cpu.h" 6 | 7 | #define get_str(x) #x 8 | #define get_get_str(x) get_str(x) 9 | #define get_simd_mov_instruction_vex(ptr, avx) avx ? (ptr % 16 == 0 ? ("vmovdqa") : ("vmovdqu")) : (ptr % 16 == 0 ? ("movdqa") : ("movdqu")) 10 | 11 | char *base_convert(uint64 number, int base); 12 | void *faster_memcpy(void * _dest, const void *_src, uint32 _n); 13 | void faster_memset(void *_s, uint32 _c, uint32 _n); 14 | int memcmp(const void *_s1, const void *_s2, uint32 _n); 15 | void *memcpy(void * _dest, void *_src, uint32 _n); 16 | void* memmove(void* dstptr, const void* srcptr, uint32 uint32); 17 | void *memset(void *_s, int _c, uint32 _n); 18 | int memcmp_fast(const void *_s1, const void *_s2, uint32 _n); 19 | void *memcpy_fast(volatile void *_dest, volatile void *_src, uint32 _n); 20 | void memzero(void *_src, uint64 _n); 21 | 22 | inline void memset_fast(void *_s, uint64 _c, uint32 _n) 23 | { 24 | while(_n) 25 | { 26 | 27 | if(_n >= 8) { 28 | *(uint64*)_s = _c; 29 | _s += 8; 30 | _n -= 8; 31 | } else if(_n >= 8) { 32 | *(uint32*)_s = _c; 33 | _s += 4; 34 | _n -= 4; 35 | } else if(_n >= 2) { 36 | *(uint16*)_s = _c; 37 | _s += 2; 38 | _n -= 2; 39 | } else { 40 | *(uint8*)_s++ = _c; 41 | _n--; 42 | } 43 | } 44 | } 45 | 46 | void* memmove_fast(void* dstptr, const void* srcptr, uint32 uint32); 47 | uint32 strlen(const char *_s); 48 | int strcmp(const char *_s1, const char *_s2); 49 | int strcmpx(const char *_s1, const char *_s2); 50 | int strncmp(const char *_s1, const char *_s2, uint32 _n); 51 | char *strcpy(char *_dest, const char *_src); 52 | char *strncpy(char *_dest, const char *_src, int uint32); 53 | char *strcat(char *_dest, const char *_src); 54 | int strcmpy(const char *c1, const char *c2); 55 | char *strchr(const char *_s, int _c); 56 | uint32 strspn(const char *_s, const char *_accept); 57 | uint32 strcspn(const char *_s, const char *_reject); 58 | char *strtok(char *_s, const char *_delim); 59 | char *strstr(const char *_haystack, const char *_needle); 60 | uint32 stroccr(char* str, const char c); 61 | uint16 strlength(string ch); 62 | uint8 strEql(string ch1,string ch2); 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /kernel/src/string/types.h: -------------------------------------------------------------------------------- 1 | #ifndef TYPES_H 2 | #define TYPES_H 3 | 4 | #include 5 | 6 | typedef signed char int8; 7 | typedef unsigned char uint8; 8 | 9 | typedef signed short int16; 10 | typedef unsigned short uint16; 11 | 12 | typedef signed int int32; 13 | typedef unsigned int uint32; 14 | 15 | typedef signed long long int64; 16 | typedef unsigned long long uint64; 17 | 18 | typedef char* string; 19 | 20 | typedef _Bool bool; 21 | 22 | typedef __gnuc_va_list va_list; 23 | 24 | #define true 1 25 | #define false 0 26 | #define NULL 0 27 | 28 | //va_start, va_arg, va_end and va_copy are already defined in stdarg.h 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /link.ld: -------------------------------------------------------------------------------- 1 | ENTRY(_start); 2 | OUTPUT_FORMAT(elf64-x86-64) 3 | 4 | kern_lma = 0x100000; 5 | kern_vma = 0xFFFF800000000000; 6 | 7 | SECTIONS 8 | { 9 | . = kern_lma; 10 | .boot : { *(*.mboot*) } 11 | .usslessarch ALIGN(4K) : { *(*.uarch*) } /*This is for the lmode_start func, have to put it in the 1M mark*/ 12 | .preliminargdt ALIGN(4K) : { *(*.pregdt*) } /*This is for the gdt64, instead of using rodata and being linked on higher half*/ 13 | .preliminarbss ALIGN(4K) : { *(*.prebss*) } 14 | . += kern_vma; 15 | .text ALIGN(4K) : AT(ADDR(.text) - kern_vma) { *(*.text*) } 16 | .data ALIGN(4K) : AT(ADDR(.data) - kern_vma) { *(*.data*) } 17 | .rodata ALIGN(4K) : AT(ADDR(.rodata) - kern_vma) { *(*.rodata*) } 18 | .bss ALIGN(4K) : AT(ADDR(.bss) - kern_vma) { *(*.bss*) *(COMMON) } 19 | .heap ALIGN(4K) : AT(ADDR(.heap) - kern_vma) { *(*.heap*) } 20 | kernel_end = .; 21 | /DISCARD/ ALIGN(4K) : AT(ADDR(.rodata) - kern_vma) { *(*.comment*) /**(*.eh_frame*)*/ } 22 | } 23 | --------------------------------------------------------------------------------