diff --git a/.gitignore b/.gitignore index fac9f9a..e0b7168 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ *.o *.bin +*.img *.lock *.com bx_enh_dbg.ini diff --git a/Makefile b/Makefile index 992e913..f94ab84 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ objects = entry.o kernel.o task.o handler.o interrupt.o v86.o print.o tss.o dosfs/dosfs.o gdt.o usermode.o paging.o fault.o tests.o kbd.o helper.o progs.o -CFLAGS = -target "i686-elf" -m32 -mgeneral-regs-only -ffreestanding -march=pentium-m -fno-stack-protector -Wno-int-conversion -nostdlib -c +CFLAGS = -target "i486-elf" -m32 -mgeneral-regs-only -ffreestanding -march=pentium-m -fno-stack-protector -Wno-int-conversion -nostdlib -c %.o: %.nasm nasm -f elf32 -o $@ $< @@ -11,7 +11,7 @@ all: $(objects) nasm boot.nasm -o boot.bin gcc -Tlink.ld -Wl,-M -m32 -ffreestanding -nostartfiles -nostdlib -o kernel.bin\ $(objects) - dd bs=256 count=1 conv=notrunc if=boot.bin of=virtdisk.bin + dd bs=400 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 diff --git a/boot.nasm b/boot.nasm index 1186a9d..cd5738d 100644 --- a/boot.nasm +++ b/boot.nasm @@ -8,6 +8,10 @@ mov es, ax mov ax, 0x8000 mov ss, ax mov sp, 0xFF00 +mov ah, 0x41 ; int 13 extensions check +mov bx, 0x55AA +int 0x13 +jc no_exten mov cx, kernelreads read_loop: xor ax, ax @@ -19,6 +23,14 @@ add word [addr_packet_transfer_buff_seg], (secreadcnt*512)/16 add word [addr_packet_start_block], secreadcnt loop read_loop entry: +mov ax,0x2403 ; A20 BIOS Support +int 0x15 +jb .no_a20 +cmp ah,0 +jnz .no_a20 +mov ax,0x2401 ; A20 BIOS Activate +int 0x15 +.no_a20: cli ; no interrupts xor ax,ax mov ds, ax @@ -28,19 +40,50 @@ or al, 1 mov cr0, eax jmp 08h:Pmode err: +mov bx, ax +mov si, string +mov cx, string_end - string +jmp print +no_exten: +mov bx, ax +mov si, no_exten_str +mov cx, no_exten_str_end - no_exten_str +print: push 0xb800 pop es xor di, di -mov si, string -mov cx, 10 mov ah, 0x7 err_print: lodsb stosw loop err_print +add di, 2 +mov ax, bx +call hexprint hlt_loop: hlt jmp hlt_loop +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, 0x7 +stosw +test cx, cx +jz .nibble2 +ret + [BITS 32] Pmode: mov eax, 0x10 @@ -49,18 +92,29 @@ mov es, ax mov fs, ax mov gs, ax mov ss, ax -in al, 0x92 +; check A20 +.a20: +mov edi, 0x101337 +mov esi, 0x001337 +mov [esi], esi +mov [edi], edi +cmpsd +jne .kernel +in al, 0x92 ; fast A20 test al, 2 -jnz after +jnz .fa20_end or al, 2 and al, 0xFE out 0x92, al -after: +.fa20_end: +jmp .a20 +.kernel: mov esi, 0x8000 mov edi, 0x100000 mov ecx, 0x10000 rep movsb jmp 08h:0x100000 + gdt_desc: dw gdt_end - gdt dd gdt @@ -79,6 +133,9 @@ gdt_data: dw 0xFFFF, 0 ; bits 0-15 limit (4GB), bits 0-15 base address gdt_end: string: db 'DISK ERROR' +string_end: +no_exten_str: db 'NO INT13 EXTEN' +no_exten_str_end: addr_packet: db 0x10, 0x00 ; size, reserved diff --git a/interrupt.c b/interrupt.c index 9d17933..46e8862 100644 --- a/interrupt.c +++ b/interrupt.c @@ -22,6 +22,13 @@ void int_printDword(uint32_t v, uint16_t *buff) { int_printWord(v >> 16, buff); int_printWord(v, &buff[4]); } +__attribute((__no_caller_saved_registers__)) +uintptr_t int_printStr(char *v, uint16_t *buff) { + char *s; + for (s = v;*s;s++,buff++) + *(char*)buff = *s; + return s - v; +} struct __attribute__((__packed__)) IDTR_t { uint16_t size; @@ -90,6 +97,8 @@ extern void real_test(); extern void jmp_usermode_test(); __attribute((__no_caller_saved_registers__)) extern void return_prev_task(); +__attribute((__no_caller_saved_registers__)) +extern void error_environment(); // defined in kernel.c #define VALID_FLAGS 0xDFF __attribute__ ((interrupt)) void gpf_handler_v86(struct interrupt_frame *frame, unsigned long error_code) { @@ -220,6 +229,23 @@ void gpf_handler_v86(struct interrupt_frame *frame, unsigned long error_code) { frame->eip = (uint16_t) (frame->eip + 1); goto done; default: + { + uint16_t *e = error_screen; + for (int i = 0; i < 80; i++) + e[i] = 0x0f00; + e += int_printStr("Unknown instruction caused V86 GPF: ", e); + *(uint32_t*)e = 0x1f001f00; + int_printDword(*(uint32_t*)ip, e); + e += 9; + *(uint8_t*)e = '@'; + e += 1; + int_printWord(frame->cs, e); + e += 4; + *(uint8_t*)e = ':'; + e += 1; + int_printWord(frame->eip, e); + error_environment(); + } for(;;); } } diff --git a/kernel.c b/kernel.c index 7621f1b..e2415b2 100644 --- a/kernel.c +++ b/kernel.c @@ -104,15 +104,16 @@ void ensure_v86env() { char *d = &_v86code; while (d < &_ev86code) *d++ = *s++; - for (int i = 0; i < 80*50; i++) - if (!(error_screen[i] & 0xFF00)) - error_screen[i] = 0x0f00 | (error_screen[i] & 0x00FF); } __attribute((__no_caller_saved_registers__)) extern void return_prev_task(); +__attribute((__no_caller_saved_registers__)) void error_environment() { ensure_v86env(); + for (int i = 0; i < 80*50; i++) + if (!(error_screen[i] & 0xFF00)) + error_screen[i] = 0x0f00 | (error_screen[i] & 0x00FF); union V86Regs_t regs; FARPTR v86_entry = i386LinearToFp(v86TextMode); enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s); @@ -126,7 +127,12 @@ void error_environment() { for(;;) { uint8_t key = get_scancode() & 0xff; if (key == KEY_E) break; - if (key == KEY_R) return_prev_task(); + if (key == KEY_R) { + // reset error screen + for (int i = 0; i < (80*50)/2; i++) + ((uint32_t*)error_screen)[i] = 0x0f000f00; + return_prev_task(); + } } v86_entry = i386LinearToFp(v86TransFlag); enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s); @@ -288,6 +294,12 @@ void start() { *(char *)&vga_text[i] = h[i]; vga_text = &vga_text[80]; + // DL *should* be preserved + uint8_t dl; + asm volatile("nop":"=d"(dl)); + vga_text += printByte(dl, vga_text); + vga_text++; + uint32_t o; asm("mov %%esp, %%eax" : "=a"(o) : :); vga_text += printDword(o, vga_text); @@ -303,15 +315,14 @@ void start() { // *(char *)&vga_text[i+(80*3)] = c[i]; //if (!apic) return; - char sse_str[] = "SSE support: "; - vga_text += printStr("SSE: ", vga_text); - char sse = check_sse(); - if (!sse) { - *vga_text = 'N'; - return; - } - vga_text += printStr("Y ", vga_text); - enable_sse(); + //char sse_str[] = "SSE support: "; + //vga_text += printStr("SSE: ", vga_text); + //char sse = check_sse(); + //if (!sse) { + // *vga_text = 'N'; + //} + //vga_text += printStr("Y ", vga_text); + //enable_sse(); setup_binary(); @@ -327,7 +338,7 @@ void start() { //print_cr4(); backup_ivtbios(); - vga_text = &((word *)0xb8000)[80]; + vga_text = &((word *)0xb8000)[160]; vga_text += printStr("Press T for tests, or any key to continue... ", vga_text); uint8_t key = get_key(); if (key == 't' || key == 'T') diff --git a/tests.c b/tests.c index e6f9255..b4f1a8e 100644 --- a/tests.c +++ b/tests.c @@ -40,7 +40,7 @@ void TestDiskRead() { regs.w.ax = 3; // text mode V8086Int(0x10, ®s); vga_text += printStr("Done. Starting Disk Read... ", vga_text); - char *diskReadBuf = (char *)0x23000; + char *diskReadBuf = (char *)0x8000; v86disk_addr_packet.transfer_buffer = (uintptr_t)diskReadBuf & 0x000F | (((uintptr_t)diskReadBuf & 0xFFFF0) << 12); diff --git a/v86.nasm b/v86.nasm index 55882fb..a761599 100644 --- a/v86.nasm +++ b/v86.nasm @@ -1,6 +1,5 @@ [BITS 16] [SECTION .v86] - global v86Interrupt v86Interrupt: int 0x00 diff --git a/v86defs.h b/v86defs.h index a605073..0b409e3 100644 --- a/v86defs.h +++ b/v86defs.h @@ -41,7 +41,7 @@ union __attribute((__packed__)) V86Regs_t { } h; }; -extern void enter_v86(uint32_t ss, uint32_t esp, uint32_t cs, uint32_t eip, union V86Regs_t *regs); +extern uint32_t enter_v86(uint32_t ss, uint32_t esp, uint32_t cs, uint32_t eip, union V86Regs_t *regs); void V8086Int(uint8_t interrupt, union V86Regs_t *regs); @@ -76,3 +76,4 @@ typedef uint32_t FARPTR; FARPTR i386LinearToFp(void *ptr); +void ensure_v86env(); diff --git a/virtdisk.bin.ex b/virtdisk.bin.ex new file mode 100644 index 0000000..804d857 Binary files /dev/null and b/virtdisk.bin.ex differ