summaryrefslogtreecommitdiffstats
path: root/src/VBox/VMM/VMMR0/VMMR0TripleFaultHackA.asm
blob: cca91654303f6b8d18bc033daffce46d269a7dc2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
; $Id: VMMR0TripleFaultHackA.asm $
;; @file
; VMM - Host Context Ring 0, Assembly Code for The Triple Fault Debugging Hack.
;

;
; Copyright (C) 2011-2020 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