diff options
Diffstat (limited to 'diag')
-rw-r--r-- | diag/mbr/handoff.S | 345 |
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: |