Right now I’m working towards being able to:
- press keys on my keyboard
- having the OS not crash
- and have the key I pressed be echoed back
I just achieved step 2, and this has been kind of a saga, so here’s an explanation of the blood and tears involved. First up, some resources that really helped me out:
- The fantastic OSDev wiki.
- This tutorial on how to make a basic x86 kernel, especially the IDT page.
- This other Rust kernel, mostly for Rust coding style.
- Most of all: the OSDev wiki page “I Can’t Get Interrupts Working”. Read this three times every time you have a problem. For real.
So here’s how I did it. There were a lot of pitfalls. Notably absent are the hours I spent in the Rust IRC channel being confused about types.
How To Get Interrupts Working, Julia’s Way
- Create a Global Descriptor Table (GDT) and load it (source)
- Switch from Real Mode to Protected Mode.
This involves turning interrupts off (
- Create a Interrupt Descriptor Table (IDT) and load it.
- Put interrupt handlers into my table.
- Press keys. Nothing happens. Hours pass. Realize interrupts are turned off and I need to turn them on.
- Turn interrupts on (
- Press a key. The OS crashes. Continue experimenting in this vein for some time. Still crashing.
- Take the advice from “I Can’t Get Interrupts Working”
and trigger the interrupts manually (with
int 1) before turning interrupts back on and trying it for real. Get my interrupt descriptor table not broken. Sweet.
- Turn interrupts on (
- The OS AGAIN crashes every time i press a key. Read “I Can’t Get Interrupts Working” again. This is called “I’m receiving EXC9 instead of IRQ1 when striking a key?!” Feel on top of this.
- Remap the PIC so that interrupt
igets mapped to
i + 32, because of an Intel design bug. This basically looks like just typing in a bunch of random numbers, but it works.
- THE OS IS STILL CRASHING WHEN I PRESS A KEY. This continues for 2 days.
- Remember that now that I have remapped interrupt 1 to interrupt 33 and I need to update my IDT.
- Update my IDT.
- Press a key. My interrupt handler runs. Practically faint with joy.
- But it only runs the first time I press a key, not the second time. This is the section “I can only receive one IRQ”
As far as I can tell this is all totally normal and just how OS programming is. Or something. Hopefully by the end of the week I will get past “I can only receive one IRQ” and into “My interrupt handler is the bomb and I can totally write a keyboard driver now”.
Then I’m going to write a keyboard driver where in addition to doing normal keyboard driver things, it changes the screen colour every time I press a key. (Kate’s idea)
I’m seriously amazed that operating systems exist and are available for free.
Edit: Thanks for all the help everyone! I’ve solved “It only runs the first time I press a key” now and moved on to new problems :)