Interrupts!
parent
236f28e1c7
commit
619ce7bda1
|
@ -0,0 +1,44 @@
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
#ifndef __ACPI_H__
|
||||||
|
#define __ACPI_H__
|
||||||
|
|
||||||
|
#define ACPI_VERSION_UNK 0
|
||||||
|
#define ACPI_VERSION_10 1
|
||||||
|
#define ACPI_VERSION_20 2
|
||||||
|
|
||||||
|
#define ACPI_10_RSDP_SIZE 20
|
||||||
|
#define ACPI_20_RSDP_SIZE 16
|
||||||
|
|
||||||
|
struct S_ACPI_RSDP {
|
||||||
|
s8 Magic[8];
|
||||||
|
u8 Checksum;
|
||||||
|
s8 OEMID[6];
|
||||||
|
u8 Revision;
|
||||||
|
u32 RSDTAddress;
|
||||||
|
|
||||||
|
// Additional ACPI 2.0 fields
|
||||||
|
u32 Length;
|
||||||
|
u32 RSDTAddressExLow;
|
||||||
|
u32 RSDTAddressExHigh;
|
||||||
|
u8 ChecksumEx;
|
||||||
|
u8 Reserved[3];
|
||||||
|
} __attribute__((packed));
|
||||||
|
typedef struct S_ACPI_RSDP T_ACPI_RSDP;
|
||||||
|
|
||||||
|
struct S_ACPI_SDT_HEADER {
|
||||||
|
s8 Signature[4];
|
||||||
|
u32 Length;
|
||||||
|
u8 Revision;
|
||||||
|
u8 Checksum;
|
||||||
|
s8 OEMID[6];
|
||||||
|
s8 OEMTableID[8];
|
||||||
|
u32 OEMRevision;
|
||||||
|
u32 CreatorID;
|
||||||
|
u32 CreatorRevision;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
typedef struct S_ACPI_SDT_HEADER T_ACPI_SDT_HEADER;
|
||||||
|
|
||||||
|
u32 acpi_find_rsdp(void);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,52 @@
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
struct S_IDT_PTR {
|
||||||
|
u16 Limit;
|
||||||
|
u32 Base;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
typedef struct S_IDT_PTR T_IDT_PTR;
|
||||||
|
|
||||||
|
struct S_IDT_ENTRY {
|
||||||
|
u16 OffsetLow;
|
||||||
|
u16 Selector;
|
||||||
|
u8 Zero;
|
||||||
|
u8 Type;
|
||||||
|
u16 OffsetHigh;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
typedef struct S_IDT_ENTRY T_IDT_ENTRY;
|
||||||
|
|
||||||
|
enum E_INTERRUPTS_RING {
|
||||||
|
E_INTERRUPTS_RING0 = 0,
|
||||||
|
E_INTERRUPTS_RING1,
|
||||||
|
E_INTERRUPTS_RING2,
|
||||||
|
E_INTERRUPTS_RING3
|
||||||
|
};
|
||||||
|
typedef enum E_INTERRUPTS_RING T_INTERRUPTS_RING;
|
||||||
|
|
||||||
|
enum E_INTERRUPTS_CHIP {
|
||||||
|
E_INTERRUPTS_CHIP_UNK,
|
||||||
|
E_INTERRUPTS_CHIP_PIC,
|
||||||
|
E_INTERRUPTS_CHIP_APIC
|
||||||
|
};
|
||||||
|
typedef enum E_INTERRUPTS_CHIP T_INTERRUPTS_CHIP;
|
||||||
|
|
||||||
|
// This is a structure that allows easy access to a 12-byte ASM stub which
|
||||||
|
// calls a stdcall handler. Not the best way and not the shortest stub,
|
||||||
|
// but hey, it works.
|
||||||
|
struct S_ISR_STUB {
|
||||||
|
u16 Code1;
|
||||||
|
u8 Code2;
|
||||||
|
u32 Handler;
|
||||||
|
u32 Code3;
|
||||||
|
u8 Code4;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
typedef struct S_ISR_STUB T_ISR_STUB;
|
||||||
|
|
||||||
|
u8 interrupts_init_idt(void);
|
||||||
|
void interrupts_setup_irq(u8 IRQ, void *Handler);
|
||||||
|
void interrupts_setup_isr(u8 Interrupt, void *Handler, T_INTERRUPTS_RING Ring);
|
||||||
|
void interrupts_init_simple(void);
|
||||||
|
void interrupts_interrupt_finish(u8 IRQ);
|
||||||
|
void interrupts_lidt(void);
|
||||||
|
void interrupts_dump_idt_entry(u8 Interrupt);
|
||||||
|
void interrupts_dump_idt_ptr(void);
|
|
@ -4,6 +4,8 @@
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
void koutb(u16 Port, u8 Data);
|
void koutb(u16 Port, u8 Data);
|
||||||
|
u8 kinb(u16 Port);
|
||||||
|
void kio_wait(void);
|
||||||
u32 kstrlen(s8 *szString);
|
u32 kstrlen(s8 *szString);
|
||||||
void kmove_cursor(u8 X, u8 Y);
|
void kmove_cursor(u8 X, u8 Y);
|
||||||
void kputs(s8 *szString);
|
void kputs(s8 *szString);
|
||||||
|
@ -14,5 +16,6 @@ void kputi(s32 Number);
|
||||||
void kprintf(s8 *Format, ...);
|
void kprintf(s8 *Format, ...);
|
||||||
void kdump(u8 *bData, u32 Length);
|
void kdump(u8 *bData, u32 Length);
|
||||||
void kprint_hex(u32 Number);
|
void kprint_hex(u32 Number);
|
||||||
|
s32 kmemcmp(u8 *MemA, u8 *MemB, u32 Length);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef __PAGING_H__
|
#ifndef __PAGING_H__
|
||||||
#define __PAGING_H__
|
#define __PAGING_H__
|
||||||
|
|
||||||
void paging_init_simple(void);
|
#include "types.h"
|
||||||
|
|
||||||
|
void paging_init_simple(void);
|
||||||
|
u8 paging_get_physical(u32 Virtual, u32 *Physical);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef __PIC_H__
|
||||||
|
#define __PIC_H__
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
#define PIC_1_ADDR 0x20
|
||||||
|
#define PIC_1_DATA 0x21
|
||||||
|
#define PIC_1_START 0xF0
|
||||||
|
|
||||||
|
#define PIC_2_ADDR 0xA0
|
||||||
|
#define PIC_2_DATA 0xA1
|
||||||
|
#define PIC_2_START 0xF8
|
||||||
|
|
||||||
|
#define PIC_IRQ_START 0xF0
|
||||||
|
|
||||||
|
void pic_init(u8 *OldMask1, u8 *OldMask2);
|
||||||
|
void pic_eoi(u8 IRQ);
|
||||||
|
void pic_unmask_irq(u8 IRQ);
|
||||||
|
|
||||||
|
#endif
|
|
@ -45,7 +45,6 @@ higherhalf:
|
||||||
mov esp, kstack + STACKSIZE
|
mov esp, kstack + STACKSIZE
|
||||||
|
|
||||||
push eax
|
push eax
|
||||||
push ebx
|
|
||||||
|
|
||||||
call kmain
|
call kmain
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
#include "Tier0/acpi.h"
|
||||||
|
#include "Tier0/kstdio.h"
|
||||||
|
|
||||||
|
u8 g_acpi_version = 0;
|
||||||
|
u32 g_acpi_rsdt_address = 0;
|
||||||
|
|
||||||
|
u32 acpi_find_rsdp(void)
|
||||||
|
{
|
||||||
|
s8 *szMagic = "RSD PTR ";
|
||||||
|
|
||||||
|
// Try to find the pointer... apparently it's 16byte-aligned...
|
||||||
|
|
||||||
|
kprintf("[i] Looking for the RSDP...\n");
|
||||||
|
u32 Address = 0;
|
||||||
|
for (u32 Search = 0x000E0000; Search <= 0x000FFFFF; Search += 4)
|
||||||
|
{
|
||||||
|
if (kmemcmp((u8 *)Search, (u8 *)szMagic, 8) == 0)
|
||||||
|
{
|
||||||
|
Address = Search;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Address == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
T_ACPI_RSDP *RSDP = (T_ACPI_RSDP *)Address;
|
||||||
|
|
||||||
|
u8 ChecksumVerify = 0;
|
||||||
|
for (u8 i = 0; i < ACPI_10_RSDP_SIZE; i++)
|
||||||
|
ChecksumVerify += ((u8*)Address)[i];
|
||||||
|
|
||||||
|
if (ChecksumVerify != 0)
|
||||||
|
{
|
||||||
|
kprintf("[e] ACPI checksum failed. Memory failure? Weird PC? We may never " \
|
||||||
|
"know ...\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RSDP->Revision == 1)
|
||||||
|
{
|
||||||
|
// ACPI 2.0...
|
||||||
|
ChecksumVerify = 0;
|
||||||
|
for (u8 i = ACPI_10_RSDP_SIZE; i < ACPI_20_RSDP_SIZE; i++)
|
||||||
|
ChecksumVerify += ((u8*)Address)[i];
|
||||||
|
|
||||||
|
if (ChecksumVerify != 0)
|
||||||
|
{
|
||||||
|
kprintf("[e] ACPI 2.0 checksum failed. Yet 1.0 succeeded? WTF.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_acpi_version = RSDP->Revision + 1;
|
||||||
|
|
||||||
|
kprintf("[i] Detected ACPI version %i.0.\n", RSDP->Revision + 1);
|
||||||
|
if (*RSDP->OEMID != 0)
|
||||||
|
kprintf("[i] OEMID %s.\n", RSDP->OEMID);
|
||||||
|
|
||||||
|
if (g_acpi_version == ACPI_VERSION_10)
|
||||||
|
g_acpi_rsdt_address = Address;
|
||||||
|
else
|
||||||
|
g_acpi_rsdt_address = RSDP->RSDTAddressExLow;
|
||||||
|
|
||||||
|
return Address;
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
// Basically stuff that is needed to go into C++ Land
|
|
@ -0,0 +1,9 @@
|
||||||
|
BITS 32
|
||||||
|
section .text
|
||||||
|
|
||||||
|
global interrupts_lidt
|
||||||
|
extern g_idt_ptr
|
||||||
|
|
||||||
|
interrupts_lidt:
|
||||||
|
lidt [g_idt_ptr]
|
||||||
|
ret
|
|
@ -0,0 +1,139 @@
|
||||||
|
#include "Tier0/interrupts.h"
|
||||||
|
#include "Tier0/paging.h"
|
||||||
|
#include "Tier0/kstdio.h"
|
||||||
|
#include "Tier0/pic.h"
|
||||||
|
|
||||||
|
T_IDT_PTR g_idt_ptr;
|
||||||
|
T_IDT_ENTRY g_idt_entries[256];
|
||||||
|
T_ISR_STUB g_isr_stubs[256];
|
||||||
|
|
||||||
|
T_INTERRUPTS_CHIP g_interrupts_chip = E_INTERRUPTS_CHIP_UNK;
|
||||||
|
|
||||||
|
void interrupts_set_chip(T_INTERRUPTS_CHIP Chip)
|
||||||
|
{
|
||||||
|
g_interrupts_chip = Chip;
|
||||||
|
|
||||||
|
if (Chip == E_INTERRUPTS_CHIP_UNK)
|
||||||
|
kprintf("[i] Interrupts: Turning off.\n");
|
||||||
|
else if (Chip == E_INTERRUPTS_CHIP_PIC)
|
||||||
|
kprintf("[i] Interrupts: Switching to 8259 based interrupts.\n");
|
||||||
|
else if (Chip == E_INTERRUPTS_CHIP_APIC)
|
||||||
|
kprintf("[i] Interrupts: Switching to intel I/O APIC based "
|
||||||
|
"interrupts.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 interrupts_init_idt(void)
|
||||||
|
{
|
||||||
|
g_idt_ptr.Limit = 256 * 8;
|
||||||
|
|
||||||
|
u32 Physical = 0;
|
||||||
|
u8 Result = paging_get_physical((u32)g_idt_entries, &Physical);
|
||||||
|
if (!Result)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
kprintf("[i] Setting up IDT at 0x%x (0x%x Virtual).\n", Physical, g_idt_entries);
|
||||||
|
|
||||||
|
g_idt_ptr.Base = Physical;
|
||||||
|
|
||||||
|
// Null those entries!
|
||||||
|
for (u16 i = 0; i < 256; i++)
|
||||||
|
{
|
||||||
|
// Maybe I should access the struct's members...
|
||||||
|
// Or i can just cast that to to u32's and null them.
|
||||||
|
// This will set the Present flag to 0 either way
|
||||||
|
*((u32 *)(&g_idt_entries[i])) = 0;
|
||||||
|
*(((u32 *)(&g_idt_entries[i]) + 1)) = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This creates a 12-byte ASM stub for a handler
|
||||||
|
void interrupts_create_stub(T_ISR_STUB *Destination, u32 Address)
|
||||||
|
{
|
||||||
|
// The ASM code is as follows:
|
||||||
|
// cli
|
||||||
|
// pushad
|
||||||
|
// mov eax, Handler
|
||||||
|
// call eax
|
||||||
|
// popad
|
||||||
|
// sti
|
||||||
|
// iret
|
||||||
|
Destination->Code1 = 0x60FA; // pishad, cli
|
||||||
|
Destination->Code2 = 0xB8; // mov eax,
|
||||||
|
Destination->Handler = Address; // Address
|
||||||
|
Destination->Code3 = 0xFB61D0FF; // sti, popad, call eax
|
||||||
|
Destination->Code4 = 0xCF; // iret
|
||||||
|
}
|
||||||
|
|
||||||
|
void interrupts_setup_irq(u8 IRQ, void *Handler)
|
||||||
|
{
|
||||||
|
if (g_interrupts_chip != E_INTERRUPTS_CHIP_PIC)
|
||||||
|
{
|
||||||
|
kprintf("[e] Sorry, but I only do PIC-based interrupts for now :(.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 Interrupt = IRQ + PIC_IRQ_START;
|
||||||
|
interrupts_setup_isr(Interrupt, Handler, E_INTERRUPTS_RING0);
|
||||||
|
|
||||||
|
// We also need to set the IRQ mask
|
||||||
|
pic_unmask_irq(IRQ);
|
||||||
|
}
|
||||||
|
|
||||||
|
void interrupts_dump_idt_ptr(void)
|
||||||
|
{
|
||||||
|
kprintf("[i] IDT Pointer structure:\n");
|
||||||
|
kprintf(" Base: 0x%x.\n", g_idt_ptr.Base);
|
||||||
|
kprintf(" Limit: 0x%x.\n", g_idt_ptr.Limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
void interrupts_dump_idt_entry(u8 Interrupt)
|
||||||
|
{
|
||||||
|
u32 *dwEntry = (u32 *)&g_idt_entries[Interrupt];
|
||||||
|
kprintf("[i] IDT Entry for interrupt %x:\n", Interrupt);
|
||||||
|
kprintf(" DW Low : 0x%x.\n", *dwEntry);
|
||||||
|
kprintf(" DW High: 0x%x.\n", *(dwEntry + 1));
|
||||||
|
|
||||||
|
T_IDT_ENTRY Entry = g_idt_entries[Interrupt];
|
||||||
|
kprintf(" Offset: 0x%x.\n", (Entry.OffsetHigh << 16) + Entry.OffsetLow);
|
||||||
|
kprintf(" Selector: %u.\n", Entry.Selector);
|
||||||
|
kprintf(" Zero: %u.\n", Entry.Zero);
|
||||||
|
kprintf(" P: %u.\n", (Entry.Type >> 7) & 0b1);
|
||||||
|
kprintf(" DPL: %u.\n", (Entry.Type >> 5) & 0b11);
|
||||||
|
kprintf(" S: %u.\n", (Entry.Type >> 4) & 0b1);
|
||||||
|
kprintf(" Gate type: %u.\n", Entry.Type & 0b1111);
|
||||||
|
}
|
||||||
|
|
||||||
|
void interrupts_setup_isr(u8 Interrupt, void *Handler, T_INTERRUPTS_RING Ring)
|
||||||
|
{
|
||||||
|
interrupts_create_stub(&g_isr_stubs[Interrupt], (u32)Handler);
|
||||||
|
|
||||||
|
u32 ASMHandler = (u32)&g_isr_stubs[Interrupt];
|
||||||
|
g_idt_entries[Interrupt].OffsetLow = ASMHandler & 0xFFFF;
|
||||||
|
g_idt_entries[Interrupt].OffsetHigh = (ASMHandler >> 16) & 0xFFFF;
|
||||||
|
g_idt_entries[Interrupt].Selector = 0x08; // Second segment, code.
|
||||||
|
g_idt_entries[Interrupt].Zero = 0;
|
||||||
|
|
||||||
|
u8 Type = 0;
|
||||||
|
Type |= (1 << 7); // Present = 1
|
||||||
|
Type |= (Ring << 5); // DPL = Ring
|
||||||
|
Type |= (0 << 4); // Storage = 0
|
||||||
|
Type |= 0xE; // Type = 0xE (32-bit interrupt gate)
|
||||||
|
g_idt_entries[Interrupt].Type = Type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void interrupts_init_simple(void)
|
||||||
|
{
|
||||||
|
interrupts_set_chip(E_INTERRUPTS_CHIP_PIC);
|
||||||
|
interrupts_init_idt();
|
||||||
|
interrupts_lidt();
|
||||||
|
|
||||||
|
pic_init(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void interrupts_interrupt_finish(u8 IRQ)
|
||||||
|
{
|
||||||
|
if (g_interrupts_chip == E_INTERRUPTS_CHIP_PIC)
|
||||||
|
pic_eoi(IRQ);
|
||||||
|
}
|
|
@ -2,15 +2,28 @@
|
||||||
#include "Tier0/kstdio.h"
|
#include "Tier0/kstdio.h"
|
||||||
#include "Tier0/gdt.h"
|
#include "Tier0/gdt.h"
|
||||||
#include "Tier0/paging.h"
|
#include "Tier0/paging.h"
|
||||||
|
#include "Tier0/acpi.h"
|
||||||
|
#include "Tier0/interrupts.h"
|
||||||
|
|
||||||
|
|
||||||
|
// Just to see whether this stuff actually works
|
||||||
|
void sample_interrupt_0x2A(void)
|
||||||
|
{
|
||||||
|
kprintf("[i] Hello from ISR for interrupt 0x2A!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Real kernel entry point, called from _start.asm
|
// Real kernel entry point, called from _start.asm
|
||||||
void kmain(void *mbd, u32 magic)
|
void kmain(u32 Magic)
|
||||||
{
|
{
|
||||||
kclear();
|
kclear();
|
||||||
|
kprintf(" _ \n"
|
||||||
|
" ___ _ _ ___ _ _ _____| |_ ___ ___ \n"
|
||||||
|
" | _| | | _| | | | . | -_| _|\n"
|
||||||
|
" |___|___|___|___|_|_|_|___|___|_| \n\n");
|
||||||
kprintf("[i] Welcome to Cucumber!\n\n");
|
kprintf("[i] Welcome to Cucumber!\n\n");
|
||||||
kprintf("[i] Magic from bootloader: 0x%x.\n", magic);
|
|
||||||
|
|
||||||
if (magic != 0x2BADB002)
|
if (Magic != 0x2BADB002)
|
||||||
{
|
{
|
||||||
kprintf("[e] Fatal! Boot via incompatible bootloader.\n");
|
kprintf("[e] Fatal! Boot via incompatible bootloader.\n");
|
||||||
return;
|
return;
|
||||||
|
@ -18,5 +31,28 @@ void kmain(void *mbd, u32 magic)
|
||||||
|
|
||||||
paging_init_simple();
|
paging_init_simple();
|
||||||
gdt_create_flat();
|
gdt_create_flat();
|
||||||
}
|
|
||||||
|
|
||||||
|
kprintf("[i] Paging and GDT set up correctly.\n");
|
||||||
|
|
||||||
|
u32 RSDPAddress = acpi_find_rsdp();
|
||||||
|
if (RSDPAddress == 0)
|
||||||
|
{
|
||||||
|
kprintf("[e] Fatal! ACPI not found.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
kprintf("[i] RSDP found at 0x%X.\n", RSDPAddress);
|
||||||
|
|
||||||
|
u32 PhysicalTest;
|
||||||
|
u8 Result = paging_get_physical(0xC00B8000, &PhysicalTest);
|
||||||
|
if (!Result || PhysicalTest != 0xB8000)
|
||||||
|
{
|
||||||
|
kprintf("[e] Paging self-test failed!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
interrupts_init_simple();
|
||||||
|
interrupts_setup_isr(0x2A, sample_interrupt_0x2A, E_INTERRUPTS_RING0);
|
||||||
|
|
||||||
|
__asm__ volatile("int $0x2a");
|
||||||
|
}
|
||||||
|
|
|
@ -14,7 +14,19 @@ u8 g_kstdio_cur_x = 0, g_kstdio_cur_y = 0;
|
||||||
|
|
||||||
void koutb(u16 Port, u8 Data)
|
void koutb(u16 Port, u8 Data)
|
||||||
{
|
{
|
||||||
__asm__ __volatile__ ("outb %1, %0" : : "dN" (Port), "a" (Data));
|
__asm__ volatile("outb %1, %0" :: "dN" (Port), "a" (Data));
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 kinb(u16 Port)
|
||||||
|
{
|
||||||
|
u8 Return;
|
||||||
|
__asm__ volatile("inb %1, %0" :"=a"(Return):"Nd"(Port));
|
||||||
|
return Return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void kio_wait(void)
|
||||||
|
{
|
||||||
|
__asm__ volatile("jmp 1f;1:jmp 1f;1:");
|
||||||
}
|
}
|
||||||
|
|
||||||
void kputi(s32 Number)
|
void kputi(s32 Number)
|
||||||
|
@ -216,3 +228,17 @@ void kclear(void)
|
||||||
}
|
}
|
||||||
kmove_cursor(0, 0);
|
kmove_cursor(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s32 kmemcmp(u8 *MemA, u8 *MemB, u32 Length)
|
||||||
|
{
|
||||||
|
u32 Result = -1;
|
||||||
|
for (u32 Search = 0; Search < Length; Search++)
|
||||||
|
{
|
||||||
|
if (MemA[Search] != MemB[Search])
|
||||||
|
{
|
||||||
|
Result = Search;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
|
@ -5,30 +5,40 @@
|
||||||
u32 g_kernel_page_directory[1024] __attribute__ ((aligned (4096)));
|
u32 g_kernel_page_directory[1024] __attribute__ ((aligned (4096)));
|
||||||
u32 g_low_page_table[1024] __attribute__ ((aligned (4096)));
|
u32 g_low_page_table[1024] __attribute__ ((aligned (4096)));
|
||||||
|
|
||||||
/*u8 paging_get_physical(u32 Virtual, u32 *Physical)
|
u8 paging_get_physical(u32 Virtual, u32 *Physical)
|
||||||
{
|
{
|
||||||
u16 Index =
|
u16 DirectoryIndex = (Virtual >> 22) & 0x3FF;
|
||||||
|
u32 DirectoryEntry = g_kernel_page_directory[DirectoryIndex];
|
||||||
u32 DirectoryEntry = g_kernel_page_directory[Index];
|
|
||||||
|
|
||||||
u8 TablePresent = DirectoryEntry & 0b1;
|
u8 TablePresent = DirectoryEntry & 0b1;
|
||||||
|
|
||||||
if (!TablePresent)
|
if (!TablePresent)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
u32 TableAddress = 0;
|
u32 TableAddress = 0;
|
||||||
TableAddress |= (DirectoryEntry & 0xFFFFF000);
|
TableAddress |= (DirectoryEntry & 0xFFFFF000);
|
||||||
|
u32 *Table = (u32 *)TableAddress;
|
||||||
|
|
||||||
u32 Table = *((u32 *) &TableAddress);
|
|
||||||
|
|
||||||
u8 PagePresent = DirectoryEntry &
|
u16 TableIndex = (Virtual >> 12) & 0x3FF;
|
||||||
}*/
|
u32 TableEntry = Table[TableIndex];
|
||||||
|
|
||||||
|
u8 PagePresent = TableEntry &0b1;
|
||||||
|
if (!PagePresent)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
*Physical = 0;
|
||||||
|
*Physical |= (TableEntry & 0xFFFFF000);
|
||||||
|
*Physical |= (Virtual & 0xFFF);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
void paging_dump_directory(void)
|
void paging_dump_directory(void)
|
||||||
{
|
{
|
||||||
for (u32 i = 0; i < 10; i++)
|
for (u32 i = 0; i < 10; i++)
|
||||||
{
|
{
|
||||||
kprintf("[i] Virtual 0x%X - 0x%X, Entry 0x%X.\n", i * 4096 * 1024, (i + 1) * 4096 * 1024, g_kernel_page_directory[i] & 0xFFFFF000);
|
kprintf("[i] Virtual 0x%X - 0x%X, Entry 0x%X.\n", i * 4096 * 1024, \
|
||||||
|
(i + 1) * 4096 * 1024, g_kernel_page_directory[i] & 0xFFFFF000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,15 +53,14 @@ void paging_init_simple(void)
|
||||||
g_kernel_page_directory[i] = 0;
|
g_kernel_page_directory[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
kprintf("[i] Page Directory Physical: 0x%X, Virtual: 0x%X.\n", RealKernelPageDir, g_kernel_page_directory);
|
kprintf("[i] Page Directory Physical: 0x%X, Virtual: 0x%X.\n", \
|
||||||
kprintf("[i] Low Page Table Physical: 0x%X, Virtual: 0x%X.\n", RealLowPageTable, g_low_page_table);
|
RealKernelPageDir, g_kernel_page_directory);
|
||||||
|
kprintf("[i] Low Page Table Physical: 0x%X, Virtual: 0x%X.\n", \
|
||||||
|
RealLowPageTable, g_low_page_table);
|
||||||
|
|
||||||
g_kernel_page_directory[0] = (u32)RealLowPageTable | 0x03;
|
g_kernel_page_directory[0] = (u32)RealLowPageTable | 0x03;
|
||||||
g_kernel_page_directory[768] = (u32)RealLowPageTable | 0x03;
|
g_kernel_page_directory[768] = (u32)RealLowPageTable | 0x03;
|
||||||
|
|
||||||
paging_dump_directory();
|
|
||||||
|
|
||||||
|
|
||||||
__asm volatile ( "mov %0, %%eax\n"
|
__asm volatile ( "mov %0, %%eax\n"
|
||||||
"mov %%eax, %%cr3\n"
|
"mov %%eax, %%cr3\n"
|
||||||
"mov %%cr0, %%eax\n"
|
"mov %%cr0, %%eax\n"
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
// 8259 Programmable interrupt controller routines...
|
||||||
|
// The usual computer will switch to IOAPIC later on, once ACPI is fully
|
||||||
|
// initialized and the driver/module system is active.
|
||||||
|
|
||||||
|
// I could probably try to do without interrupts until I get in C++-land but
|
||||||
|
// you never know - also, paging without interrupts is pointless, especiallly
|
||||||
|
// if I want a good heap implementation, which is more-or-less indispensable
|
||||||
|
// if I want to ever reach Tier1 in a sane way.
|
||||||
|
|
||||||
|
// tl;dr - This code isn't going to be running all the time
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
#include "Tier0/kstdio.h"
|
||||||
|
#include "Tier0/pic.h"
|
||||||
|
|
||||||
|
#define PIC_COMMAND_EOI 0x20
|
||||||
|
|
||||||
|
// Initialisation "words".
|
||||||
|
#define PIC_ICW1_INIT 0x10
|
||||||
|
#define PIC_ICW1_ICW4 0x01
|
||||||
|
#define PIC_ICW4_8086 0x01
|
||||||
|
|
||||||
|
void pic_init(u8 *OldMask1, u8 *OldMask2)
|
||||||
|
{
|
||||||
|
if (OldMask1 != 0)
|
||||||
|
*OldMask1 = kinb(PIC_1_DATA);
|
||||||
|
|
||||||
|
if (OldMask2 != 0)
|
||||||
|
*OldMask2 = kinb(PIC_2_DATA);
|
||||||
|
|
||||||
|
koutb(PIC_1_ADDR, PIC_ICW1_INIT | PIC_ICW1_ICW4);
|
||||||
|
kio_wait();
|
||||||
|
|
||||||
|
koutb(PIC_2_ADDR, PIC_ICW1_INIT | PIC_ICW1_ICW4);
|
||||||
|
kio_wait();
|
||||||
|
|
||||||
|
// ICW2
|
||||||
|
koutb(PIC_1_DATA, PIC_1_START);
|
||||||
|
kio_wait();
|
||||||
|
|
||||||
|
koutb(PIC_2_DATA, PIC_2_START);
|
||||||
|
kio_wait();
|
||||||
|
|
||||||
|
// ICW3
|
||||||
|
koutb(PIC_1_DATA, 4);
|
||||||
|
kio_wait();
|
||||||
|
|
||||||
|
koutb(PIC_2_DATA, 2);
|
||||||
|
kio_wait();
|
||||||
|
|
||||||
|
// ICW4
|
||||||
|
koutb(PIC_1_DATA, PIC_ICW4_8086);
|
||||||
|
kio_wait();
|
||||||
|
|
||||||
|
koutb(PIC_2_DATA, PIC_ICW4_8086);
|
||||||
|
kio_wait();
|
||||||
|
|
||||||
|
//We don't support ANYTHING
|
||||||
|
koutb(PIC_1_DATA, 0xFF);
|
||||||
|
koutb(PIC_2_DATA, 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pic_eoi(u8 IRQ)
|
||||||
|
{
|
||||||
|
if (IRQ > 7)
|
||||||
|
koutb(PIC_2_ADDR, PIC_COMMAND_EOI);
|
||||||
|
|
||||||
|
koutb(PIC_1_ADDR, PIC_COMMAND_EOI);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pic_unmask_irq(u8 IRQ)
|
||||||
|
{
|
||||||
|
if (IRQ > 7)
|
||||||
|
{
|
||||||
|
u8 Bit = 0;
|
||||||
|
Bit |= 1 << (IRQ - 8);
|
||||||
|
|
||||||
|
u8 CurrentMask = kinb(PIC_2_DATA);
|
||||||
|
u8 NewMask = ~((~CurrentMask) | Bit);
|
||||||
|
|
||||||
|
koutb(PIC_2_DATA, NewMask);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u8 Bit = 0;
|
||||||
|
Bit |= 1 << (IRQ);
|
||||||
|
|
||||||
|
u8 CurrentMask = kinb(PIC_1_DATA);
|
||||||
|
u8 NewMask = ~((~CurrentMask) | Bit);
|
||||||
|
|
||||||
|
koutb(PIC_1_DATA, NewMask);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue