366 lines
6.8 KiB
ArmAsm
366 lines
6.8 KiB
ArmAsm
/* -----------------------------------------------------------------------
|
|
*
|
|
* Copyright 2010-2011 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.
|
|
*
|
|
* ----------------------------------------------------------------------- */
|
|
|
|
/*
|
|
* handoff.S: MBR/VBR-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=handoff.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=handoff.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 */
|
|
// #define DEBUG_FDT /* Print the floppy descriptor table; INT 1Eh*/
|
|
|
|
#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
|
|
|
|
int_1e = (4*0x1e)
|
|
int_1e_seg = (int_1e)
|
|
int_1e_off = (int_1e+2)
|
|
|
|
.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 /* Check for $PnP */
|
|
cmpw %dx, %ax
|
|
jne ch_pnp_l
|
|
es lodsw
|
|
cmpw %bx, %ax
|
|
je pr_pnp
|
|
ch_pnp_l: /* Check $PnP failed; loop to next address */
|
|
addw $14, %si
|
|
andw $0xFFF0, %si
|
|
loopw ch_pnp
|
|
jmp pnp_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
|
|
pnp_end:
|
|
|
|
#ifdef DEBUG_FDT
|
|
/* INT 1Eh: Floppy Parameter Table Pointer */
|
|
pr_1e: call wrstr
|
|
.ascii "INT 1Eh: \0"
|
|
mov $int_1e,%bx
|
|
les (%bx),%di
|
|
pushw %es
|
|
popw %dx
|
|
call wrhexw
|
|
movb $':, %al
|
|
call wrchr
|
|
pushw %di
|
|
popw %dx
|
|
call wrhexw
|
|
call crlf
|
|
/* [INT 1Eh] */
|
|
movw $14, %cx
|
|
call wrhexbses
|
|
call crlf
|
|
#endif /* DEBUG_FDT */
|
|
|
|
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
|