From 71aaa7a598dca23d5134f195d59ee572b88d2de3 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Tue, 23 Dec 2003 22:00:00 -0500 Subject: [PATCH] Import backup from 2003-12-23 --- k_defines.h | 2 +- kernel.asm | 2 +- kernel.c | 18 ++- lib/io.asm | 8 +- lib/misc.asm | 2 +- lib/string.c | 13 --- lib/string.h | 8 -- mm.c | 306 ++++++++++++--------------------------------------- mm.h | 24 +--- video.c | 17 ++- video.h | 2 + vmm.c | 130 +--------------------- vmm.h | 15 +-- 13 files changed, 110 insertions(+), 437 deletions(-) delete mode 100644 lib/string.c delete mode 100644 lib/string.h diff --git a/k_defines.h b/k_defines.h index e02de99..486a652 100644 --- a/k_defines.h +++ b/k_defines.h @@ -29,7 +29,7 @@ #define YELLOW_TXT 0x0E #define BRWHITE_TXT 0x0F -#define FREERAM_START 0x268000 +#define FREERAM_START 0x368000 // 0x368000 is first available byte (this is right after the initrd @ 2mb, 1440kb. #define MAX_RAM 0x40000000 //1gb maximum RAM supported #define PID_KERNEL 0x02 //kernel's PID diff --git a/kernel.asm b/kernel.asm index 4d8a3eb..2b15735 100644 --- a/kernel.asm +++ b/kernel.asm @@ -86,7 +86,7 @@ newgdtcontinue: mov gs, ax mov fs, ax mov ss, ax - mov esp, 0xc01ffffc ;stack just under 2mb, moves downward + mov esp, 0xc01ffffc ;stack just under 3gb+2mb, moves downward lidt [idtr] ;load idt call _k_init diff --git a/kernel.c b/kernel.c index ebaf3a6..b4ef426 100644 --- a/kernel.c +++ b/kernel.c @@ -6,7 +6,6 @@ #include "k_defines.h" //#DEFINE's for kernel -#include "lib/string.h" //library string functions #include "lib/io.h" //library input/output functions #include "functions.h" //general functions @@ -34,30 +33,27 @@ extern dword read_cr3(); #include "video.c" dword timer = 0; -dword *videoMode; //Main kernel initialization method void k_init() { // ===== Initialization fdc_sendDOR(0x0C); //turn off floppy motor!! + console_cls(); + video_init(); mm_init(); vmm_init(); - console_cls(); remap_pics(0x20, 0x28); init_timer(); - videoMode = (dword *)0x90002; - if (*videoMode) - video_init((ModeInfoBlock *) 0x90306); mouse_init(); 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.12 - Kernel Size: %d kb\n", kernel_size()/1024); - printf("Memory available to OS: %d MB (Bytes: %d)\n", mm_totalmem/0x100000, mm_totalmem); - printf("Free memory: %d bytes\n", mm_freemem()); + + printf("HOS 0.12 - Kernel Size: %u kb\n", kernel_size()/1024); + printf("Memory available to OS: %u MB (Bytes: %u)\n", mm_megabytes, mm_totalmem); + printf("Free memory: %u bytes\n", mm_freemem()); dword key = 0; for (;;) @@ -75,7 +71,7 @@ void isr(dword num) { case 0x20: // IRQ0 - timer interrupt timer++; - (*(byte *)(0xb8000))++; + (*(byte *)(0xc00b8000))++; eoi(); break; case 0x21: // IRQ1 - keyboard interrupt diff --git a/lib/io.asm b/lib/io.asm index d828bb0..5852a23 100644 --- a/lib/io.asm +++ b/lib/io.asm @@ -107,7 +107,7 @@ _putc: jz putc_tab shl ebx, 1 - add ebx, 0xb8000 + add ebx, 0xc00b8000 mov ah, 0x07 mov [ebx], ax mov eax, ecx @@ -274,8 +274,8 @@ printf_done: ; _console_scroll: pusha - mov esi, 0xb8000+160 - mov edi, 0xb8000 + mov esi, 0xc00b8000+160 + mov edi, 0xc00b8000 mov ecx, 960 ;(2000-80)/2 console_scroll_loop: lodsd @@ -294,7 +294,7 @@ console_scroll_loop2: ; _console_cls: pusha - mov edi, 0xb8000 + mov edi, 0xc00b8000 mov ax, 0x0720 mov ecx, 2000 console_cls_loop: diff --git a/lib/misc.asm b/lib/misc.asm index 187f931..dfb3d49 100644 --- a/lib/misc.asm +++ b/lib/misc.asm @@ -11,7 +11,7 @@ _memcpy: push ecx mov esi, [ebp+8] mov edi, [ebp+12] - mov ecx, [ebp+14] + mov ecx, [ebp+16] rep movsb diff --git a/lib/string.c b/lib/string.c deleted file mode 100644 index e7855ec..0000000 --- a/lib/string.c +++ /dev/null @@ -1,13 +0,0 @@ - -#include "string.h" - -int strlen(char *str) -{ - int retn = 0; - while (*str++ != 0) - retn++; - return retn; -} - - - diff --git a/lib/string.h b/lib/string.h deleted file mode 100644 index 346a277..0000000 --- a/lib/string.h +++ /dev/null @@ -1,8 +0,0 @@ - -#ifndef __HSTRING_H__ -#define __HSTRING_H__ __HSTRING_H__ - -int strlen(char *str); - -#endif - diff --git a/mm.c b/mm.c index 466e35a..85ae7db 100644 --- a/mm.c +++ b/mm.c @@ -1,273 +1,105 @@ // mm.c // 09/01/03 Josh Holtrop -// 0x368000 is first available byte (this is right after the kernel @ 1mb and the initrd @ 2mb, 1440kb. - - -//Pointer to the first pageblock in the linked list -pageblock *first_pageblock = (pageblock *) 0; //The total amount of physical memory available (bytes) -dword mm_totalmem = 0x100000; //start counting from 1mb -//The highest physical address -dword mm_highestAddress = 0; +#define BITMAP_SIZE 0x20000 +dword mm_totalmem = 0; +dword mm_megabytes; +byte page_bitmap[BITMAP_SIZE]; //used to store a bit for each page that is used, 0 if available + //0x20000*(8 bits/byte)=0x100000 pages in 4gb total //This function initializes the memory manager's linked list, filling it with the // memory areas returned by bios interrupt 0x8E20 void mm_init() { - dword *memmap_entries = (dword *) 0x9040A; - memmap_entry *maps = (memmap_entry *) 0x92000; + dword memmap_entries = *(dword *)0xC009040A; + memmap_entry *maps = (memmap_entry *) 0xC0092000; dword a; - for (a=0;a<(*memmap_entries);a++) + for (a = 0; a < BITMAP_SIZE; a++) + { + page_bitmap[a] = 0xFF; //all pages used + } + for (a = 0; a < memmap_entries; a++) { if (maps[a].attributes == 1) // (1) mem free to OS { mm_totalmem += maps[a].limit.lowdword; - if (mm_highestAddress < (maps[a].base.lowdword + maps[a].limit.lowdword)) - mm_highestAddress = maps[a].base.lowdword + maps[a].limit.lowdword; - if ((maps[a].base.lowdword + maps[a].limit.lowdword) > (FREERAM_START+8192)) //goes past where we start freeram + if ((maps[a].base.lowdword + maps[a].limit.lowdword) >= (FREERAM_START+4096)) //goes past where we start freeram { if (maps[a].base.lowdword < FREERAM_START) { - maps[a].limit.lowdword = maps[a].limit.lowdword - (FREERAM_START - maps[a].base.lowdword); - maps[a].base.lowdword = FREERAM_START; //block at least 4kb, starts >= FREERAM_START + mm_pfreen(FREERAM_START, (maps[a].limit.lowdword - (FREERAM_START - maps[a].base.lowdword)) >> 12); } - if (first_pageblock == 0) //no pageblock page set up yet, so set it up here + else { - first_pageblock = (pageblock *) maps[a].base.lowdword; - maps[a].base.lowdword += 4096; - maps[a].limit.lowdword -= 4096; - mm_init_pageblockpage(first_pageblock); - first_pageblock->base = maps[a].base.lowdword; - first_pageblock->length = maps[a].limit.lowdword / 4096; - first_pageblock->pid = MM_PB_AVAIL; + mm_pfreen(maps[a].base.lowdword, maps[a].limit.lowdword >> 12); //set the appropriate bits as "free" in the page bitmap } - else //first_pageblock already set up, add on segment + } + } + } + if (mm_totalmem % 0x100000) + mm_megabytes = (mm_totalmem >> 20) + 1; + else + mm_megabytes = mm_totalmem >> 20; +} + + +void mm_pfreen(dword base, dword pages) +{ + dword a; + dword max = base + (pages << 12); + for (a = base; a < max; a += 4096) + { + mm_pfree(a); + } +} + + +void mm_pfree(dword base) +{ +// dword pageNumber = base >> 12; // >>12 == /4096 + dword byteNumber = base >> 15; //pageNumber >> 3; //pageNumber/8 + dword bitNumber = (base >> 12) % 8; //pageNumber % 8; + page_bitmap[byteNumber] = page_bitmap[byteNumber] & ((0x01 << bitNumber) ^ 0xFF); +} + + +void *mm_palloc() +{ + dword bite; + for (bite = 0; bite < BITMAP_SIZE; bite++) + { + if (page_bitmap[bite] != 0xFF) //there is an available page within this 8-page region + { + int bit; + for (bit = 0; bit < 8; bit++) + { + if (!(page_bitmap[bite] & (1 << bit))) //this bite/bit combination is available { - pageblock *pb = first_pageblock; - for (;;) - { - if (pb->pid == MM_PB_NP) - break; - else - pb++; - } - pb->base = maps[a].base.lowdword; - pb->length = maps[a].limit.lowdword / 4096; - pb->pid = MM_PB_AVAIL; + return (void *)((bite << 15) + (bit << 12)); } } } + bite++; } - if (first_pageblock == 0) - { - printf("ERROR! NO INITIAL PAGE BLOCK CREATED."); - asm("cli"); - asm("hlt"); - for (;;) - ; - } + return 0; //no free page } - -//This function initializes a pageblock to be full of empty pointers -void mm_init_pageblockpage(pageblock *pbp) +dword mm_freemem() { - int a; - for (a=0; a<256; a++) // 256 pageblock entries * 16 bytes per page block entry = 4096 bytes (1 page of pageblock entries) + dword a; + dword pages = 0; + for (a = 0; a < BITMAP_SIZE; a++) { - pbp[a].base = 0; - pbp[a].length = 0; - pbp[a].pid = MM_PB_NP; - if (a<255) - pbp[a].link = (dword)(&pbp[a+1]); - else - pbp[a].link = 0; - } -} - - -//This function allocates a certain number of physical pages for a particular process -//Returns: -// 0 - no free mem, invalied PID -// void* - physical address of allocated pages -void *mm_palloc(dword numpages, dword proc_pid) -{ - if (proc_pid < PID_KERNEL) - return 0; - pageblock *pb = first_pageblock; - if (mm_freeentries() < 2) - { - if(mm_new_pageblock_page() == 0) - return 0; - } - pageblock *newentry = mm_nextpageblockentry(); - for (;;) - { - if ((pb->pid == MM_PB_AVAIL) && (pb->length >= numpages)) - break; - if (pb->link == 0) - return 0; - pb = (pageblock *)pb->link; - } - if (pb->length == numpages) //dont need a new entry, just mark this one as used :) - { - pb->pid = proc_pid; - return (void *)pb->base; - } - else //subtract out allocated number of pages from length - { - newentry->base = pb->base; - newentry->length = numpages; - newentry->pid = proc_pid; - pb->base += (numpages * 4096); - pb->length -= numpages; - return (void *)newentry->base; - } -} - - -//This method returns the number of free pageblock entries at the end of the linked list -dword mm_freeentries() -{ - pageblock *pb = first_pageblock; - dword counter = 0; - for (;;) - { - if (pb->pid == MM_PB_NP) - counter++; - if (pb->link == 0) - return counter; - pb = (pageblock *) pb->link; - } -} - - -//This method creates a new page used to hold more pageblock entries at the end of the linked list -//Returns: -// 0 - no free pages -// pageblock* - address of pageblock page -pageblock *mm_new_pageblock_page() //as of 09/26/03 this method leaks 4kb main memory per call, unrecoverable -{ - pageblock *pb = first_pageblock; - for (;;) - { - if ((pb->pid == MM_PB_AVAIL) && (pb->length > 1)) + int bit; + for (bit = 0; bit < 8; bit++) { - pageblock *retval = (pageblock *)pb->base; - pb->base += 4096; - pb->length--; - mm_init_pageblockpage(retval); //zeros out, links new pageblock page - mm_lastpageblockentry()->link = (dword)retval; //set up link to new pageblock page - return retval; + if (!(page_bitmap[a] & (1 << bit))) + pages++; } - pb = (pageblock *) pb->link; - if (pb == 0) - return 0; - } -} - - -//This method frees a physical page -//Returns: -// 2 - pointer to free was a null pointer -// 1 - address not found -// 0 - all went well -int mm_pfree(void *ptr) -{ - if (ptr == 0) - return 2; - pageblock *pb = first_pageblock; - dword tofree = (dword) ptr; - for (;;) - { - if (pb->base == tofree) // && (pb->pid == MM_PB_USED)) - { - pb->pid = MM_PB_AVAIL; //found block, mark available / coalesce it - mm_coalesce(pb); - return 0; - } - if (pb->link == 0) - return 1; - pb = (pageblock *) pb->link; - } -} - - -//This method returns a pointer to the last pageblock in the linked list -pageblock *mm_lastpageblockentry() -{ - pageblock *pb = first_pageblock; - for (;;) - { - if (pb->link == 0) - return pb; - pb = (pageblock *)pb->link; - } -} - - -//This method returns the next available-for-use pageblock entry -// or 0, if they are all used -pageblock *mm_nextpageblockentry() -{ - pageblock *pb = first_pageblock; - for (;;) - { - if (pb->pid == MM_PB_NP) - return pb; - if (pb->link == 0) - return 0; - pb = (pageblock *)pb->link; - } -} - - -//This method returns the amount of free physical RAM -dword mm_freemem() -{ - dword amount = 0; - pageblock *pb = first_pageblock; - for (;;) - { - if (pb->pid == MM_PB_AVAIL) - amount += (pb->length)*4096; - if (pb->link == 0) - return amount; - pb = (pageblock *) pb->link; - } -} - - -//This method "walks" through the linked list of pageblock entries and -// combines any two entries that are adjacent and of the same type -void mm_coalesce(pageblock *pb) -{ - pageblock *pbc = first_pageblock; - for (;;) - { - if (pbc->pid == pb->pid) //pid fields must match, both same process, both avail, or both not present - { - if ((pbc->base + (pbc->length * 4096)) == pb->base) //pbc ends where pb starts - { - pbc->length += pb->length; - pb->pid = MM_PB_NP; - mm_coalesce(pbc); //recursion: checks for any more page blocks to coalesce if one found - return; //exit this recursion... - } - if ((pb->base + (pb->length * 4096)) == pbc->base) //pb ends where pbc starts - { - pb->length += pbc->length; - pbc->pid = MM_PB_NP; - mm_coalesce(pb); - return; - } - } - if (pbc->link == 0) - return; - pbc = (pageblock *)pbc->link; } + return pages << 12; } diff --git a/mm.h b/mm.h index 34d3343..3de6ab2 100644 --- a/mm.h +++ b/mm.h @@ -7,28 +7,14 @@ typedef struct { } __attribute__((packed)) memmap_entry; -typedef struct { - dword base; - dword length; //in pages - dword pid; //normally PID of process, use NP, AVAIL for special flags - dword link; //leave dword instead of pointer so i dont have to worry about pointer arithmetic -} __attribute__ ((packed)) pageblock; //16 byte pageblock entry - 256 entries = 1 page - void mm_init(); -void mm_init_pageblockpage(pageblock *pbp); -void *mm_palloc(dword numpages, dword proc_pid); -void mm_coalesce(pageblock *pb); -int mm_pfree(void *ptr); -dword mm_freeentries(); +void mm_pfreen(dword base, dword pages); +void mm_pfree(dword base); +void *mm_palloc(); dword mm_freemem(); -pageblock *mm_new_pageblock_page(); -pageblock *mm_lastpageblockentry(); -pageblock *mm_nextpageblockentry(); - - -#define MM_PB_NP 0x00 //00000000 -#define MM_PB_AVAIL 0x01 //00000001 + + diff --git a/video.c b/video.c index 26ffd3c..a922527 100644 --- a/video.c +++ b/video.c @@ -4,9 +4,17 @@ //Initialized the video mode information block video_mode and allocated double-buffer memory for graphics display -void video_init(ModeInfoBlock *mib) +void video_init() { - video_mode = *mib; + videoMode = *(dword *)0xC0090002; + + if (!videoMode) //we are in console mode + { + video_psetp = &video_psetpnull; + return; + } + + video_mode = *(ModeInfoBlock *) 0xC0090306; switch(video_mode.BitsPerPixel) { @@ -139,5 +147,8 @@ void video_psetp32(int pixel, dword color) vid_ptr32[pixel] = color; } - +//Dummy function to not draw anything if there is no graphical mode enabled +void video_psetpnull(int pixel, dword color) +{ +} diff --git a/video.h b/video.h index 2c4a088..f30028b 100644 --- a/video.h +++ b/video.h @@ -11,6 +11,7 @@ inline void video_pset(int x, int y, dword color); void video_psetp16(int pixel, dword color); void video_psetp24(int pixel, dword color); void video_psetp32(int pixel, dword color); +void video_psetpnull(int pixel, dword color); void video_renderChar(int x, int y, int character, dword color); typedef struct{ @@ -53,6 +54,7 @@ typedef struct{ } ModeInfoBlock; ModeInfoBlock video_mode; +dword videoMode; //what video mode # we are in, 0 for console mode byte *vid_ptr24; word *vid_ptr16; dword *vid_ptr32; diff --git a/vmm.c b/vmm.c index d15ecee..3669a97 100644 --- a/vmm.c +++ b/vmm.c @@ -2,140 +2,20 @@ // vmm.c // Author: Josh Holtrop // Date: 09/30/03 - -PageDirectory *vmm_PDBR = (PageDirectory *)0x104000; -dword vmm_first_virtual_address = 0; +// Rewritten from scratch: 12/23/03 void vmm_init() { - if (mm_totalmem % 4096) - vmm_first_virtual_address = mm_totalmem + (4096 - (mm_totalmem % 4096)); - else - vmm_first_virtual_address = mm_totalmem; + dword *pagetables = (dword *)0xC0104000; //this is the location of the page directory + pagetables[0x3FF] = 0x104000|0x03; //the last page directory entry points to the page directory itself + if (videoMode) //we are in a graphical mode + { - if (vmm_mapn(0, 0, 0x03, mm_totalmem/4096+1)) - { - printf("Could not page in all physical RAM!\n"); - //halt(); - } - //we also need to map in the video framebuffer memory: - if (video_mode.PhysBasePtr > 0 && video_mode.BitsPerPixel > 0) - { - if (vmm_mapn(video_mode.PhysBasePtr, video_mode.PhysBasePtr, 0x03, ((video_mode.BitsPerPixel>>3) * video_mode.XResolution * video_mode.YResolution)/4096+1)) - { - printf("Could not page in video memory at 0x%x!\n", video_mode.PhysBasePtr); - halt(); - } } } -int vmm_map1(dword virtual, dword physical, dword flags) -{ - if (virtual & 0x00000FFF) - return 1; // ERROR 1: address not page-aligned - if (physical & 0x00000FFF) - return 1; // ERROR 1: address not page-aligned - int pde = (virtual & 0xFFC00000) >> 22; - int pte = (virtual & 0x003FF000) >> 12; - if (!(vmm_PDBR->pageTables[pde] & 0x01)) - { - vmm_PDBR->pageTables[pde] = (dword)mm_palloc(1, PID_KERNEL) | 0x7; //user, r/w, present - vmm_init_pagetable(vmm_PDBR->pageTables[pde] & 0xFFFFF000); - if (vmm_PDBR->pageTables[pde] == 0x07) - return 2; // ERROR 2: page table could not be created - } - PageTable *ptp = (PageTable *)(vmm_PDBR->pageTables[pde] & 0xFFFFF000); - if (ptp->page[pte] & 0x01) - return 3; // ERROR 3: page table entry already exists - ptp->page[pte] = physical | flags; - //invlpg(); - return 0; -} - - -int vmm_mapn(dword virtual, dword physical, dword flags, dword n) -{ - int mapped; - dword va = virtual; - dword pa = physical; - for (mapped = 0; mapped < n; mapped++) - { - vmm_map1(va, pa, flags); - va += 4096; - pa += 4096; - } - //invlpg(); - return 0; -} - -int vmm_unmap1(dword virtual) -{ - if (virtual & 0x00000FFF) - return 1; // ERROR 1: address not page-aligned - int pde = (virtual & 0xFFC00000) >> 22; - int pte = (virtual & 0x003FF000) >> 12; - 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; -} - - -void vmm_init_pagetable(dword address) -{ - PageTable *ptp = (PageTable *)address; - int n; - for (n = 0; n < 1024; n++) - ptp->page[n] = 0; -} - - -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 165d864..11b969f 100644 --- a/vmm.h +++ b/vmm.h @@ -2,26 +2,13 @@ // vmm.h // Author: Josh Holtrop // Date: 09/30/03 +// Rewritten from scratch: 12/23/03 -typedef struct { - dword page[1024]; -} PageTable; - -typedef struct { - dword pageTables[1024]; -} PageDirectory; - void vmm_init(); void *malloc(dword bytes); int free(void *ptr); -int vmm_map1(dword virtual, dword physical, dword flags); -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();