Import backup from 2003-12-23

This commit is contained in:
Josh Holtrop 2003-12-23 22:00:00 -05:00
parent 9070a76b18
commit 71aaa7a598
13 changed files with 110 additions and 437 deletions

View File

@ -29,7 +29,7 @@
#define YELLOW_TXT 0x0E #define YELLOW_TXT 0x0E
#define BRWHITE_TXT 0x0F #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 MAX_RAM 0x40000000 //1gb maximum RAM supported
#define PID_KERNEL 0x02 //kernel's PID #define PID_KERNEL 0x02 //kernel's PID

View File

@ -86,7 +86,7 @@ newgdtcontinue:
mov gs, ax mov gs, ax
mov fs, ax mov fs, ax
mov ss, 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 lidt [idtr] ;load idt
call _k_init call _k_init

View File

@ -6,7 +6,6 @@
#include "k_defines.h" //#DEFINE's for kernel #include "k_defines.h" //#DEFINE's for kernel
#include "lib/string.h" //library string functions
#include "lib/io.h" //library input/output functions #include "lib/io.h" //library input/output functions
#include "functions.h" //general functions #include "functions.h" //general functions
@ -34,30 +33,27 @@ extern dword read_cr3();
#include "video.c" #include "video.c"
dword timer = 0; dword timer = 0;
dword *videoMode;
//Main kernel initialization method //Main kernel initialization method
void k_init() void k_init()
{ {
// ===== Initialization // ===== Initialization
fdc_sendDOR(0x0C); //turn off floppy motor!! fdc_sendDOR(0x0C); //turn off floppy motor!!
console_cls();
video_init();
mm_init(); mm_init();
vmm_init(); vmm_init();
console_cls();
remap_pics(0x20, 0x28); remap_pics(0x20, 0x28);
init_timer(); init_timer();
videoMode = (dword *)0x90002;
if (*videoMode)
video_init((ModeInfoBlock *) 0x90306);
mouse_init(); mouse_init();
pic1_mask(0); //unmask IRQ's 0-7 pic1_mask(0); //unmask IRQ's 0-7
pic2_mask(0); //unmask IRQ's 8-15 pic2_mask(0); //unmask IRQ's 8-15
enable_ints(); enable_ints();
kbd_resetLEDs(); //after enabling interrupts!! kbd_resetLEDs(); //after enabling interrupts!!
printf("HOS 0.12 - Kernel Size: %d kb\n", kernel_size()/1024); printf("HOS 0.12 - Kernel Size: %u kb\n", kernel_size()/1024);
printf("Memory available to OS: %d MB (Bytes: %d)\n", mm_totalmem/0x100000, mm_totalmem); printf("Memory available to OS: %u MB (Bytes: %u)\n", mm_megabytes, mm_totalmem);
printf("Free memory: %d bytes\n", mm_freemem()); printf("Free memory: %u bytes\n", mm_freemem());
dword key = 0; dword key = 0;
for (;;) for (;;)
@ -75,7 +71,7 @@ void isr(dword num)
{ {
case 0x20: // IRQ0 - timer interrupt case 0x20: // IRQ0 - timer interrupt
timer++; timer++;
(*(byte *)(0xb8000))++; (*(byte *)(0xc00b8000))++;
eoi(); eoi();
break; break;
case 0x21: // IRQ1 - keyboard interrupt case 0x21: // IRQ1 - keyboard interrupt

View File

@ -107,7 +107,7 @@ _putc:
jz putc_tab jz putc_tab
shl ebx, 1 shl ebx, 1
add ebx, 0xb8000 add ebx, 0xc00b8000
mov ah, 0x07 mov ah, 0x07
mov [ebx], ax mov [ebx], ax
mov eax, ecx mov eax, ecx
@ -274,8 +274,8 @@ printf_done:
; ;
_console_scroll: _console_scroll:
pusha pusha
mov esi, 0xb8000+160 mov esi, 0xc00b8000+160
mov edi, 0xb8000 mov edi, 0xc00b8000
mov ecx, 960 ;(2000-80)/2 mov ecx, 960 ;(2000-80)/2
console_scroll_loop: console_scroll_loop:
lodsd lodsd
@ -294,7 +294,7 @@ console_scroll_loop2:
; ;
_console_cls: _console_cls:
pusha pusha
mov edi, 0xb8000 mov edi, 0xc00b8000
mov ax, 0x0720 mov ax, 0x0720
mov ecx, 2000 mov ecx, 2000
console_cls_loop: console_cls_loop:

View File

@ -11,7 +11,7 @@ _memcpy:
push ecx push ecx
mov esi, [ebp+8] mov esi, [ebp+8]
mov edi, [ebp+12] mov edi, [ebp+12]
mov ecx, [ebp+14] mov ecx, [ebp+16]
rep movsb rep movsb

View File

@ -1,13 +0,0 @@
#include "string.h"
int strlen(char *str)
{
int retn = 0;
while (*str++ != 0)
retn++;
return retn;
}

View File

@ -1,8 +0,0 @@
#ifndef __HSTRING_H__
#define __HSTRING_H__ __HSTRING_H__
int strlen(char *str);
#endif

274
mm.c
View File

@ -1,273 +1,105 @@
// mm.c // mm.c
// 09/01/03 Josh Holtrop // 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) //The total amount of physical memory available (bytes)
dword mm_totalmem = 0x100000; //start counting from 1mb #define BITMAP_SIZE 0x20000
//The highest physical address dword mm_totalmem = 0;
dword mm_highestAddress = 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 //This function initializes the memory manager's linked list, filling it with the
// memory areas returned by bios interrupt 0x8E20 // memory areas returned by bios interrupt 0x8E20
void mm_init() void mm_init()
{ {
dword *memmap_entries = (dword *) 0x9040A; dword memmap_entries = *(dword *)0xC009040A;
memmap_entry *maps = (memmap_entry *) 0x92000; memmap_entry *maps = (memmap_entry *) 0xC0092000;
dword a; 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 if (maps[a].attributes == 1) // (1) mem free to OS
{ {
mm_totalmem += maps[a].limit.lowdword; mm_totalmem += maps[a].limit.lowdword;
if (mm_highestAddress < (maps[a].base.lowdword + maps[a].limit.lowdword)) if ((maps[a].base.lowdword + maps[a].limit.lowdword) >= (FREERAM_START+4096)) //goes past where we start freeram
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 < FREERAM_START) if (maps[a].base.lowdword < FREERAM_START)
{ {
maps[a].limit.lowdword = maps[a].limit.lowdword - (FREERAM_START - maps[a].base.lowdword); mm_pfreen(FREERAM_START, (maps[a].limit.lowdword - (FREERAM_START - maps[a].base.lowdword)) >> 12);
maps[a].base.lowdword = FREERAM_START; //block at least 4kb, starts >= FREERAM_START
} }
if (first_pageblock == 0) //no pageblock page set up yet, so set it up here
{
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;
}
else //first_pageblock already set up, add on segment
{
pageblock *pb = first_pageblock;
for (;;)
{
if (pb->pid == MM_PB_NP)
break;
else else
pb++;
}
pb->base = maps[a].base.lowdword;
pb->length = maps[a].limit.lowdword / 4096;
pb->pid = MM_PB_AVAIL;
}
}
}
}
if (first_pageblock == 0)
{ {
printf("ERROR! NO INITIAL PAGE BLOCK CREATED."); mm_pfreen(maps[a].base.lowdword, maps[a].limit.lowdword >> 12); //set the appropriate bits as "free" in the page bitmap
asm("cli");
asm("hlt");
for (;;)
;
} }
} }
}
}
if (mm_totalmem % 0x100000)
//This function initializes a pageblock to be full of empty pointers mm_megabytes = (mm_totalmem >> 20) + 1;
void mm_init_pageblockpage(pageblock *pbp)
{
int a;
for (a=0; a<256; a++) // 256 pageblock entries * 16 bytes per page block entry = 4096 bytes (1 page of pageblock entries)
{
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 else
pbp[a].link = 0; mm_megabytes = mm_totalmem >> 20;
}
} }
//This function allocates a certain number of physical pages for a particular process void mm_pfreen(dword base, dword pages)
//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) dword a;
return 0; dword max = base + (pages << 12);
pageblock *pb = first_pageblock; for (a = base; a < max; a += 4096)
if (mm_freeentries() < 2)
{ {
if(mm_new_pageblock_page() == 0) mm_pfree(a);
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 void mm_pfree(dword base)
dword mm_freeentries()
{ {
pageblock *pb = first_pageblock; // dword pageNumber = base >> 12; // >>12 == /4096
dword counter = 0; dword byteNumber = base >> 15; //pageNumber >> 3; //pageNumber/8
for (;;) dword bitNumber = (base >> 12) % 8; //pageNumber % 8;
{ page_bitmap[byteNumber] = page_bitmap[byteNumber] & ((0x01 << bitNumber) ^ 0xFF);
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 void *mm_palloc()
//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; dword bite;
for (;;) for (bite = 0; bite < BITMAP_SIZE; bite++)
{ {
if ((pb->pid == MM_PB_AVAIL) && (pb->length > 1)) if (page_bitmap[bite] != 0xFF) //there is an available page within this 8-page region
{ {
pageblock *retval = (pageblock *)pb->base; int bit;
pb->base += 4096; for (bit = 0; bit < 8; bit++)
pb->length--; {
mm_init_pageblockpage(retval); //zeros out, links new pageblock page if (!(page_bitmap[bite] & (1 << bit))) //this bite/bit combination is available
mm_lastpageblockentry()->link = (dword)retval; //set up link to new pageblock page {
return retval; return (void *)((bite << 15) + (bit << 12));
} }
pb = (pageblock *) pb->link;
if (pb == 0)
return 0;
} }
}
bite++;
}
return 0; //no free page
} }
//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 mm_freemem()
{ {
dword amount = 0; dword a;
pageblock *pb = first_pageblock; dword pages = 0;
for (;;) for (a = 0; a < BITMAP_SIZE; a++)
{ {
if (pb->pid == MM_PB_AVAIL) int bit;
amount += (pb->length)*4096; for (bit = 0; bit < 8; bit++)
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 (!(page_bitmap[a] & (1 << bit)))
{ pages++;
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 pages << 12;
return;
pbc = (pageblock *)pbc->link;
}
} }

24
mm.h
View File

@ -7,28 +7,14 @@ typedef struct {
} __attribute__((packed)) memmap_entry; } __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();
void mm_init_pageblockpage(pageblock *pbp); void mm_pfreen(dword base, dword pages);
void *mm_palloc(dword numpages, dword proc_pid); void mm_pfree(dword base);
void mm_coalesce(pageblock *pb); void *mm_palloc();
int mm_pfree(void *ptr);
dword mm_freeentries();
dword mm_freemem(); 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

17
video.c
View File

@ -4,9 +4,17 @@
//Initialized the video mode information block video_mode and allocated double-buffer memory for graphics display //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) switch(video_mode.BitsPerPixel)
{ {
@ -139,5 +147,8 @@ void video_psetp32(int pixel, dword color)
vid_ptr32[pixel] = 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)
{
}

View File

@ -11,6 +11,7 @@ inline void video_pset(int x, int y, dword color);
void video_psetp16(int pixel, dword color); void video_psetp16(int pixel, dword color);
void video_psetp24(int pixel, dword color); void video_psetp24(int pixel, dword color);
void video_psetp32(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); void video_renderChar(int x, int y, int character, dword color);
typedef struct{ typedef struct{
@ -53,6 +54,7 @@ typedef struct{
} ModeInfoBlock; } ModeInfoBlock;
ModeInfoBlock video_mode; ModeInfoBlock video_mode;
dword videoMode; //what video mode # we are in, 0 for console mode
byte *vid_ptr24; byte *vid_ptr24;
word *vid_ptr16; word *vid_ptr16;
dword *vid_ptr32; dword *vid_ptr32;

130
vmm.c
View File

@ -2,140 +2,20 @@
// vmm.c // vmm.c
// Author: Josh Holtrop // Author: Josh Holtrop
// Date: 09/30/03 // Date: 09/30/03
// Rewritten from scratch: 12/23/03
PageDirectory *vmm_PDBR = (PageDirectory *)0x104000;
dword vmm_first_virtual_address = 0;
void vmm_init() void vmm_init()
{ {
if (mm_totalmem % 4096) dword *pagetables = (dword *)0xC0104000; //this is the location of the page directory
vmm_first_virtual_address = mm_totalmem + (4096 - (mm_totalmem % 4096)); pagetables[0x3FF] = 0x104000|0x03; //the last page directory entry points to the page directory itself
else if (videoMode) //we are in a graphical mode
vmm_first_virtual_address = mm_totalmem; {
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) void *malloc(dword bytes)

15
vmm.h
View File

@ -2,26 +2,13 @@
// vmm.h // vmm.h
// Author: Josh Holtrop // Author: Josh Holtrop
// Date: 09/30/03 // 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 vmm_init();
void *malloc(dword bytes); void *malloc(dword bytes);
int free(void *ptr); 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();