mbr_asm/core/idt.c

69 lines
1.7 KiB
C

#include "idt.h"
static struct idtEntry idt[IDT_NUM];
int idtSetup()
{
struct idtRegister idtr;
for (int i = 0; i < IDT_NUM; i++) {
struct idtEntry *idte = idt + i;
/* Setup an empty IDTE interrupt gate, see figure 5-2 in Intel
x86 doc, vol 3 */
idte->seg_sel = BUILD_SEGMENT_SELECTOR(RING_0, 0, SEGMENT_IDX_CODE);
idte->reserved = 0;
idte->flags = 0;
idte->type = 0x6; /* Interrupt gate (110b) */
idte->op_size = 1; /* 32bits instructions */
/* Disabled it for now */
idte->zero = 0;
idte->offset_low = 0;
idte->offset_high = 0;
idte->dpl = 0;
idte->present = 0;
}
/*
* Setup the IDT register, see Intel x86 doc vol 3, section 5.8.
*/
/* Address of the IDT */
idtr.base_addr = (uint32_t)idt;
/* The limit is the maximum offset in bytes from the base address of
the IDT */
idtr.limit = sizeof(idt) - 1;
/* Commit the IDT into the CPU */
asm volatile("lidt %0\n" ::"m"(idtr) : "memory");
return 0;
}
int idt_set_handler(int index, unsigned int addr, int priviledge)
{
struct idtEntry *idte;
if (index < 0 || index >= IDT_NUM)
return -1;
if ((priviledge < 0) || priviledge > 3)
return -1;
idte = idt + index;
if (addr != (unsigned int)NULL) {
idte->offset_low = addr & 0xffff;
idte->offset_high = (addr >> 16) & 0xffff;
idte->dpl = priviledge;
idte->present = 1;
} else {
idte->offset_low = 0;
idte->offset_high = 0;
idte->dpl = 0;
idte->present = 0;
}
return 0;
}