Here's my kmain:
Code: Select all
void _kmain( void* mbd, unsigned int magic )
{
global_mbd_addr = mbd;
global_magic = magic;
// write your kernel here
kvideoinit();
koutstr("Video OK!\n",BLACK, DEFCOL);
koutstr("Initialising...\n",BLACK, DEFCOL);
koutstr("Setting up IDT...\n",BLACK, DEFCOL);
kidt_setup();
if((unsigned int)global_mbd_addr < 4096*1024) //if the mbd is in kernel memory
{
//translate the address
global_mbd = (struct mbd*)(KERNEL_MEMSTART + (unsigned char*)global_mbd_addr);
}
else
{
//if not, at some point we'll allocate a page to refer to it with
//but for now, we'll just give an error
kerror("Error: MBD not in kernel memory!\n");
while(1);
}
koutstr("Initialising keyboard...\n",BLACK, DEFCOL);
kkeyinit();
koutstr("Setting up kernel process...\n",BLACK, DEFCOL);
//set up the kernel process
systemprocess.page0 = KERNEL_MEMSTART>>12;
systemprocess.pages = 1024;
systemprocess.type = 0;
systemprocess.firstfree = (struct blockheader*)&_end;
systemprocess.firstfree->size = 4096*1024 - ((unsigned int)(&_end)-KERNEL_MEMSTART);
systemprocess.firstfree->next = 0;
systemprocess.firstfree->prev = 0;
systemprocess.firstfree->type = 0;
asm volatile("mov %%cr3, %0":"=a"(systemprocess.cr3));
systemprocess.nextproc = &systemprocess;
systemprocess.priority = 50;
systemprocess.count = systemprocess.priority;
systemprocess.waiting = 0;
systemprocess.next_msg = 0;
systemprocess.msg_queue_end = 0;
prevproc = currentproc = &systemprocess; //lets processes exit properly (without a previous process, there's a dead pointer passed about in the process linked list)
koutstr("Remapping PIC...\n",BLACK, DEFCOL);
kpicinit(0x20, 0x28);
inb(0x60); //(why does this need to be here?)
koutstr("Initialising memory management...\n",BLACK, DEFCOL);
kmeminit();
koutstr("Starting floppy daemon...\n",BLACK, DEFCOL);
kthread(&kfloppydaemon); //turns off floppy motor after a period of inaction
asm volatile("sti");
koutstr("Initialising terminal I/O...\n",BLACK, DEFCOL);
kioinit();
koutstr("Initialising timer...\n",BLACK, DEFCOL);
ktimerinit();
koutstr("Calibrating floppy drives...\n",BLACK, DEFCOL);
kfloppyinit();
ksleep(100);
kclearscreen();
koutstr("Welcome to Freya!\nOperating system of the gods!\n",BLACK, DEFCOL);
if(global_mbd->flags&(1<<11)) koutstr("Received video info!\n",BLACK,DEFCOL);
else koutstr("No video info!\n",BLACK,DEFCOL);
//bit of code here to test my floppy code
unsigned char *bootsect = kmalloc(512, 0);
kmainfloppyreadsinglesect(0, bootsect);
koutstr("Read boot sector.\n", BLACK, DEFCOL);
if(bootsect[510] == 0x55) koutstr("First floppy boot signature found.\n", BLACK, DEFCOL);
if(bootsect[511] == 0xAA) koutstr("Second floppy boot signature found.\n", BLACK, DEFCOL);
while(1) //loop forever - otherwise the computer will turn off
{
}
}
Code: Select all
#define PIC1 0x20 /* IO base address for master PIC */
#define PIC2 0xA0 /* IO base address for slave PIC */
#define PIC1_COMMAND PIC1
#define PIC1_DATA (PIC1+1)
#define PIC2_COMMAND PIC2
#define PIC2_DATA (PIC2+1)
#define PIC_EOI 0x20 /* End-of-interrupt command code */
#define ICW1_ICW4 0x01 /* ICW4 (not) needed */
#define ICW1_SINGLE 0x02 /* Single (cascade) mode */
#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */
#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */
#define ICW1_INIT 0x10 /* Initialization - required! */
#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */
#define ICW4_AUTO 0x02 /* Auto (normal) EOI */
#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */
#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
#define ICW4_SFNM 0x10 /* Special fully nested (not) */
#define PIC1_MASK 0xBC
#define PIC2_MASK 0xFF
... snip ...
void kpicinit(unsigned char offset1, unsigned char offset2)
{
outb(PIC1_COMMAND, ICW1_INIT+ICW1_ICW4); // starts the initialization sequence
io_wait();
outb(PIC2_COMMAND, ICW1_INIT+ICW1_ICW4);
io_wait();
outb(PIC1_DATA, offset1); // define the PIC vectors
io_wait();
outb(PIC2_DATA, offset2);
io_wait();
outb(PIC1_DATA, 4); // continue initialization sequence
io_wait();
outb(PIC2_DATA, 2);
io_wait();
outb(PIC1_DATA, ICW4_8086);
io_wait();
outb(PIC2_DATA, ICW4_8086);
io_wait();
outb(PIC1_DATA, PIC1_MASK); // set the masks
outb(PIC2_DATA, PIC2_MASK);
}
Code: Select all
contextswitch: ;;performs a context switch
;; first store the register values
pushad
;; now store the old stack pointers and load the new ones
mov eax, [currentproc]
mov ebx, [eax+32] ; ebx is now the next process
mov [eax+20], esp
mov [eax+16], ebp
mov esp, [ebx+20]
mov ebp, [ebx+16]
;; store the stack pointer in the TSS
mov edi, TSS
mov [edi+4], esp
;; store eax as the previous process
mov [prevproc], eax
;; reset the next process's counter and set it as the current process
mov eax, [ebx+36]
mov [ebx+40], eax
mov [currentproc], ebx
;; load the correct page directory
mov eax, [ebx+24]
mov cr3, eax
;; finally, set the data segment registers to the correct values
mov eax, [ebx+8]
or eax, eax
jz .kernelcode
mov ax, 0x28
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
popad
ret
.kernelcode:
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
popad
ret