diff --git a/Functions.c b/Functions.c index 481d2bd..12ed8fd 100644 --- a/Functions.c +++ b/Functions.c @@ -1,18 +1,21 @@ //Functions.c //05/07/03 Josh Holtrop //for HOS +//Modified: 10/30/03 - +//Writes a byte out to a port inline void outportb(unsigned int port, unsigned char value) // Output a byte to a port { asm volatile ("outb %%al,%%dx"::"d" (port), "a" (value)); }; +//Writes a word out to a port inline void outportw(unsigned int port, unsigned int value) // Output a word to a port { asm volatile ("outw %%ax,%%dx"::"d" (port), "a" (value)); }; +//Reads a byte from a port inline byte inportb(unsigned short port) { unsigned char ret_val; @@ -23,16 +26,19 @@ inline byte inportb(unsigned short port) return ret_val; }; -void enable_ints() +//Enables (SeTs) Interrupt Flag on the processor +inline void enable_ints() { asm("sti"); }; -void disable_ints() +//Disables (CLears) Interrupt Flag on the processor +inline void disable_ints() { asm("cli"); }; +//Re-maps the Programmable Interrupr Controllers so IRQ0->pic1 base address, IRG8->pic2 base address void remap_pics(int pic1, int pic2) { byte a1, a2; @@ -53,24 +59,37 @@ void remap_pics(int pic1, int pic2) outportb(PIC2_DATA, a2); //0xA1 } +//Masks interrupts on first Programmable Interrupt Controller inline void pic1_mask(byte mask) { outportb(PIC1_DATA, mask); //0x21, maskfield *OCW1* } +//Masks interrupts on second Programmable Interrupt Controller inline void pic2_mask(byte mask) { outportb(PIC2_DATA, mask); //0xA1, maskfield *OCW1* } +//Restarts the computer inline void restart() { + byte temp; + do + { + temp = inportb(0x64); + if (temp & 1) + inportb(0x60); + } while(temp & 2); + + outportb (0x64, 0xfe); for (;;) { } } +//Halts (freezes) the computer inline void halt() { asm("cli"); @@ -79,17 +98,32 @@ inline void halt() ; } -inline void eoi() +//Initializes 8253 Programmable Interrupt Timer +inline void init_timer() { - outportb(0x20, 0x20); //EOI + //set timer : 2e9c = 100hz + outportb(0x43, 0x34); + outportb(0x40, 0x9c); //lsb + outportb(0x40, 0x2e); //msb } +//Signals an End Of Interrupt signal to the first PIC +inline void eoi() +{ + outportb(0x20, 0x20); +} + +//Signals an End Of Interrupt signal to both the second and first PIC unit inline void eoi2() { outportb(0xA0, 0x20); outportb(0x20, 0x20); } +//Returns the size of the kernel (code & data) +// - this does not include the bss section +// - this should be 4kb aligned per the linker script +// - this should be the size of kernel.bin inline dword kernel_size() { return (dword)(&_bss)-(dword)(&_code); diff --git a/asmfuncs.asm b/asmfuncs.asm index 794237d..e5a26b8 100644 --- a/asmfuncs.asm +++ b/asmfuncs.asm @@ -7,6 +7,7 @@ [global _write_cr3] [global _read_cr3] +;stores the parameter to the CR0 register ;extern dword write_cr0(dword cr0); _write_cr0: push ebp @@ -16,12 +17,13 @@ _write_cr0: pop ebp ret +;returns the value in the CR0 register ;extern dword read_cr0(); _read_cr0: mov eax, cr0; ret - +;stores the parameter to the CR3 register ;extern dword write_cr3(dword cr3); _write_cr3: push ebp @@ -31,6 +33,7 @@ _write_cr3: pop ebp ret +;returns the value in the CR3 register ;extern dword read_cr3(); _read_cr3: mov eax, cr3; diff --git a/fdc.c b/fdc.c new file mode 100644 index 0000000..64afa5b --- /dev/null +++ b/fdc.c @@ -0,0 +1,9 @@ +//fdc.c +//Author: Josh Holtrop +//Date: 10/30/03 + + +inline void fdc_sendDOR(byte dor) +{ + outportb(FDC_DOR, dor); +} diff --git a/fdc.h b/fdc.h new file mode 100644 index 0000000..a25fcf4 --- /dev/null +++ b/fdc.h @@ -0,0 +1,12 @@ +//fdc.h +//Author: Josh Holtrop +//Date: 10/30/03 + + +#define FDC_DOR 0x3f2 +#define FDC_MSR 0x3f4 + + +inline void fdc_sendDOR(byte dor); + + diff --git a/functions.h b/functions.h index ed05723..3f0708a 100644 --- a/functions.h +++ b/functions.h @@ -1,6 +1,7 @@ //functions.h //05/07/03 Josh Holtrop //for HOS +//Modified: 10/30/03 extern dword _code; extern dword _bss; @@ -9,8 +10,8 @@ extern dword _end; inline void outportb(unsigned int port, unsigned char value); inline void outportw(unsigned int port, unsigned int value); inline byte inportb(unsigned short port); -void enable_ints(); -void disable_ints(); +inline void enable_ints(); +inline void disable_ints(); inline void restart(); inline void halt(); void remap_pics(int pic1, int pic2); @@ -19,6 +20,7 @@ inline void pic2_mask(byte mask); inline void eoi(); inline void eoi2(); inline dword kernel_size(); +inline void init_timer(); diff --git a/gdt.inc b/gdt.inc index f03c29c..2c04c58 100644 --- a/gdt.inc +++ b/gdt.inc @@ -1,4 +1,7 @@ - +;gdt.inc +;Author: Josh Holtrop +;for HOS +;Modified: 10/30/03 gdtr: dw gdt_end-gdt-1 diff --git a/idt.inc b/idt.inc index 8339a1b..0efb45b 100644 --- a/idt.inc +++ b/idt.inc @@ -1,3 +1,7 @@ +;idt.inc +;Author: Josh Holtrop +;for HOS +;Modified: 10/30/03 idtr: dw 50*8-1 ;size of idt @@ -78,7 +82,7 @@ isr_main: iret - + diff --git a/k_defines.h b/k_defines.h index e148310..e02de99 100644 --- a/k_defines.h +++ b/k_defines.h @@ -1,5 +1,6 @@ //k_defines.h //03/17/03 Josh Holtrop +//Modified: 10/30/03 #define PIC1 0x20 #define PIC2 0xA0 @@ -31,9 +32,9 @@ #define FREERAM_START 0x268000 #define MAX_RAM 0x40000000 //1gb maximum RAM supported -#define PID_KERNEL 0x02 +#define PID_KERNEL 0x02 //kernel's PID #define PID_VMM 0x03 -#define PID_USER 0x10000 +#define PID_USER 0x10000 //user processes' start PID typedef unsigned char byte; typedef unsigned short word; diff --git a/kernel.asm b/kernel.asm index 1454d26..f75b4fe 100644 --- a/kernel.asm +++ b/kernel.asm @@ -1,3 +1,6 @@ +;kernel.asm +;Author: Josh Holtrop +;Modified: 10/30/03 %include "bootdef.inc" @@ -10,6 +13,7 @@ bits 32 +;This is where the kernel begins execution start: cli ;if they weren't already off mov edi, GDT @@ -38,6 +42,7 @@ fill_idt: mov esi, ebx add esi, edx loop fill_idt + mov word [IDT+0x30*8+4], 0xEE00 ;interrupt 0x30 has user priviledges lgdt [gdtr] ;load gdt jmp KERNEL_CODE:newgdtcontinue @@ -52,8 +57,9 @@ newgdtcontinue: lidt [idtr] ;load idt call _k_init +haltit: hlt ;halt processor when k_init is done - jmp $ ;shouldn't get here... + jmp haltit ;shouldn't get here... %include "gdt.inc" %include "idt.inc" diff --git a/kernel.c b/kernel.c index b6c2083..5b7f753 100644 --- a/kernel.c +++ b/kernel.c @@ -1,23 +1,24 @@ //kernel.c //08/13/03 Josh Holtrop //Holtrop's Operating System -//Version: 0.1.1 -//Modified: 10/23/03 +//Version: 0.1.2 +//Modified: 10/30/03 #define VXR video_mode.XResolution #define VYR video_mode.YResolution -#include "k_defines.h" +#include "k_defines.h" //#DEFINE's for kernel -#include "lib/string.h" -#include "lib/io.h" +#include "lib/string.h" //library string functions +#include "lib/io.h" //library input/output functions -#include "functions.h" -#include "video.h" -#include "mm.h" -#include "vmm.h" -#include "keyboard.h" -#include "mouse.h" +#include "functions.h" //general functions +#include "video.h" //video functions +#include "mm.h" //physical memory management functions +#include "vmm.h" //virtual memory management & paging functions +#include "keyboard.h" //generic keyboard driver & functions +#include "mouse.h" //generic ps/2 mouse driver & functions +#include "fdc.h" //Floppy Disk Controller functions void isr(dword num); void k_init(); @@ -26,6 +27,7 @@ extern dword read_cr0(); extern dword write_cr3(dword cr3); extern dword read_cr3(); +#include "fdc.c" #include "mouse.c" #include "keyboard.c" #include "mm.c" @@ -35,76 +37,44 @@ extern dword read_cr3(); dword timer = 0; +//Main kernel initialization method void k_init() { + // ===== Initialization + fdc_sendDOR(0x0C); //turn off floppy motor!! console_cls(); remap_pics(0x20, 0x28); - //set timer : 2e9c = 100hz - outportb(0x43, 0x34); - outportb(0x40, 0x9c); //lsb - outportb(0x40, 0x2e); //msb + init_timer(); video_init((ModeInfoBlock *) 0x90306); - video_rectf(VXR*3/11, 0, VXR*4/11, VYR-1, 0x00000088); //test rectangles, draws "HOS" - video_rectf(VXR*7/11, 0, VXR*8/11, VYR-1, 0x00000088); - video_rectf(VXR/11, 0, VXR*2/11, VYR*2/5, 0x00000088); - video_rectf(VXR/11, VYR*3/5, VXR*2/11, VYR-1, 0x00000088); - video_rectf(VXR*5/11, VYR/5, VXR*6/11, VYR*4/5, 0x00000088); - video_rectf(VXR*9/11, VYR/5, VXR-1, VYR*2/5, 0x00000088); - video_rectf(VXR*8/11, VYR*3/5, VXR*10/11, VYR*4/5, 0x00000088); - - video_vert(10, 10, 16, 0x00ffff00); //should be yellow 'H' - video_horiz(13, 10, 14, 0x00ffff00); - video_vert(14, 10, 16, 0x00ffff00); - - video_horiz(10, 17, 21, 0x00ffff00); - video_vert(19, 10, 16, 0x00ffff00); - video_horiz(16, 17, 21, 0x00ffff00); - - int a, b; - for (a = 0; a < 256; a++) - { - for (b = 0; b < 256; b++) - { - video_pset(a+5, b+30, (a<<16)|(b<<8)); - video_pset(a+270, b+30, (a<<8)|(b)); - video_pset(a+535, b+30, (a<<16)|(b)); - - video_pset(a+5, b+290, (a<<16)|(b<<8)|0x000000ff); - video_pset(a+270, b+290, (a<<8)|(b)|0x00ff0000); - video_pset(a+535, b+290, (a<<16)|(b)|0x0000ff00); - } - } - mm_init(); vmm_init(); mouse_init(); - printf("HOS 0.1.1 - Kernel Size: %d kb\n", kernel_size()/1024); - printf("%x\t%x\n", read_cr0(), read_cr3()); vmm_enable_paging(); - printf("%x\t%x\n", read_cr0(), read_cr3()); - printf("Memory available to OS: %d MB (Bytes: %d)\n", mm_totalmem/0x100000, mm_totalmem); - vmm_map1(0x45000000, 0xB8000, 0x3); - *((word *)0x45000002) = 0x0444; - vmm_mapn(0x54FFF000, 0xB7000, 0x3, 2); - *((word *)0x55000020) = 0x0443; pic1_mask(0); //unmask IRQ's 0-7 pic2_mask(0); //unmask IRQ's 8-15 enable_ints(); + kbd_resetLEDs(); //after enabling interrupts!! + + printf("HOS 0.1.2 - Kernel Size: %d kb\n", kernel_size()/1024); + printf("Memory available to OS: %d MB (Bytes: %d)\n", mm_totalmem/0x100000, mm_totalmem); + dword key = 0; for (;;) { key = kbdWaitKey(); - putc(key); + if (((key & 0xFF00) >> 8) != 2) //key is not a control key + putc(key); } } +// main Interrupt Service Routine - handles all interrupts unless caught by kernel.asm void isr(dword num) { switch(num) { case 0x20: // IRQ0 - timer interrupt timer++; - (*(byte *)0xb8000)++; + (*(byte *)(0xb8000+3998))++; eoi(); break; case 0x21: // IRQ1 - keyboard interrupt diff --git a/keyboard.c b/keyboard.c index 689c81f..fd3e6e0 100644 --- a/keyboard.c +++ b/keyboard.c @@ -1,28 +1,29 @@ //Keyboard.c // Created: 04/17/03 Josh Holtrop -// Modified: 09/09/03 +// Modified: 10/30/03 //for HOS #define KBD_BUFFER_LENGTH 64 -byte kbdFlags = 0; -byte kbdAscii = 0; -byte kbdScan = 0; +byte kbdFlags = 0; //holds current keyboard flags - caps/num/scroll/shift/ctrl/alt +byte kbdAscii = 0; //holds ASCII value of a key pressed +byte kbdScan = 0; //holds the keyboard scan code of a key pressed -dword kbdBuffer[KBD_BUFFER_LENGTH]; -int kbdBufferStart = 0; -int kbdBufferLen = 0; -byte kbdExt = 0; -byte kbdExt2 = 0; +dword kbdBuffer[KBD_BUFFER_LENGTH]; //a buffer for all keypresses +int kbdBufferStart = 0; //position of next key in buffer +int kbdBufferLen = 0; //number of keys left in the buffer +byte kbdExt = 0; //# of extended key codes left to input +byte kbdExt2 = 0; //# of 2nd-set-extended key codes left to input byte ackReason = 0; //used to record the reason why we would get an acknowledge byte (0xFA) +//these arrays convert a keyboard scan code to an ASCII character value //nul esc bksp tab lctl lsft rsft lalt caps F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 numScrlNumPad------- unknown---- F11 F12 unknown.... const byte SCAN2ASCII[128] = "\000\0331234567890-=\010\011qwertyuiop[]\n\001asdfghjkl;'`\001\\zxcvbnm,./\001*\001 \001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001-\001\001\001+\001\001\001\001\001\002\002\002\001\001\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002"; const byte SCAN2ASCIISHIFT[128] = "\000\033!@#$%^&*()_+\010\011QWERTYUIOP{}\n\001ASDFGHJKL:\"~\001|ZXCVBNM<>?\001*\001 \001\001\001\001\001\001\001\001\001\001\001\001\001789-456+1230.\002\002\002\001\001\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002"; //====FUNCTIONS: - +// The Keyboard Interrupt Service Routine void isr_keyboard() { kbdScan = inportb(0x60); @@ -35,20 +36,20 @@ void isr_keyboard() if (kbdScan == 0xFA) //250 //ACKnowledge { + //printf("KBD_ACK 0x%x!\n", ackReason); if (ackReason == 0xED) //reset LEDs { - outportb(0x64, (kbdFlags & 0x07)); - printf("KBD_ACK!"); + outportb(0x60, (kbdFlags & 0x07)); } ackReason = 0; } - if (kbdScan == 224) //extended key + if (kbdScan == 224) //extended key { kbdExt = 1; eoi(); return; } - if (kbdScan == 225) + if (kbdScan == 225) //2nd-set-extended key { kbdExt2 = 2; eoi(); @@ -57,7 +58,7 @@ void isr_keyboard() //====handle control keys:: kbdAscii = 2; - switch (kbdScan) //control keys + switch (kbdScan) //control keys { case KBD_SCAN_LSHIFT: kbdFlags |= KBD_SHIFT; @@ -96,17 +97,17 @@ void isr_keyboard() case KBD_SCAN_CAPS+KBD_SCAN_RELEASED: kbdFlags ^= KBD_CAPS; kbdAscii = 1; - kbd_resetLEDs(); //update LEDs + kbd_resetLEDs(); //update LEDs break; case KBD_SCAN_SCROLL+KBD_SCAN_RELEASED: kbdFlags ^= KBD_SCROLL; kbdAscii = 1; - kbd_resetLEDs(); //update LEDs + kbd_resetLEDs(); //update LEDs break; case KBD_SCAN_NUM+KBD_SCAN_RELEASED: kbdFlags ^= KBD_NUM; kbdAscii = 1; - kbd_resetLEDs(); //update LEDs + kbd_resetLEDs(); //update LEDs break; } if (kbdAscii == 1) @@ -170,7 +171,7 @@ void isr_keyboard() } //====do something with key:: - if ((kbdScan == 83) & ((kbdFlags & KBD_CTRL) != 0) & ((kbdFlags & KBD_ALT) != 0)) + if ((kbdScan == 83) && (kbdFlags & KBD_CTRL) && (kbdFlags & KBD_ALT)) { printf("Initiating reboot."); restart(); @@ -196,19 +197,19 @@ void isr_keyboard() eoi(); -// if (key == 0xFA) //ACKnowledge -// outportb(0x60, 0x3); } -inline byte switchCase(byte asciiCode) +//Switches the case of an ASCII character +/*inline byte (byte asciiCode) { if ((asciiCode >= 'A') & (asciiCode <= 'Z')) return (asciiCode + ('a' - 'A')); if ((asciiCode >= 'a') & (asciiCode <= 'z')) return (asciiCode - ('a' - 'A')); return asciiCode; -} +}*/ +//Gets a key from the buffer, returns 0 if no keys available, returns immediately dword kbdGetKey() { if (kbdBufferLen == 0) //buffer empty @@ -221,6 +222,7 @@ dword kbdGetKey() return retVal; } +//Gets a key from the buffer, if no keys available, waits for one to be entered dword kbdWaitKey() { for (;;) @@ -236,10 +238,11 @@ dword kbdWaitKey() return retVal; } +//Resets the keyboard LEDs to reflect the current state of the num lock, caps lock, and scroll lock bits inline void kbd_resetLEDs() { - outportb(0x64, 0xED); - //outportb(0x64, (kbdFlags & 0x07)); + outportb(0x60, 0xED); + //outportb(0x60, (kbdFlags & 0x07)); ackReason = 0xED; } diff --git a/video.c b/video.c index 6566d02..8cf6935 100644 --- a/video.c +++ b/video.c @@ -31,6 +31,39 @@ void video_init(ModeInfoBlock *mib) else video_psetp(a, 0x00FFFFFF); } + + video_rectf(VXR*3/11, 0, VXR*4/11, VYR-1, 0x00000088); //test rectangles, draws "HOS" + video_rectf(VXR*7/11, 0, VXR*8/11, VYR-1, 0x00000088); + video_rectf(VXR/11, 0, VXR*2/11, VYR*2/5, 0x00000088); + video_rectf(VXR/11, VYR*3/5, VXR*2/11, VYR-1, 0x00000088); + video_rectf(VXR*5/11, VYR/5, VXR*6/11, VYR*4/5, 0x00000088); + video_rectf(VXR*9/11, VYR/5, VXR-1, VYR*2/5, 0x00000088); + video_rectf(VXR*8/11, VYR*3/5, VXR*10/11, VYR*4/5, 0x00000088); + + video_vert(10, 10, 16, 0x00ffff00); //should be yellow 'H' + video_horiz(13, 10, 14, 0x00ffff00); + video_vert(14, 10, 16, 0x00ffff00); + + video_horiz(10, 17, 21, 0x00ffff00); + video_vert(19, 10, 16, 0x00ffff00); + video_horiz(16, 17, 21, 0x00ffff00); + + int b; + for (a = 0; a < 256; a++) + { + for (b = 0; b < 256; b++) + { + video_pset(a+5, b+30, (a<<16)|(b<<8)); + video_pset(a+270, b+30, (a<<8)|(b)); + video_pset(a+535, b+30, (a<<16)|(b)); + + video_pset(a+5, b+290, (a<<16)|(b<<8)|0x000000ff); + video_pset(a+270, b+290, (a<<8)|(b)|0x00ff0000); + video_pset(a+535, b+290, (a<<16)|(b)|0x0000ff00); + } + } + + } void video_horiz(int y, int x1, int x2, dword color) diff --git a/vmm.c b/vmm.c index 112ce8b..1fdd9b9 100644 --- a/vmm.c +++ b/vmm.c @@ -64,6 +64,7 @@ int vmm_map1(dword virtual, dword physical, dword flags) if (ptp->page[pte] & 0x01) return 3; // ERROR 3: page table entry already exists ptp->page[pte] = physical | flags; + //invlpg(); return 0; } @@ -76,8 +77,7 @@ int vmm_mapn(dword virtual, dword physical, dword flags, dword n) dword pa = physical; for (mapped = 0; mapped < n; mapped++) { - result = vmm_map1(va, pa, flags); - if (result != 0) + if (result = vmm_map1(va, pa, flags)) { if (mapped > 0) vmm_unmapn(virtual, mapped); @@ -86,6 +86,8 @@ int vmm_mapn(dword virtual, dword physical, dword flags, dword n) va += 4096; pa += 4096; } + //invlpg(); + return 0; } int vmm_unmap1(dword virtual) @@ -94,14 +96,28 @@ int vmm_unmap1(dword virtual) int pte = (virtual & 0x003FF000) >> 12; if (virtual & 0x00000FFF) return 1; // ERROR 1: address not page-aligned + if (!(vmm_PDBR->pageTables[pde] & 0x01)) + return 2; // ERROR 2: page table not present PageTable *ptp = (PageTable *)(vmm_PDBR->pageTables[pde] & 0xFFFFF000); - + ptp->page[pte] = 0; + //invlpg(); + return 0; } int vmm_unmapn(dword virtual, dword n) { - + int reslt; + int i; + for (i = 0; i < n; i++) + { + if (reslt = vmm_unmap1(virtual)) + return reslt; + virtual += 4096; + } + vmm_walkPageTables(); + //invlpg(); + return 0; } @@ -114,6 +130,34 @@ void vmm_init_pagetable(dword address) } +int vmm_walkPageTables() +{ + int pde; + int pte; + int used_ptes; + PageTable *ptp; + for (pde = 0; pde < 1024; pde++) + { + if (vmm_PDBR->pageTables[pde] & 0x01) + { + used_ptes = 0; + ptp = (PageTable *)(vmm_PDBR->pageTables[pde] & 0xFFFFF000); + for (pte = 0; pte < 1024; pte++) + { + if (ptp->page[pte] & 0x01) //page table entry present + used_ptes++; + } + if (!(used_ptes)) //no used pte's -- remove page table & page directory entry + { + mm_pfree(ptp); + vmm_PDBR->pageTables[pde] = 0; + } + } + } + return 0; +} + + void *malloc(dword bytes) { diff --git a/vmm.h b/vmm.h index 0a0fdf9..b955f99 100644 --- a/vmm.h +++ b/vmm.h @@ -22,6 +22,7 @@ int vmm_mapn(dword virtual, dword physical, dword flags, dword n); int vmm_unmap1(dword virtual); int vmm_unmapn(dword virtual, dword n); void vmm_init_pagetable(dword address); +int vmm_walkPageTables();