I am trying to write an operating system using osdev and others. Now I'm stuck in a keyboard interrupt handler. When I compile my OS and start only the kernel with qemu-system-i386 -kernel kernel/myos.kernel
, everything works fine, but when I put everything in the ISO and try to start it with qemu-system-i386 -cdrom myos.iso
, it loads, but when I press any button on the keyboard, it restarts. I think this is caused by some problems in the address of the interrupt handler in the IDT record.
Here:
-my-handler (gnu as syntax):
.globl keyboard_handler
.align 4
keyboard_handler:
pushal
cld
call keyboard_handler_main
popal
iret
-my main handler (c):
void keyboard_handler_main(void) {
unsigned char status;
char keycode;
write_port(0x20, 0x20);
status = read_port(KEYBOARD_STATUS_PORT);
if (status & 0x01) {
keycode = read_port(KEYBOARD_DATA_PORT);
if(keycode < 0)
return;
if(keycode == ENTER_KEY_CODE) {
printf("\n");
return;
}
printf("%c", keyboard_map[(unsigned char) keycode]);
}
}
-function, I use to download IDT (c):
void idt_init(void)
{
unsigned long idt_address;
unsigned long idt_ptr[2];
auto keyboard_address = (*keyboard_handler);
IDT[0x21].offset_lowerbits = keyboard_address & 0xffff;
IDT[0x21].selector = KERNEL_CODE_SEGMENT_OFFSET;
IDT[0x21].zero = 0;
IDT[0x21].type_attr = INTERRUPT_GATE;
IDT[0x21].offset_higherbits = (keyboard_address & 0xffff0000) >> 16;
write_port(0x20 , 0x11);
write_port(0xA0 , 0x11);
write_port(0x21 , 0x20);
write_port(0xA1 , 0x28);
write_port(0x21 , 0x00);
write_port(0xA1 , 0x00);
write_port(0x21 , 0x01);
write_port(0xA1 , 0x01);
write_port(0x21 , 0xff);
write_port(0xA1 , 0xff);
idt_address = (unsigned long)IDT ;
idt_ptr[0] = (sizeof (struct IDT_entry) * IDT_SIZE) + ((idt_address & 0xffff) << 16);
idt_ptr[1] = idt_address >> 16 ;
load_idt(idt_ptr);
printf("%s\n", "loadd");
}
The files are organized like this: http://wiki.osdev.org/Meaty_Skeleton , but I have another bootloader.
, - , .
, 13 , , .