; $Id: VMMR0TripleFaultHackA.asm 44529 2013-02-04 15:54:15Z vboxsync $ ;; @file ; VMM - Host Context Ring 0, Assembly Code for The Triple Fault Debugging Hack. ; ; ; Copyright (C) 2011-2012 Oracle Corporation ; ; This file is part of VirtualBox Open Source Edition (OSE), as ; available from http://www.virtualbox.org. This file is free software; ; you can redistribute it and/or modify it under the terms of the GNU ; General Public License (GPL) as published by the Free Software ; Foundation, in version 2 as it comes in the "COPYING" file of the ; VirtualBox OSE distribution. VirtualBox OSE is distributed in the ; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. ; ;******************************************************************************* ;* Header Files * ;******************************************************************************* %include "VBox/asmdefs.mac" BEGINCODE GLOBALNAME vmmR0TripleFaultHackStart %define CALC_ADDR(a_Addr) ( (a_Addr) - NAME(vmmR0TripleFaultHackStart) + 07000h ) BITS 16 BEGINPROC vmmR0TripleFaultHack ; Set up stack. cli ; paranoia mov sp, 0ffffh mov ax, cs mov ss, ax mov ds, ax mov es, ax cld ; paranoia COM_INIT ; Beep and say hello to the post-reset world. call NAME(vmmR0TripleFaultHackBeep) mov si, CALC_ADDR(.s_szHello) call NAME(vmmR0TripleFaultHackPrint) .forever: hlt jmp .forever .s_szHello: db 'Hello post-reset world', 0ah, 0dh, 0 ENDPROC vmmR0TripleFaultHack ;; ds:si = zero terminated string. BEGINPROC vmmR0TripleFaultHackPrint push eax push esi .outer_loop: lodsb cmp al, 0 je .done call NAME(vmmR0TripleFaultHackPrintCh) jmp .outer_loop .done: pop esi pop eax ret ENDPROC vmmR0TripleFaultHackPrint ;; al = char to print BEGINPROC vmmR0TripleFaultHackPrintCh push eax push edx push ecx mov ah, al ; save char. ; Wait for status. mov ecx, _1G mov dx, VBOX_UART_BASE + 5 .pre_status: in al, dx test al, 20h jnz .put_char dec ecx jnz .pre_status ; Write the character. .put_char: mov al, ah mov dx, VBOX_UART_BASE out dx, al ; Wait for status. mov ecx, _1G mov dx, VBOX_UART_BASE + 5 .post_status: in al, dx test al, 20h jnz .done dec ecx jnz .post_status .done: pop ecx pop edx pop eax ret ENDPROC vmmR0TripleFaultHackPrintCh ;; ; make a 440 BEEP. BEGINPROC vmmR0TripleFaultHackBeep push eax push edx push ecx ; program PIT(1) and stuff. mov al, 10110110b out 43h, al mov ax, 0a79h ; A = 440 out 42h, al shr ax, 8 out 42h, al in al, 61h or al, 3 out 61h, al ; delay mov ecx, _1G .delay: inc ecx dec ecx dec ecx jnz .delay ; shut up speaker. in al, 61h and al, 11111100b out 61h, al .done: pop ecx pop edx pop eax ret ENDPROC vmmR0TripleFaultHackBeep GLOBALNAME vmmR0TripleFaultHackEnd ;;; ;;; ;;; ;;; ;;; BITS ARCH_BITS BEGINPROC vmmR0TripleFaultHackKbdWait push xAX .check_status: in al, 64h test al, 1 ; KBD_STAT_OBF jnz .read_data_and_status test al, 2 ; KBD_STAT_IBF jnz .check_status pop xAX ret .read_data_and_status: in al, 60h jmp .check_status ENDPROC vmmR0TripleFaultHackKbdWait BEGINPROC vmmR0TripleFaultHackKbdRead out 64h, al ; Write the command. .check_status: in al, 64h test al, 1 ; KBD_STAT_OBF jz .check_status in al, 60h ; Read the data. ret ENDPROC vmmR0TripleFaultHackKbdRead BEGINPROC vmmR0TripleFaultHackKbdWrite out 64h, al ; Write the command. call NAME(vmmR0TripleFaultHackKbdWait) xchg al, ah out 60h, al ; Write the data. call NAME(vmmR0TripleFaultHackKbdWait) xchg al, ah ret ENDPROC vmmR0TripleFaultHackKbdWrite BEGINPROC vmmR0TripleFaultHackTripleFault push xAX push xSI xor eax, eax push xAX push xAX push xAX push xAX COM_CHAR 'B' COM_CHAR 'y' COM_CHAR 'e' COM_CHAR '!' COM_CHAR 0ah COM_CHAR 0dh ;call NAME(vmmR0TripleFaultHackBeep32) %if 1 lidt [xSP] %elif 0 in al, 92h or al, 1 out 92h, al in al, 92h cli hlt %else mov al, 0d0h ; KBD_CCMD_READ_OUTPORT call NAME(vmmR0TripleFaultHackKbdRead) mov ah, 0feh and ah, al mov al, 0d1h ; KBD_CCMD_WRITE_OUTPORT call NAME(vmmR0TripleFaultHackKbdWrite) cli hlt %endif int3 pop xAX pop xAX pop xAX pop xAX pop xSI pop xAX ret ENDPROC vmmR0TripleFaultHackTripleFault