From 0fa405dd98f445d44d5c66f6ebde3852ac300b7d Mon Sep 17 00:00:00 2001 From: Lucia Ceionia Date: Wed, 14 Sep 2022 16:50:44 -0500 Subject: [PATCH] real initial commit --- .gitignore | 4 + Makefile | 11 ++ bochsrc | 54 +++++++ boot.nasm | 31 ++++ entry.nasm | 337 +++++++++++++++++++++++++++++++++++++++ kernel.c | 453 +++++++++++++++++++++++++++++++++++++++++++++++++++++ link.ld | 19 +++ 7 files changed, 909 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 bochsrc create mode 100644 boot.nasm create mode 100644 entry.nasm create mode 100644 kernel.c create mode 100644 link.ld diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f8536d7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.o +*.bin +*.lock +bx_enh_dbg.ini diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ec7a187 --- /dev/null +++ b/Makefile @@ -0,0 +1,11 @@ +all: + nasm boot.nasm -o boot.bin + nasm -f elf32 -o entry.o entry.nasm + clang -target "i686-elf" -ffreestanding -m32 -march=pentium-m -fno-stack-protector -nostdlib -c -o kernel.o kernel.c + #clang -target "i686-elf" -O2 -ffreestanding -m32 -march=i386 -fno-stack-protector -nostdlib -c -o kernel.o kernel.c + gcc -Tlink.ld -m32 -ffreestanding -nostartfiles -nostdlib -o kernel.bin entry.o kernel.o + dd bs=256 count=1 conv=notrunc if=boot.bin of=virtdisk.bin + dd bs=512 seek=1 conv=notrunc if=kernel.bin of=virtdisk.bin +virtdisk: + dd bs=1M count=32 if=/dev/zero of=virtdisk.bin + echo -n -e '\x55\xaa' | dd bs=1 seek=510 conv=notrunc of=virtdisk.bin diff --git a/bochsrc b/bochsrc new file mode 100644 index 0000000..9e069bf --- /dev/null +++ b/bochsrc @@ -0,0 +1,54 @@ +# configuration file generated by Bochs +display_library: x, options="gui_debug" +#magic_break: enabled=1 +plugin_ctrl: unmapped=true, biosdev=true, speaker=true, extfpuirq=true, parallel=true, serial=true, iodebug=true, pcidev=false, usb_uhci=false +config_interface: textconfig +display_library: x +memory: host=32, guest=32 +romimage: file="/usr/share/bochs/BIOS-bochs-latest", address=0x00000000, options=none +vgaromimage: file="/usr/share/bochs/VGABIOS-lgpl-latest" +boot: disk +floppy_bootsig_check: disabled=0 +floppya: type=none +# no floppyb +ata0: enabled=true, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 +ata0-master: type=disk, path="virtdisk.bin", mode=flat, cylinders=2, heads=16, spt=63, sect_size=512, model="Generic 1234", biosdetect=auto, translation=auto +ata0-slave: type=none +ata1: enabled=true, ioaddr1=0x170, ioaddr2=0x370, irq=15 +ata1-master: type=none +ata1-slave: type=none +ata2: enabled=false +ata3: enabled=false +optromimage1: file=none +optromimage2: file=none +optromimage3: file=none +optromimage4: file=none +optramimage1: file=none +optramimage2: file=none +optramimage3: file=none +optramimage4: file=none +pci: enabled=1, chipset=i440fx, slot1=none, slot2=none, slot3=none, slot4=none, slot5=none +vga: extension=vbe, update_freq=5, realtime=1, ddc=builtin +cpu: count=1:1:1, ips=4000000, quantum=16, model=core_duo_t2400_yonah, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0 +print_timestamps: enabled=0 +debugger_log: - +magic_break: enabled=0 +port_e9_hack: enabled=0 +private_colormap: enabled=0 +clock: sync=none, time0=local, rtc_sync=0 +# no cmosimage +log: - +logprefix: %t%e%d +debug: action=ignore +info: action=report +error: action=report +panic: action=ask +keyboard: type=mf, serial_delay=250, paste_delay=100000, user_shortcut=none +mouse: type=ps2, enabled=false, toggle=ctrl+mbutton +speaker: enabled=true, mode=system +parport1: enabled=true, file=none +parport2: enabled=false +com1: enabled=true, mode=null +com2: enabled=false +com3: enabled=false +com4: enabled=false diff --git a/boot.nasm b/boot.nasm new file mode 100644 index 0000000..3cba20c --- /dev/null +++ b/boot.nasm @@ -0,0 +1,31 @@ +[ORG 0x7c00] +[BITS 16] + +xor ax, ax +mov ds, ax +mov es, ax +mov ah, 0x42 +mov si, addr_packet +int 0x13 +jnc 0x8000 +push 0xb800 +pop es +xor di, di +mov si, string +mov cx, 10 +mov ah, 0x7 +err_print: +lodsb +stosw +loop err_print +hlt_loop: +hlt +jmp hlt_loop + +string: db 'DISK ERROR' + +addr_packet: +db 0x10, 0x00 ; size, reserved +dw 0x20 ; blocks +dd 0x8000 ; transfer buffer +dq 1 ; start block diff --git a/entry.nasm b/entry.nasm new file mode 100644 index 0000000..38c56a9 --- /dev/null +++ b/entry.nasm @@ -0,0 +1,337 @@ +[BITS 16] + +global entry +entry: +cli ; no interrupts +xor ax,ax +mov ds, ax +lgdt [gdt_desc] ; load gdt register +mov eax, cr0 ; set pmode bit +or al, 1 +mov cr0, eax +jmp 08h:Pmodecode + +[BITS 32] +Pmodecode: +mov ax, 0x10 ; set up segments +mov ds, ax +mov es, ax +mov ss, ax +mov ebp, 0x400000 +mov esp, ebp +mov eax, 0x1f001f00 +mov ecx, (80*25)/2 +mov edi, 0xb8000 +rep stosd +call start +hlt_loop: +hlt +jmp hlt_loop + +setup_paging: +mov ecx, 1024*3 ; 3K? +xor eax, eax +mov edi, 0x1000 +rep stosd ; zero first 3K for some reason +mov edi, 0x4000 +mov eax, 0x800007 ; 8MB + 7 +std ; fill backwards +.fill: +stosd +sub eax, 0x1000 +jge .fill +cld ; fix direction +mov dword [0x0000], 0x2000 + 7 +mov dword [0x0004], 0x3000 + 7 +mov eax, 0x1000 +mov cr3, eax ; page dir start 0x1000 +mov eax, cr0 +or eax, 0x80000000 +mov cr0, eax ; set paging bit +ret ; flushes pre-fetch queue + +[BITS 16] +real_hexprint: +xor cx, cx +mov bl, al +shr al, 4 +jmp .donibble +.nibble2: +mov al, bl +inc cx +.donibble: +and al, 0x0F +cmp al, 0x0A +jl .noadjust +add al, 'A' - '0' - 10 +.noadjust: +add al, '0' +mov ah, 0x1f +stosw +test cx, cx +jz .nibble2 +ret +real_printword: +mov dx, ax +mov al, ah +call real_hexprint +mov ax, dx +call real_hexprint +ret +extern v86Code +v86Code: +mov ax, 0xb814 +mov es, ax +mov di, 20 +mov ax, sp +call real_printword +add di, 2 +mov ax, ds +call real_printword +add di, 2 +mov ax, cs +call real_printword +.loop: +inc byte [0] +;mov ax, 0x1111 +;mov ds, ax +;mov ax, 0x2222 +;mov es, ax +;mov ax, 0x3333 +;mov fs, ax +;mov ax, 0x4444 +;mov gs, ax +;mov ax, 0x5555 +;mov ss, ax +;mov ax, 0x6666 +;mov sp, ax +int 3 +;jmp .loop +mov ax, 0x13 +int 0x10 +int 0x30 ; exit +jmp $ +extern real_test +real_test: +nop +nop +nop +jmp $ +[BITS 32] +; extern void enter_v86(uint32_t ss, uint32_t esp, uint32_t cs, uint32_t eip); +global enter_v86 +enter_v86: +mov ebp, esp ; save stack pointer +push dword [ebp+4] ; ss +push dword [ebp+8] ; esp +pushfd ; eflags +or dword [esp], (1 << 17) ; set VM flags +;or dword [esp], (3 << 12) ; IOPL 3 +push dword [ebp+12] ; cs +push dword [ebp+16] ; eip +iret + +user_test: +mov dword [0xb8000], 0x0f000f00 | 'U' | 's' << 16 +mov dword [0xb8004], 0x0f000f00 | 'e' | 'r' << 16 +mov dword [0xb8008], 0x0f000f00 | 'm' | 'o' << 16 +mov dword [0xb800C], 0x0f000f00 | 'd' | 'e' << 16 +mov word [0xb8010], 0x0f00 | '!' +mov edi, 0xA0000 +xor eax, eax +.loop: +mov cx, 320 +rep stosb +inc al +cmp eax, 200 +jl .loop +xor ebx, ebx +div bl + +global jmp_usermode_test +jmp_usermode_test: +mov ax, 0x20 | 3 +mov ds, ax +mov es, ax +mov fs, ax +mov gs, ax +mov eax, esp +push 0x20 | 3 +push eax +pushfd +push 0x18 | 3 +push user_test +iret + +extern unhandled_handler +unhandled_handler: +mov ax, 0x10 +mov ds, ax +mov dword [0xb8000], 0x0f000f00 | 'E' | 'R' << 16 +mov dword [0xb8004], 0x0f000f00 | 'R' | 'O' << 16 +mov dword [0xb8008], 0x0f000f00 | 'R' | '!' << 16 +.hlt: +hlt +jmp .hlt + +extern gpf_handler_v86 +global gpfHandler +gpfHandler: +iret +mov ax, 0x10 +mov ds, ax +;jmp gpf_handler_v86 +mov word [0xb8000], 0x0f00 | 'G' +mov word [0xb8002], 0x0f00 | 'P' +mov word [0xb8004], 0x0f00 | 'F' +.hlt: +hlt +jmp .hlt + +scancodesToAscii: db 0, 0 ; 0x00 - 0x01 +db "1234567890" ; 0x02 - 0x0B +db "-=" ; 0x0C - 0x0D +db 0, 0 ; 0x0E - 0x0F +db "qwertyuiop[]" ; 0x10 - 0x1B +db 0, 0 ; 0x1C - 0x1D +db "asdfghjkl;'`" ; 0x1E - 0x29 +db 0 ; 0x2A +db "\zxcvbnm,./" ; 0x2B - 0x35 +db 0 ; 0x36 +db '*' ; 0x37 +db 0 ; 0x38 +db ' ' ; 0x39 +db 'C' +scancodesToAsciiEnd: +cursorCurrent: dd 0xb8000 + (80*6*2) +global keyboardHandler +keyboardHandler: +push eax +push ebx +push ds +mov ax, 0x10 +mov ds, ax +xor eax, eax +in al, 0x60 +cmp eax, 0x3A +jg .done +mov al, [scancodesToAscii+eax] +test al, al +jz .done +mov ebx, [cursorCurrent] +mov byte [ebx], al +add dword [cursorCurrent], 2 +mov byte [KBDWAIT], 1 +.done: +mov al, 0x20 +out 0x20, al +pop ds +pop ebx +pop eax +iret + +KBDWAIT: db 0 +global kbd_wait +kbd_wait: +mov byte [KBDWAIT], 0 +.loop: +hlt +xor eax, eax +mov al, [KBDWAIT] +test eax, eax +jz .loop +ret + +global timerHandler +timerHandler: +push eax +push ds +mov ax, 0x10 +mov ds, ax +inc byte [(0xb8000 + (80*8*2))] +mov al, 0x20 +out 0x20, al +pop ds +pop eax +iret + +global picInit +picInit: +mov al, 0x11 ; initialization sequence +out 0x20, al ; send to 8259A-1 +jmp $+2 +jmp $+2 +out 0xA0, al ; and to 8259A-2 +jmp $+2 +jmp $+2 +mov al, 0x20 ; start of hardware ints (0x20) +out 0x21, al +jmp $+2 +jmp $+2 +mov al, 0x28 ; start of hardware ints 2 (0x28) +out 0xA1, al +jmp $+2 +jmp $+2 +mov al, 0x04 ; 8259-1 is master +out 0x21, al +jmp $+2 +jmp $+2 +mov al, 0x02 ; 8259-2 is slave +out 0xA1, al +jmp $+2 +jmp $+2 +mov al, 0x01 ; 8086 mode for both +out 0x21, al +jmp $+2 +jmp $+2 +out 0xA1, al +jmp $+2 +jmp $+2 +mov al, 0xFF ; all interrupts off for now +out 0x21, al +jmp $+2 +jmp $+2 +out 0xA1, al +ret + +global flushTSS +flushTSS: +mov ax, 0x28 +ltr ax +ret + +extern tss_data + +extern start + +gdt_desc: + dw gdt_end - gdt + dd gdt +gdt: +gdt_null: dq 0 +gdt_code: dw 0xFFFF, 0 ; bits 0-15 limit (4GB), bits 0-15 base address + db 0 ; bits 16-23 base address + db 10011010b ; access byte + db 11001111b ; bits 16-19 limit (4GB), 4 bits flags + db 0 ; bits 24-31 base address +gdt_data: dw 0xFFFF, 0 ; bits 0-15 limit (4GB), bits 0-15 base address + db 0 ; bits 16-23 base address + db 10010010b ; access byte + db 11001111b ; bits 16-19 limit (4GB), 4 bits flags + db 0 ; bits 24-31 base address +gdt_r3code: dw 0xFFFF, 0 ; bits 0-15 limit (4GB), bits 0-15 base address + db 0 ; bits 16-23 base address + db 0xFA ; access byte + db 11001111b ; bits 16-19 limit (4GB), 4 bits flags + db 0 ; bits 24-31 base address +gdt_r3data: dw 0xFFFF, 0 ; bits 0-15 limit (4GB), bits 0-15 base address + db 0 ; bits 16-23 base address + db 0xF2 ; access byte + db 11001111b ; bits 16-19 limit (4GB), 4 bits flags + db 0 ; bits 24-31 base address +gdt_tss: dw 0x2080, 0x0000;26*4, tss_data ; bits 0-15 limit (4GB), bits 0-15 base address + db 0x2 ; bits 16-23 base address + db 0x89 ; access byte + db 00000000b ; bits 16-19 limit (4GB), 4 bits flags + db 0 ; bits 24-31 base address +gdt_end: diff --git a/kernel.c b/kernel.c new file mode 100644 index 0000000..81e5e93 --- /dev/null +++ b/kernel.c @@ -0,0 +1,453 @@ +#include + +typedef unsigned short word; + +char nibbleToHex(char n) { + return n > 9 ? (n - 10) + 'A' : n + '0'; +} +void printByte(char v, short *buff) { + *(char *)&buff[0] = nibbleToHex((v >> 4) & 0xF); + *(char *)&buff[1] = nibbleToHex(v & 0xF); +} +void printWord(short v, short *buff) { + printByte(v >> 8, buff); + printByte(v, &buff[2]); +} +void printDword(int v, short *buff) { + printWord(v >> 16, buff); + printWord(v, &buff[4]); +} + +char check_apic() { + uint32_t eax, ebx, ecx, edx; + asm("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(1)); + return (edx & (1 << 9)) != 0; +} +char check_sse() { + uint32_t eax, ebx, ecx, edx; + asm("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(1)); + return (edx & (1 << 25)) != 0; +} + +struct __attribute__((__packed__)) IDTR_t { + uint16_t size; + uint32_t offset; +}; + +struct __attribute__((__packed__)) InterruptDescriptor32 { + uint16_t offset_1; // offset bits 0..15 + uint16_t selector; // a code segment selector in GDT or LDT + uint8_t zero; // unused, set to 0 + uint8_t type_attributes; // gate type, dpl, and p fields + uint16_t offset_2; // offset bits 16..31 +}; + +__attribute__((aligned(0x10))) +struct InterruptDescriptor32 IDT[256]; +struct IDTR_t IDTR; + +void outb(uint16_t port, uint8_t value) { + asm volatile("outb %%al, %%dx" : : "d"(port), "a"(value)); +} +uint8_t inb(uint16_t port) { + uint8_t value; + asm volatile("inb %%dx, %%al" : "=a"(value) : "d"(port)); + return value; +} + +void IRQ_set_mask(char IRQline) { + uint16_t port; + uint8_t value; + if (IRQline < 8) { + port = 0x21; + } else { + port = 0xA1; + IRQline -= 8; + } + value = inb(port) | (1 << IRQline); + outb(port, value); +} +void IRQ_clear_mask(char IRQline) { + uint16_t port; + uint8_t value; + if (IRQline < 8) { + port = 0x21; + } else { + port = 0xA1; + IRQline -= 8; + } + value = inb(port) & ~(1 << IRQline); + outb(port, value); +} + +struct interrupt_frame { + uint32_t eip, cs; + uint32_t eflags; + uint32_t esp, ss; + uint32_t es, ds, fs, gs; +}; + +/* Real Mode helper macros */ +/* segment:offset pair */ +typedef uint32_t FARPTR; + +/* Make a FARPTR from a segment and an offset */ +#define MK_FP(seg, off) ((FARPTR) (((uint32_t) (seg) << 16) | (uint16_t) (off))) + +/* Extract the segment part of a FARPTR */ +#define FP_SEG(fp) (((FARPTR) fp) >> 16) + +/* Extract the offset part of a FARPTR */ +#define FP_OFF(fp) (((FARPTR) fp) & 0xffff) + +/* Convert a segment:offset pair to a linear address */ +#define FP_TO_LINEAR(seg, off) ((void*)(uintptr_t)((((uint32_t)seg) << 4) + ((uint32_t)off))) + +FARPTR i386LinearToFp(void *ptr) +{ + unsigned seg, off; + off = (uintptr_t) ptr & 0xffff; + seg = ((uintptr_t) ptr >> 16); + return MK_FP(seg, off); +} + +#define EFLAG_IF ((uint32_t)1 << 9) +#define EFLAG_VM ((uint32_t)1 << 17) + +char v86_if = 0; +extern void real_test(); +extern void kbd_wait(); +#define VALID_FLAGS 0xDFF +__attribute__ ((interrupt)) +void gpf_handler_v86(struct interrupt_frame *frame, uint32_t error_code) { + asm volatile("mov %%ax,%%ds"::"a"(0x10)); + uint8_t *ip; + uint16_t *stack, *ivt; + uint32_t *stack32; + char is_operand32 = 0, is_address32 = 0; + ip = ((frame->cs << 4) + frame->eip) & 0xFFFFF; + ivt = (uint16_t*)0x0000; + stack = FP_TO_LINEAR(frame->ss, frame->esp); + stack32 = (uint32_t*)stack; + + char *vga = (char*)0xb8000 + (160 * 10); + vga[0] = 'I'; vga[2] = 'P'; printWord(frame->eip, &vga[4]); vga += 14; + vga[0] = 'C'; vga[2] = 'S'; printWord(frame->cs, &vga[4]); vga += 14; + vga[0] = 'F'; vga[2] = 'L'; printDword(frame->eflags, &vga[4]); vga += 14; + vga = (char*)0xb8000 + (160 * 11); + vga[0] = 'S'; vga[2] = 'P'; printWord(frame->esp, &vga[4]); vga += 14; + vga[0] = 'S'; vga[2] = 'S'; printWord(frame->ss, &vga[4]); vga += 14; + vga = (char*)0xb8000 + (160 * 12); + vga[0] = 'E'; vga[2] = 'S'; printWord(frame->es, &vga[4]); vga += 14; + vga[0] = 'D'; vga[2] = 'S'; printWord(frame->ds, &vga[4]); vga += 14; + vga[0] = 'F'; vga[2] = 'S'; printWord(frame->fs, &vga[4]); vga += 14; + vga[0] = 'G'; vga[2] = 'S'; printWord(frame->gs, &vga[4]); vga += 14; + + //vga[2]++; + //printDword(frame, &vga[20]); + //vga = &vga[38]; + //uint32_t *fr = frame; + //for (int i = 0; i < sizeof(struct interrupt_frame)/sizeof(uint32_t); i++) { + // printDword(fr[i], vga); + // vga += (sizeof(uint32_t)*2+1)*2; + //} + //vga = (char*)0xb80A0; + //printDword(ip, &vga[20]); + //vga = &vga[38]; + //for (int i = 0; i < 16; i++) { + // printByte(ip[i], vga); + // vga += (sizeof(uint8_t)*2)*2; + //} + vga = (char*)0xb8000 + (160*3); + for(;;) { + switch (ip[0]) { + case 0x66: // O32 + is_operand32 = 1; + ip++; + frame->eip = (uint16_t)(frame->eip + 1); + break; + case 0x67: // A32 + is_address32 = 1; + ip++; + frame->eip = (uint16_t)(frame->eip + 1); + break; + case 0x9C: // PUSHF + if (is_operand32) { + frame->esp = ((frame->esp & 0xffff) - 4) & 0xffff; + stack32--; + stack32[0] = frame->eflags & VALID_FLAGS; + if (v86_if) + stack32[0] |= EFLAG_IF; + else + stack32[0] &= ~EFLAG_IF; + } else { + frame->esp = ((frame->esp & 0xffff) - 2) & 0xffff; + stack--; + stack[0] = (uint16_t)frame->eflags; + if (v86_if) + stack[0] |= EFLAG_IF; + else + stack[0] &= ~EFLAG_IF; + } + frame->eip = (uint16_t)(frame->eip + 1); + goto done; + case 0x9D: // POPF + if (is_operand32) { + frame->eflags = EFLAG_IF | EFLAG_VM | (stack32[0] & VALID_FLAGS); + v86_if = (stack32[0] & EFLAG_IF) != 0; + frame->esp = ((frame->esp & 0xffff) + 4) & 0xffff; + } else { + frame->eflags = EFLAG_IF | EFLAG_VM | stack[0]; + v86_if = (stack[0] & EFLAG_IF) != 0; + frame->esp = ((frame->esp & 0xffff) + 2) & 0xffff; + } + frame->eip = (uint16_t)(frame->eip + 1); + goto done; + case 0xCD: // INT n + vga[0] = 'I'; vga[2]++; if (vga[2] < '0') vga[2] = '0'; + asm volatile("nop\nnop"); + switch (ip[1]) { + case 0x30: // Exit V86 Mode? + asm volatile("nop\nnop"); + asm volatile("jmp jmp_usermode_test"); + //__builtin_unreachable(); + break; + //case 0x20: // ??? + //case 0x21: // ??? + case 0x3: // Debugger trap + kbd_wait(); + asm volatile("nop"); + default: + stack -= 3; + frame->esp = ((frame->esp & 0xffff) - 6) & 0xffff; + + stack[0] = (uint16_t) (frame->eip + 2); + stack[1] = frame->cs; + stack[2] = (uint16_t) frame->eflags; + + if (v86_if) + stack[2] |= EFLAG_IF; + else + stack[2] &= ~EFLAG_IF; + + frame->cs = ivt[ip[1] * 2 + 1]; + frame->eip = ivt[ip[1] * 2]; + asm volatile("nop"); + //frame->cs = 0; + //frame->eip = real_test; + goto done; + } + goto done; + case 0xCF: // IRET + frame->eip = stack[0]; + frame->cs = stack[1]; + frame->eflags = EFLAG_IF | EFLAG_VM | stack[2]; + v86_if = (stack[2] & EFLAG_IF) != 0; + frame->esp = ((frame->esp & 0xffff) + 6) & 0xffff; + goto done; + case 0xFA: // CLI + v86_if = 0; + frame->eip = (uint16_t) (frame->eip + 1); + goto done; + case 0xFB: // STI + v86_if = 1; + frame->eip = (uint16_t) (frame->eip + 1); + goto done; + default: + goto done; + } + } + done: + vga = (char*)0xb8000 + (160 * 13); + vga[0] = 'I'; vga[2] = 'P'; printWord(frame->eip, &vga[4]); vga += 14; + vga[0] = 'C'; vga[2] = 'S'; printWord(frame->cs, &vga[4]); vga += 14; + vga[0] = 'F'; vga[2] = 'L'; printDword(frame->eflags, &vga[4]); vga += 14; + vga = (char*)0xb8000 + (160 * 14); + vga[0] = 'S'; vga[2] = 'P'; printWord(frame->esp, &vga[4]); vga += 14; + vga[0] = 'S'; vga[2] = 'S'; printWord(frame->ss, &vga[4]); vga += 14; + vga = (char*)0xb8000 + (160 * 15); + vga[0] = 'E'; vga[2] = 'S'; printWord(frame->es, &vga[4]); vga += 14; + vga[0] = 'D'; vga[2] = 'S'; printWord(frame->ds, &vga[4]); vga += 14; + vga[0] = 'F'; vga[2] = 'S'; printWord(frame->fs, &vga[4]); vga += 14; + vga[0] = 'G'; vga[2] = 'S'; printWord(frame->gs, &vga[4]); vga += 14; +} + +extern void timerHandler(); +extern void keyboardHandler(); +extern void gpfHandler(); +extern void unhandled_handler(); +extern void picInit(); +void set_system_gate(uint8_t gate, void (*handler)()) { + IDT[gate].offset_1 = (uint32_t)handler & 0xFFFF; + IDT[gate].offset_2 = ((uint32_t)handler >> 16) & 0xFFFF; + IDT[gate].selector = 0x08; + IDT[gate].type_attributes = 0x8E; +} +void set_trap_gate(uint8_t gate, void (*handler)()) { + IDT[gate].offset_1 = (uint32_t)handler & 0xFFFF; + IDT[gate].offset_2 = ((uint32_t)handler >> 16) & 0xFFFF; + IDT[gate].selector = 0x08; + IDT[gate].type_attributes = 0x8F; +} +void setup_interrupts() { + IDTR.size = 256*8 - 1; + IDTR.offset = (uint32_t)IDT; + for (int i = 0; i < 256; i++) { + *(uint64_t*)&IDT[i] = 0; + } + + for (int i = 0; i < 9; i++) { + set_trap_gate(i, unhandled_handler); + } + for (int i = 10; i < 15; i++) { + set_trap_gate(i, unhandled_handler); + } + for (int i = 16; i < 22; i++) { + set_trap_gate(i, unhandled_handler); + } + + set_system_gate(0x20, timerHandler); + set_system_gate(0x21, keyboardHandler); + set_trap_gate(13, gpf_handler_v86); + //set_trap_gate(13, gpfHandler); + + asm volatile("lidt %0": : "m"(IDTR)); + picInit(); + IRQ_clear_mask(0); + IRQ_clear_mask(1); + asm volatile("sti"); +} + + +struct __attribute__((__packed__)) tss_entry_struct { + uint32_t prev_tss; + uint32_t esp0; + uint32_t ss0; + uint32_t esp1; + uint32_t ss1; + uint32_t esp2; + uint32_t ss2; + uint32_t cr3; + uint32_t eip; + uint32_t eflags; + uint32_t eax; + uint32_t ecx; + uint32_t edx; + uint32_t ebx; + uint32_t esp; + uint32_t ebp; + uint32_t esi; + uint32_t edi; + uint32_t es; + uint32_t cs; + uint32_t ss; + uint32_t ds; + uint32_t fs; + uint32_t gs; + uint32_t ldt; + uint32_t trap; + uint32_t iomap_base; +}; +struct tss_entry_struct *tss_data; +void write_tss() { + tss_data = (struct tss_entry_struct *)0x20000; + for (int i = 0; i < 0x2080; i++) + ((uint8_t*)tss_data)[i] = 0; + tss_data->ss0 = 0x10; + tss_data->esp0 = 0x400000; + tss_data->iomap_base = 0x80; +} + +void enable_sse() { + asm volatile( + "mov %%cr0, %%eax\n" + "and $0xFFFB, %%ax\n" + "or $0x2, %%ax\n" + "mov %%eax, %%cr0\n" + "mov %%cr4, %%eax\n" + "or $0x600, %%ax\n" + "mov %%eax, %%cr4\n" + : : : "%eax" + ); +} + +void print_flags() { + uint32_t flags; + asm volatile("pushfd\npop %%eax":"=a"(flags)); + printDword(flags, 0xB8000 + (160*4) + 50); +} +void print_cr0() { + uint32_t reg; + asm volatile("mov %%cr0, %%eax":"=a"(reg)); + printDword(reg, 0xB8000 + (160*5) + 50); +} +void print_cr3() { + uint32_t reg; + asm volatile("mov %%cr3, %%eax":"=a"(reg)); + printDword(reg, 0xB8000 + (160*5) + 50 + 8*2 + 2); +} +void print_cr4() { + uint32_t reg; + asm volatile("mov %%cr4, %%eax":"=a"(reg)); + printDword(reg, 0xB8000 + (160*5) + 50 + 8*4 + 4); +} + +extern void enter_v86(uint32_t ss, uint32_t esp, uint32_t cs, uint32_t eip); +extern void v86Code(); +extern void flushTSS(); +extern void jmp_usermode_test(); + +/* +Real Mode Accessible (First MB) + 00000 - 02000 IVT + 01000 - 04000 Paging + 04000 - 07C00 Free + 07C00 - 08000 Boot + 08000 - 20000 Kernel Code + 20000 - 22080 TSS + 80000 - 90000 Real Mode Stack + 90000 - A0000 Free + A0000 - FFFFF BIOS Area +Protected Only (1MB+) +100000 - Free +*/ + +void start() { + word *vga_text = (word *)0xb8000; + char h[] = "LuciaOS"; + for (int i = 0; i < sizeof(h); i++) + *(char *)&vga_text[i] = h[i]; + + uint32_t o; + asm("mov %%esp, %%eax" : "=a"(o) : :); + printDword(o, (short *)&vga_text[80]); + asm("mov %%ebp, %%eax" : "=a"(o) : :); + printDword(o, (short *)&vga_text[160]); + + //char c[] = "APIC support: "; + //char apic; + //printByte(apic = check_apic(), (short*)&vga_text[80*3 + sizeof(c) - 1]); + //for (int i = 0; i < sizeof(c); i++) + // *(char *)&vga_text[i+(80*3)] = c[i]; + //if (!apic) return; + + char sse_str[] = "SSE support: "; + char sse; + printByte(sse = check_sse(), (short*)&vga_text[80*4 + sizeof(sse_str) - 1]); + for (int i = 0; i < sizeof(sse_str); i++) + *(char *)&vga_text[i+(80*4)] = sse_str[i]; + if (!sse) return; + enable_sse(); + + setup_interrupts(); + write_tss(); + flushTSS(); + print_flags(); + print_cr0(); + print_cr3(); + print_cr4(); + FARPTR v86_entry = i386LinearToFp(v86Code); + enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry)); + //jmp_usermode_test(); +} + diff --git a/link.ld b/link.ld new file mode 100644 index 0000000..56ffbbe --- /dev/null +++ b/link.ld @@ -0,0 +1,19 @@ +OUTPUT_FORMAT(binary) +ENTRY(entry) + +SECTIONS { + . = 0x8000; + + .text : ALIGN(0x1000) { + *(.text) + } + + .data : ALIGN(0x1000) { + *(.data) + *(.rodata) + } + + .bss : ALIGN(0x1000) { + *(.bss) + } +}