about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2020-12-23 10:39:54 -0800
committerKartik Agaram <vc@akkartik.com>2020-12-23 10:39:54 -0800
commit286ccc40e0c0ec2f897cd93a730ea8bacc84cf3e (patch)
treeefc200905faf736d3d5e61c46c6259215e136bed
parent2ff765b6586d6d09ca27e10a17c09796624e769d (diff)
downloadmu-286ccc40e0c0ec2f897cd93a730ea8bacc84cf3e.tar.gz
7388 - snapshot initializing interrupt table
I'm now back at the state of commit 7382 (including 7376). The existing
print to screen surprisingly seems to work without reset-looping, but when
I step through I notice that the lidt isn't doing what I expect.

Desired: at address 0x7cce, the processor executes:
  0f 01 1e 00 7f  # lidt ds:*idt_descriptor

Observed: at address 0x7cce, the processor executes:
  0f 01 1e        # lidt ds:*esi
As a result the next instruction is:
  00 7f fb

So the `fb` isn't interpreted to enable interrupts. So the problem of commit
7376 is latent.

Past this point the instruction stream is lined up again, and everything
occurs as it should. Purely by chance.

I fully expect all hell to break loose again, like it did in commit 7376,
once I debug the lidt encoding. There's still something I don't understand
about enabling interrupts. Perhaps I need to fill in more entries in the
table.
-rw-r--r--apps/boot.hex93
1 files changed, 69 insertions, 24 deletions
diff --git a/apps/boot.hex b/apps/boot.hex
index 0bf0874f..dad4a098 100644
--- a/apps/boot.hex
+++ b/apps/boot.hex
@@ -1,7 +1,8 @@
 # Bootable image that:
 #   - loads more sectors past the first boot sector (using BIOS primitives)
 #   - switches to 32-bit mode (giving up access to BIOS primitives)
-#   - as an example program, prints a letter from the second sector to the top-left of the screen (by writing to memory-mapped VGA memory)
+#   - sets up a handler for keyboard events
+#   - as an example program, prints alphabets to the top-left position on screen (by writing to memory-mapped VGA memory) as they're typed
 #
 # If the initial load fails, it prints 'D' to the top-left of the screen and
 # halts.
@@ -32,7 +33,8 @@
 #   to the address range [0x7c00, 0x7e00)
 
 # offset 00 (address 0x7c00):
-  fa  # cli  # TODO: don't forget to reenable interrupts in a real program
+  # disable interrupts for this initialization
+  fa  # cli
 
   # initialize segment registers
   # this isn't always needed, but is considered safe not to assume
@@ -46,7 +48,7 @@
   # We don't read or write the stack before we get to 32-bit mode. No function
   # calls, so we don't need to initialize the stack.
 
-# 0d:
+# 0e:
   # load more sectors from disk
   b4 02  # ah <- 2  # read sectors from disk
   # dl comes conveniently initialized at boot time with the index of the device being booted
@@ -166,11 +168,18 @@ e9 fb ff  # loop forever
   8e c0  # es <- ax
   8e e0  # fs <- ax
   8e e8  # gs <- ax
-  e9 2d 00 00 00  # jump to 0x7d00
+
+  # load interrupt handlers
+  0f 01 1e  # lidt 00/mod/indirect 011/subop 110/rm32/TODO
+    00 7f  # *idt_descriptor
+
+  # initialization is done; enable interrupts
+  fb
+  e9 27 00 00 00  # jump to 0x7d00
 
 # padding
-# d3:
-         00 00 00 00 00 00 00 00 00 00 00 00 00
+# d9:
+                           00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 
@@ -194,6 +203,9 @@ e9 fb ff ff ff  # loop forever
 # padding
 # 111:
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+# 120:
+
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
@@ -215,24 +227,57 @@ e9 fb ff ff ff  # loop forever
 ## sector 2
 # not loaded on boot; loaded by load_disk
 
-# offset 200 (address 0x7e00):
-00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+# offset 200 (address 0x7e00): interrupt descriptor table
+# 32 entries * 8 bytes each = 256 bytes (0x100)
+# idt_start:
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+
+# offset 9: keyboard, following https://alex.dzyoba.com/blog/os-interrupts
+  20 7d  # offset[0:16]
+  08 00  # segment selector (gdt_code)
+  00  # unused
+  8e  # 1/p 00/dpl 0 1110/type/32-bit-interrupt-gate
+  00 00  # offset[16:32]
+
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+# idt_end:
+
+# offset 300 (address 0x7f00):
+# idt_descriptor:
+  ff 00  # idt_end - idt_start - 1
+  00 7e 00 00  # start = idt_start
+
+# padding
+                  00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00