diff options
author | Kartik Agaram <vc@akkartik.com> | 2020-12-23 23:11:39 -0800 |
---|---|---|
committer | Kartik Agaram <vc@akkartik.com> | 2020-12-23 23:11:39 -0800 |
commit | 720dc75be7cbb9ee2ae85f4af42cd2d7542d9009 (patch) | |
tree | a99fcde35b8ec5ebbf36f609f97a474b2f51bb28 /html/apps/boot.hex.html | |
parent | 32fc6c2ddfc353ff88f3ceca8e4eb7e8607f5edf (diff) | |
download | mu-720dc75be7cbb9ee2ae85f4af42cd2d7542d9009.tar.gz |
7396
Diffstat (limited to 'html/apps/boot.hex.html')
-rw-r--r-- | html/apps/boot.hex.html | 371 |
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 < apps/boot.hex > 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 <- 0</span> + 8e d8 <span class="Comment"># ds <- ax</span> + 8e d0 <span class="Comment"># ss <- ax</span> + 8e c0 <span class="Comment"># es <- ax</span> + 8e e0 <span class="Comment"># fs <- ax</span> + 8e e8 <span class="Comment"># gs <- 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 <- 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 <- 0 # cylinder 0</span> + b6 00 <span class="Comment"># dh <- 0 # track 0</span> + b1 02 <span class="Comment"># cl <- 2 # second sector, 1-based</span> + b0 01 <span class="Comment"># al <- 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 <- 0</span> + 8e c3 <span class="Comment"># es <- bx</span> + bb 00 7e <span class="Comment"># bx <- 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 <- 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 <- 0xd1</span> + e6 64 <span class="Comment"># port 0x64 <- al</span> + +<span class="Comment"># 30:</span> + <span class="Comment"># seta20.2:</span> + e4 64 <span class="Comment"># al <- 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 <- 0xdf</span> + e6 64 <span class="Comment"># port 0x64 <- 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 <- cr0</span> + 66 83 c8 01 <span class="Comment"># eax <- or 0x1</span> + 0f 22 c0 <span class="Comment"># cr0 <- 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 <- 0x0f44</span> + <span class="Comment"># bx <- 0xb800</span> + bb 00 b8 + <span class="Comment"># ds <- bx</span> + 8e db <span class="Comment"># 11b/mod 011b/reg/ds 011b/rm/bx</span> + <span class="Comment"># al <- 'D'</span> + b0 44 + <span class="Comment"># ah <- 0x0f # white on black</span> + b4 0f + <span class="Comment"># bx <- 0</span> + bb 00 00 + <span class="Comment"># *ds:bx <- 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 <- offset 16 from gdt_start</span> + 8e d8 <span class="Comment"># ds <- ax</span> + 8e d0 <span class="Comment"># ss <- ax</span> + 8e c0 <span class="Comment"># es <- ax</span> + 8e e0 <span class="Comment"># fs <- ax</span> + 8e e8 <span class="Comment"># gs <- 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 <- 0xfd # enable just IRQ1</span> + e6 21 <span class="Comment"># port 0x21 <- 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 <- *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 <- 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 <- 0x20</span> + e6 20 <span class="Comment"># port 0x20 <- 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 <- 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 <- xor eax; 11/direct 000/r32/eax 000/rm32/eax</span> + e4 60 <span class="Comment"># al <- 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 <- 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:ft=conf</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> |