summaryrefslogtreecommitdiff
path: root/diag
diff options
context:
space:
mode:
Diffstat (limited to 'diag')
-rw-r--r--diag/mbr/handoff.S345
1 files changed, 345 insertions, 0 deletions
diff --git a/diag/mbr/handoff.S b/diag/mbr/handoff.S
new file mode 100644
index 00000000..a73b4a66
--- /dev/null
+++ b/diag/mbr/handoff.S
@@ -0,0 +1,345 @@
+/* -----------------------------------------------------------------------
+ *
+ * Copyright 2010 Gene Cumm
+ *
+ * Portions from mbr.S:
+ * Copyright 2007-2009 H. Peter Anvin - All Rights Reserved
+ * Copyright 2009 Intel Corporation; author: H. Peter Anvin
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * mbr_ho.S: MBR-like codeblock to display handoff data
+ *
+ * Displays the values of DL, DS, SI, the contents of [DS:SI] (16 bytes),
+ * the values of ES, DI, the contents of [ES:DI] (4 bytes), scans memory for
+ * $PnP then reports a boot failure.
+ *
+ * This should (hopefully) be only 8086 code
+ */
+
+/*
+ * Install instructions (assuming your target is /dev/dev; file or block device):
+ *
+ * MBR:
+ * dd conv=notrunc bs=440 count=1 if=mbr_ho.bin of=/dev/dev
+ *
+ * VBR/PBR (should work for FAT12/16/32, ext[234]fs, btrfs):
+ * echo -en "\0353\0130\0220" |dd conv=notrunc bs=1 count=3 of=/dev/dev
+ * dd conv=notrunc bs=2 count=210 seek=45 if=mbr_ho.bin of=/dev/dev
+ */
+
+// #define DEBUG_MARKER1 /* Insert markers in binary */
+// #define DEBUG_START /* Print entry addresses at start */
+// #define DEBUG_LOADE /* movw versus pop */
+#define DEBUG_PNP /* Scan for $PnP and show address */
+#define DEBUG_PAK /* Press Any Key before boot fail */
+// #define DEBUG_ENTRY_REG /* Store (manually as pusha is 80186) registers */
+
+#ifdef DEBUG_MARKER1
+ .macro ASCII_MARKER1 s:vararg
+ .ascii \s
+ .endm
+#else /* DEBUG_MARKER1 */
+ .macro ASCII_MARKER1 s:vararg
+ .endm
+#endif /* DEBUG_MARKER1 */
+
+#ifdef DEBUG_LOADE
+ .macro LOADE r:req, t:req
+ movw (es_\r), %\t
+ .endm
+#else /* DEBUG_LOADE */
+ .macro LOADE r:req, t:req
+ popw %\t
+ .endm
+#endif /* DEBUG_LOADE */
+
+ .code16
+ .text
+
+entry = 0x7c00
+stack = (entry)
+e_start = (stack)
+e_ax = (e_start-2)
+e_ss = (e_ax-2)
+e_sp = (e_ss-2)
+e_bot = (e_ss)
+/* Doubtful this will be used */
+e0_beg = (e_bot)
+e0_ax = (e0_beg-2)
+e0_cx = (e0_ax-2)
+e0_dx = (e0_cx-2)
+e0_bx = (e0_dx-2)
+e0_sp = (e0_bx-2)
+e0_bp = (e0_sp-2)
+e0_si = (e0_bp-2)
+e0_di = (e0_si-2)
+e0_ds = (e0_di-2)
+e0_es = (e0_ds-2)
+e0_bot = (e0_es)
+es_beg = (e0_bot) /* Original register values from entry point */
+es_di = (es_beg-2)
+es_es = (es_di-2)
+es_si = (es_es-2)
+es_ds = (es_si-2)
+es_bot = (es_ds)
+
+BIOS_page = 0x462
+
+ .globl _start
+_start:
+ cli
+#ifdef DEBUG_ENTRY_REG
+ movw %ax, e_ax
+ movw %ss, e_ss
+ movw %sp, e_sp
+#endif /* DEBUG_ENTRY_REG */
+ xorw %ax, %ax
+ movw %ax, %ss
+#ifdef DEBUG_ENTRY_REG
+ movw $e0_beg, %sp
+ /* pushaw */ /* 80186 */
+ pushw %ax
+ pushw %cx
+ pushw %dx
+ pushw %bx
+ pushw %sp
+ pushw %bp
+ pushw %si
+ pushw %di
+ pushw %ds
+ pushw %es
+#else /* DEBUG_ENTRY_REG */
+ movw $es_beg, %sp
+#endif /* DEBUG_ENTRY_REG */
+ pushw %di /* es:di -> $PnP header */
+ pushw %es
+ pushw %si
+ pushw %ds
+ sti
+ cld
+ pushw %cs
+ popw %ds
+
+#ifdef DEBUG_START
+ pushw %dx
+ call crlf
+ movw $(_start),%dx /* 0x0600 mbr.ld .text address */
+ call wrhexw
+ call crlf
+ call caddr
+caddr:
+ popw %dx
+ subw $(caddr - _start), %dx
+ call wrhexw
+ call crlf
+ popw %dx
+#endif /* DEBUG_START */
+
+ /* write DL */
+pr_dl: call wrstr
+ .ascii "DL: \0"
+ call wrhexb
+ /* DS */
+pr_ds: call wrstr
+ .ascii " DS: \0"
+ LOADE ds, dx
+ pushw %dx
+ popw %es
+ call wrhexw
+ /* SI */
+pr_si: call wrstr
+ .ascii " SI: \0"
+ LOADE si, dx
+ pushw %dx
+ popw %di
+ call wrhexw
+ call crlf
+ /* DS:SI */
+ movw $16, %cx
+ call wrhexbses
+ call crlf
+
+ /* ES */
+pr_es: call wrstr
+ .ascii "ES: \0"
+ LOADE es, dx
+ pushw %dx
+ popw %es
+ call wrhexw
+pr_di: call wrstr
+ .ascii " DI: \0"
+ LOADE di, dx
+ pushw %dx
+ popw %di
+ call wrhexw
+ call crlf
+ /* ES:DI */ /* %es:0(%di) */
+ movw $4, %cx
+ call wrhexbses
+
+#ifdef DEBUG_PNP
+ subw $4, %si
+ es lodsw
+ cmpw $0x5024, %ax
+ jne scn_pnp
+ es lodsw
+ cmpw $0x506E, %ax
+ jne scn_pnp
+ call wrstr
+ .ascii " =$PnP\0"
+scn_pnp:
+ call crlf
+ /* $PnP Scan */
+ movw $0xf000, %dx
+ pushw %dx
+ popw %es
+ movw $0, %si
+ movw $0x1000, %cx
+ /* 0x506E5024 */
+ movw $0x5024, %dx
+ movw $0x506E, %bx
+ch_pnp: es lodsw
+ cmpw %dx, %ax
+ jne ch_pnp_l
+ es lodsw
+ cmpw %bx, %ax
+ je pr_pnp
+ch_pnp_l:
+ addw $14, %si
+ andw $0xFFF0, %si
+ loopw ch_pnp
+ jmp end
+pr_pnp:
+ pushw %si
+ call wrstr
+ .ascii "$PnP-\0"
+ movw %es, %dx
+ call wrhexw
+ movb $':, %al
+ call wrchr
+ popw %dx
+ andw $0xFFF0, %dx
+ call wrhexw
+#endif /* DEBUG_PNP */
+
+ call crlf
+
+end:
+ jmp bootfail
+
+ ASCII_MARKER1 "wc"
+wrchr:
+ movb $0x0e, %ah
+ movb (BIOS_page), %bh
+ movb $0x07, %bl
+ int $0x10 /* May destroy %bp */
+ ret
+
+ ASCII_MARKER1 "ws"
+wrstr:
+ pop %si
+wrstr_l:
+ lodsb
+ cmpb $0, %al
+ je wrstr_d
+ call wrchr
+ jmp wrstr_l
+wrstr_d:
+ push %si
+ ret
+
+crlf:
+ call wrstr
+ .ascii "\r\n\0"
+ ret
+
+ ASCII_MARKER1 "hx"
+wrhexn:
+ and $0x0F, %al
+ cmpb $10, %al
+ jae .alph
+ addb $'0, %al
+ jmp .wc
+.alph:
+ addb $('A - 10), %al
+.wc:
+ call wrchr
+ ret
+
+wrhexb:
+ pushw %cx
+ movb %dl, %al
+ pushw %ax
+ movb $4, %cl
+ rorw %cl, %ax
+ call wrhexn
+ popw %ax
+ call wrhexn
+ popw %cx
+ ret
+
+wrhexw:
+ pushw %cx
+ movb $8, %cl
+ rorw %cl, %dx
+ call wrhexb
+ rorw %cl, %dx
+ call wrhexb
+ popw %cx
+ ret
+
+ ASCII_MARKER1 "HE"
+wrhexbses:
+ pushw %di
+ popw %si
+wrhexbses_l:
+ movb $' , %al
+ call wrchr
+ es lodsb
+ movw %ax, %dx
+ call wrhexb
+ loop wrhexbses_l
+ ret
+
+data:
+ ASCII_MARKER1 "bf"
+bootfail:
+#ifdef DEBUG_PAK
+ call wrstr
+ .ascii "\r\n\r\nPress any key\r\n\0"
+ xor %ax, %ax
+ int $0x16
+#endif
+ int $0x18 /* Boot failure */
+die:
+ hlt
+ jmp die
+
+zerob: /* Begin zeroing block to fill to desired length */
+ /* 420 bytes for FAT32 */
+zeroln = (420 - (zerob - _start))
+ .=.+zeroln /* prevents overflow */
+zeroe: