about summary refs log tree commit diff stats
path: root/html/apps/boot.hex.html
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2020-12-23 23:11:39 -0800
committerKartik Agaram <vc@akkartik.com>2020-12-23 23:11:39 -0800
commit720dc75be7cbb9ee2ae85f4af42cd2d7542d9009 (patch)
treea99fcde35b8ec5ebbf36f609f97a474b2f51bb28 /html/apps/boot.hex.html
parent32fc6c2ddfc353ff88f3ceca8e4eb7e8607f5edf (diff)
downloadmu-720dc75be7cbb9ee2ae85f4af42cd2d7542d9009.tar.gz
7396
Diffstat (limited to 'html/apps/boot.hex.html')
-rw-r--r--html/apps/boot.hex.html371
1 files changed, 371 insertions, 0 deletions
diff --git a/html/apps/boot.hex.html b/html/apps/boot.hex.html
new file mode 100644
index 00000000..31aeeb67
--- /dev/null
+++ b/html/apps/boot.hex.html
@@ -0,0 +1,371 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>Mu - apps/boot.hex</title>
+<meta name="Generator" content="Vim/8.1">
+<meta name="plugin-version" content="vim8.1_v1">
+<meta name="syntax" content="conf">
+<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
+<meta name="colorscheme" content="minimal-light">
+<style type="text/css">
+<!--
+pre { white-space: pre-wrap; font-family: monospace; color: #000000; background-color: #c6c6c6; }
+body { font-family: monospace; color: #000000; background-color: #c6c6c6; }
+* { font-size: 1em; }
+.Todo { color: #000000; background-color: #ffff00; padding-bottom: 1px; }
+.Comment { color: #005faf; }
+-->
+</style>
+</head>
+<body>
+<a href='https://github.com/akkartik/mu/blob/master/apps/boot.hex'>https://github.com/akkartik/mu/blob/master/apps/boot.hex</a>
+<pre id='vimCodeElement'>
+<span class="Comment"># Bootable image that:</span>
+<span class="Comment">#   - loads more sectors past the first boot sector (using BIOS primitives)</span>
+<span class="Comment">#   - switches to 32-bit mode (giving up access to BIOS primitives)</span>
+<span class="Comment">#   - sets up a handler for keyboard events</span>
+<span class="Comment">#   - as an example program, prints alphabets to the top-left position on screen (by writing to memory-mapped VGA memory) as they're typed</span>
+<span class="Comment">#</span>
+<span class="Comment"># If the initial load fails, it prints 'D' to the top-left of the screen and</span>
+<span class="Comment"># halts.</span>
+<span class="Comment">#</span>
+<span class="Comment"># To convert to a disk image, first prepare a realistically sized disk image:</span>
+<span class="Comment">#   dd if=/dev/zero of=disk.img count=20160  # 512-byte sectors, so 10MB</span>
+<span class="Comment"># Now fill in sectors:</span>
+<span class="Comment">#   ./bootstrap run apps/hex &lt; apps/boot.hex &gt; boot.bin</span>
+<span class="Comment">#   dd if=boot.bin of=disk.img conv=notrunc</span>
+<span class="Comment"># To run:</span>
+<span class="Comment">#   qemu-system-i386 disk.img</span>
+<span class="Comment"># Or:</span>
+<span class="Comment">#   bochs -f apps/boot.bochsrc  # boot.bochsrc loads disk.img</span>
+<span class="Comment">#</span>
+<span class="Comment"># Since we start out in 16-bit mode, we need instructions SubX doesn't</span>
+<span class="Comment"># support.</span>
+<span class="Comment"># This file contains just hex bytes and comments. Zero error-checking. Make</span>
+<span class="Comment"># liberal use of:</span>
+<span class="Comment">#   - comments documenting expected offsets</span>
+<span class="Comment">#   - size checks on the emitted file (currently: 512 bytes)</span>
+<span class="Comment">#   - xxd to eyeball that offsets contain expected bytes</span>
+
+<span class="Comment">## 16-bit entry point</span>
+
+<span class="Comment"># Upon reset, the IBM PC</span>
+<span class="Comment">#   loads the first sector (512 bytes)</span>
+<span class="Comment">#   from some bootable image (see the boot sector marker at the end of this file)</span>
+<span class="Comment">#   to the address range [0x7c00, 0x7e00)</span>
+
+<span class="Comment"># offset 00 (address 0x7c00):</span>
+  <span class="Comment"># disable interrupts for this initialization</span>
+  fa  <span class="Comment"># cli</span>
+
+  <span class="Comment"># initialize segment registers</span>
+  <span class="Comment"># this isn't always needed, but is considered safe not to assume</span>
+  b8 00 00  <span class="Comment"># ax &lt;- 0</span>
+  8e d8  <span class="Comment"># ds &lt;- ax</span>
+  8e d0  <span class="Comment"># ss &lt;- ax</span>
+  8e c0  <span class="Comment"># es &lt;- ax</span>
+  8e e0  <span class="Comment"># fs &lt;- ax</span>
+  8e e8  <span class="Comment"># gs &lt;- ax</span>
+
+  <span class="Comment"># We don't read or write the stack before we get to 32-bit mode. No function</span>
+  <span class="Comment"># calls, so we don't need to initialize the stack.</span>
+
+<span class="Comment"># 0e:</span>
+  <span class="Comment"># load more sectors from disk</span>
+  b4 02  <span class="Comment"># ah &lt;- 2  # read sectors from disk</span>
+  <span class="Comment"># dl comes conveniently initialized at boot time with the index of the device being booted</span>
+  b5 00  <span class="Comment"># ch &lt;- 0  # cylinder 0</span>
+  b6 00  <span class="Comment"># dh &lt;- 0  # track 0</span>
+  b1 02  <span class="Comment"># cl &lt;- 2  # second sector, 1-based</span>
+  b0 01  <span class="Comment"># al &lt;- 1  # number of sectors to read</span>
+  <span class="Comment"># address to write sectors to = es:bx = 0x7e00, contiguous with boot segment</span>
+  bb 00 00  <span class="Comment"># bx &lt;- 0</span>
+  8e c3  <span class="Comment"># es &lt;- bx</span>
+  bb 00 7e  <span class="Comment"># bx &lt;- 0x7e00</span>
+  cd 13  <span class="Comment"># int 13h, BIOS disk service</span>
+  0f 82 76 00  <span class="Comment"># jump-if-carry disk-error</span>
+
+<span class="Comment"># 26:</span>
+  <span class="Comment"># undo the A20 hack: <a href="https://en.wikipedia.org/wiki/A20_line">https://en.wikipedia.org/wiki/A20_line</a></span>
+  <span class="Comment"># this is from <a href="https://github.com/mit-pdos/xv6-public/blob/master/bootasm.S">https://github.com/mit-pdos/xv6-public/blob/master/bootasm.S</a></span>
+  <span class="Comment"># seta20.1:</span>
+  e4 64  <span class="Comment"># al &lt;- port 0x64</span>
+  a8 02  <span class="Comment"># set zf if bit 1 (second-least significant) is not set</span>
+  75 fa  <span class="Comment"># if zf not set, goto seta20.1 (-6)</span>
+
+  b0 d1  <span class="Comment"># al &lt;- 0xd1</span>
+  e6 64  <span class="Comment"># port 0x64 &lt;- al</span>
+
+<span class="Comment"># 30:</span>
+  <span class="Comment"># seta20.2:</span>
+  e4 64  <span class="Comment"># al &lt;- port 0x64</span>
+  a8 02  <span class="Comment"># set zf if bit 1 (second-least significant) is not set</span>
+  75 fa  <span class="Comment"># if zf not set, goto seta20.2 (-6)</span>
+
+  b0 df  <span class="Comment"># al &lt;- 0xdf</span>
+  e6 64  <span class="Comment"># port 0x64 &lt;- al</span>
+
+<span class="Comment"># 3a:</span>
+  <span class="Comment"># switch to 32-bit mode</span>
+  0f 01 16  <span class="Comment"># lgdt 00/mod/indirect 010/subop 110/rm/use-disp16</span>
+    80 7c  <span class="Comment"># *gdt_descriptor</span>
+<span class="Comment"># 3f:</span>
+  0f 20 c0  <span class="Comment"># eax &lt;- cr0</span>
+  66 83 c8 01  <span class="Comment"># eax &lt;- or 0x1</span>
+  0f 22 c0  <span class="Comment"># cr0 &lt;- eax</span>
+  ea c0 7c 08 00  <span class="Comment"># far jump to initialize_32bit_mode after setting cs to the record at offset 8 in the gdt (gdt_code)</span>
+
+<span class="Comment"># padding</span>
+<span class="Comment"># 4e:</span>
+                                          00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+<span class="Comment">## GDT: 3 records of 8 bytes each</span>
+
+<span class="Comment"># 60:</span>
+<span class="Comment"># gdt_start:</span>
+<span class="Comment"># gdt_null:  mandatory null descriptor</span>
+  00 00 00 00 00 00 00 00
+<span class="Comment"># gdt_code:  (offset 8 from gdt_start)</span>
+  ff ff  <span class="Comment"># limit[0:16]</span>
+  00 00 00  <span class="Comment"># base[0:24]</span>
+  9a  <span class="Comment"># 1/present 00/privilege 1/descriptor type = 1001b</span>
+      <span class="Comment"># 1/code 0/conforming 1/readable 0/accessed = 1010b</span>
+  cf  <span class="Comment"># 1/granularity 1/32-bit 0/64-bit-segment 0/AVL = 1100b</span>
+      <span class="Comment"># limit[16:20] = 1111b</span>
+  00  <span class="Comment"># base[24:32]</span>
+<span class="Comment"># gdt_data:  (offset 16 from gdt_start)</span>
+  ff ff  <span class="Comment"># limit[0:16]</span>
+  00 00 00  <span class="Comment"># base[0:24]</span>
+  92  <span class="Comment"># 1/present 00/privilege 1/descriptor type = 1001b</span>
+      <span class="Comment"># 0/data 0/conforming 1/readable 0/accessed = 0010b</span>
+  cf  <span class="Comment"># same as gdt_code</span>
+  00  <span class="Comment"># base[24:32]</span>
+<span class="Comment"># gdt_end:</span>
+
+<span class="Comment"># padding</span>
+<span class="Comment"># 78:</span>
+                        00 00 00 00 00 00 00 00
+
+<span class="Comment"># 80:</span>
+<span class="Comment"># gdt_descriptor:</span>
+  17 00  <span class="Comment"># final index of gdt = gdt_end - gdt_start - 1</span>
+  60 7c 00 00  <span class="Comment"># start = gdt_start</span>
+
+<span class="Comment"># padding</span>
+<span class="Comment"># 85:</span>
+                  00 00 00 00 00 00 00 00 00 00
+
+<span class="Comment"># 90:</span>
+<span class="Comment"># disk_error:</span>
+  <span class="Comment"># print 'D' to top-left of screen to indicate disk error</span>
+  <span class="Comment"># *0xb8000 &lt;- 0x0f44</span>
+  <span class="Comment"># bx &lt;- 0xb800</span>
+  bb 00 b8
+  <span class="Comment"># ds &lt;- bx</span>
+  8e db  <span class="Comment"># 11b/mod 011b/reg/ds 011b/rm/bx</span>
+  <span class="Comment"># al &lt;- 'D'</span>
+  b0 44
+  <span class="Comment"># ah &lt;- 0x0f  # white on black</span>
+  b4 0f
+  <span class="Comment"># bx &lt;- 0</span>
+  bb 00 00
+  <span class="Comment"># *ds:bx &lt;- ax</span>
+  89 07  <span class="Comment"># 00b/mod/indirect 000b/reg/ax 111b/rm/bx</span>
+
+e9 fb ff  <span class="Comment"># loop forever</span>
+
+<span class="Comment"># padding</span>
+<span class="Comment"># a1:</span>
+   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+<span class="Comment">## 32-bit code from this point (still some instructions not in SubX)</span>
+
+<span class="Comment"># c0:</span>
+<span class="Comment"># initialize_32bit_mode:</span>
+  66 b8 10 00  <span class="Comment"># ax &lt;- offset 16 from gdt_start</span>
+  8e d8  <span class="Comment"># ds &lt;- ax</span>
+  8e d0  <span class="Comment"># ss &lt;- ax</span>
+  8e c0  <span class="Comment"># es &lt;- ax</span>
+  8e e0  <span class="Comment"># fs &lt;- ax</span>
+  8e e8  <span class="Comment"># gs &lt;- ax</span>
+
+  <span class="Comment"># load interrupt handlers</span>
+  0f 01 1d  <span class="Comment"># lidt 00/mod/indirect 011/subop 101/rm32/use-disp32</span>
+    00 7f 00 00  <span class="Comment"># *idt_descriptor</span>
+
+  <span class="Comment"># enable keyboard IRQ</span>
+  b0 fd  <span class="Comment"># al &lt;- 0xfd  # enable just IRQ1</span>
+  e6 21  <span class="Comment"># port 0x21 &lt;- al</span>
+
+  <span class="Comment"># initialization is done; enable interrupts</span>
+  fb
+  e9 21 00 00 00  <span class="Comment"># jump to 0x7d00</span>
+
+<span class="Comment"># padding</span>
+<span class="Comment"># df:</span>
+                                             00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+<span class="Comment">## 'application' SubX code: print one character to top-left of screen</span>
+
+<span class="Comment"># offset 100 (address 0x7d00):</span>
+<span class="Comment"># Entry:</span>
+  <span class="Comment"># eax &lt;- *0x7ff4  # random address in second segment containing 'H'</span>
+  8b  <span class="Comment"># copy rm32 to r32</span>
+    05  <span class="Comment"># 00/mod/indirect 000/r32/eax 101/rm32/use-disp32</span>
+    <span class="Comment"># disp32</span>
+    f4 7f 00 00
+  <span class="Comment"># *0xb8000 &lt;- eax</span>
+  89  <span class="Comment"># copy r32 to rm32</span>
+    05  <span class="Comment"># 00/mod/indirect 000/r32/eax 101/rm32/use-disp32</span>
+    <span class="Comment"># disp32</span>
+    00 80 0b 00
+
+e9 fb ff ff ff  <span class="Comment"># loop forever</span>
+
+<span class="Comment"># padding</span>
+<span class="Comment"># 111:</span>
+   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+<span class="Comment"># 120:</span>
+<span class="Comment"># null interrupt handler:</span>
+  cf  <span class="Comment"># iret</span>
+
+<span class="Comment"># padding</span>
+<span class="Comment"># 121:</span>
+   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+<span class="Comment"># 130:</span>
+<span class="Comment"># keyboard interrupt handler:</span>
+  <span class="Comment"># prologue</span>
+  fa  <span class="Comment"># disable interrupts</span>
+  60  <span class="Comment"># push all registers to stack</span>
+  <span class="Comment"># acknowledge interrupt</span>
+  b0 20  <span class="Comment"># al &lt;- 0x20</span>
+  e6 20  <span class="Comment"># port 0x20 &lt;- al</span>
+  <span class="Comment"># read keyboard status (</span><span class="Todo">TODO</span><span class="Comment">: why bit 0? Doesn't line up with <a href="https://web.archive.org/web/20040604041507/http://panda.cs.ndsu.nodak.edu/~achapwes/PICmicro/keyboard/atkeyboard.html)">https://web.archive.org/web/20040604041507/http://panda.cs.ndsu.nodak.edu/~achapwes/PICmicro/keyboard/atkeyboard.html)</a></span>
+<span class="Comment">#?   e4 64  # al &lt;- port 0x64</span>
+<span class="Comment">#?   a8 01  # set zf if bit 0 (least significant) is not set</span>
+<span class="Comment">#?   74 11  # if bit 0 is not set, skip to epilogue</span>
+  <span class="Comment"># read keycode into eax</span>
+  31 c0  <span class="Comment"># eax &lt;- xor eax;  11/direct 000/r32/eax 000/rm32/eax</span>
+  e4 60  <span class="Comment"># al &lt;- port 0x60</span>
+  <span class="Comment"># map key '1' to ascii; if eax == 2, eax = 0x31</span>
+  3d 02 00 00 00  <span class="Comment"># compare eax with 0x02</span>
+  75 0b  <span class="Comment"># if not equal, goto epilogue</span>
+  b8 31 0f 00 00  <span class="Comment"># eax &lt;- 0x0f31</span>
+  <span class="Comment"># print eax to top-left of screen (*0xb8000)</span>
+  89  <span class="Comment"># copy r32 to rm32</span>
+    05  <span class="Comment"># 00/mod/indirect 000/r32/eax 101/rm32/use-disp32</span>
+    <span class="Comment"># disp32</span>
+    00 80 0b 00
+  <span class="Comment"># epilogue</span>
+  61  <span class="Comment"># pop all registers</span>
+  fb  <span class="Comment"># enable interrupts</span>
+  cf  <span class="Comment"># iret</span>
+
+<span class="Comment"># padding</span>
+<span class="Comment"># 14f</span>
+                                             00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+<span class="Comment"># final 2 bytes of boot sector</span>
+55 aa
+
+<span class="Comment">## sector 2</span>
+<span class="Comment"># not loaded on boot; loaded by load_disk</span>
+
+<span class="Comment"># offset 200 (address 0x7e00): interrupt descriptor table</span>
+<span class="Comment"># 32 entries * 8 bytes each = 256 bytes (0x100)</span>
+<span class="Comment"># idt_start:</span>
+
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+
+<span class="Comment"># entry 8: clock?</span>
+  20 7d  <span class="Comment"># target[0:16] = null interrupt handler</span>
+  08 00  <span class="Comment"># segment selector (gdt_code)</span>
+  00  <span class="Comment"># unused</span>
+  8e  <span class="Comment"># 1/p 00/dpl 0 1110/type/32-bit-interrupt-gate</span>
+  00 00  <span class="Comment"># target[16:32]</span>
+
+<span class="Comment"># entry 9: keyboard?</span>
+  30 7d  <span class="Comment"># target[0:16] = keyboard interrupt handler</span>
+  08 00  <span class="Comment"># segment selector (gdt_code)</span>
+  00  <span class="Comment"># unused</span>
+  8e  <span class="Comment"># 1/p 00/dpl 0 1110/type/32-bit-interrupt-gate</span>
+  00 00  <span class="Comment"># target[16:32]</span>
+
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+<span class="Comment"># idt_end:</span>
+
+<span class="Comment"># offset 300 (address 0x7f00):</span>
+<span class="Comment"># idt_descriptor:</span>
+  ff 00  <span class="Comment"># idt_end - idt_start - 1</span>
+  00 7e 00 00  <span class="Comment"># start = idt_start</span>
+
+<span class="Comment"># padding</span>
+                  00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 48 0f 00 00 00 00 00 00 00 00 00 00  <span class="Comment"># spot the 'H' with attributes</span>
+<span class="Comment"># offset 400 (address 0x8000)</span>
+
+<span class="Comment"># vim&#0058;ft=conf</span>
+</pre>
+</body>
+</html>
+<!-- vim: set foldmethod=manual : -->