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
|
## @file
# This is the assembly code for transferring to control to OS S3 waking vector
# for X64 platform
#
# Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials are
# licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
ASM_GLOBAL ASM_PFX(AsmTransferControl)
ASM_PFX(AsmTransferControl):
# rcx S3WakingVector :DWORD
# rdx AcpiLowMemoryBase :DWORD
lea _AsmTransferControl_al_0000(%rip), %eax
movq $0x2800000000, %r8
orq %r8, %rax
pushq %rax
shrd $20, %ecx, %ebx
andl $0x0f, %ecx
movw %cx, %bx
movl %ebx, jmp_addr(%rip)
lret
_AsmTransferControl_al_0000:
.byte 0x0b8, 0x30, 0 # mov ax, 30h as selector
movl %eax, %ds
movl %eax, %es
movl %eax, %fs
movl %eax, %gs
movl %eax, %ss
movq %cr0, %rax
movq %cr4, %rbx
.byte 0x66
andl $0x7ffffffe, %eax
andb $0xdf, %bl
movq %rax, %cr0
.byte 0x66
movl $0x0c0000080, %ecx
rdmsr
andb $0xfe, %ah
wrmsr
movq %rbx, %cr4
.byte 0x0ea # jmp far jmp_addr
jmp_addr:
.long 0
ASM_GLOBAL ASM_PFX(AsmTransferControl32)
ASM_PFX(AsmTransferControl32):
# S3WakingVector :DWORD
# AcpiLowMemoryBase :DWORD
pushq %rbp
movl %esp,%ebp
.byte 0x8d, 0x05 # lea eax, AsmTransferControl16
ASM_GLOBAL ASM_PFX(AsmFixAddress16)
ASM_PFX(AsmFixAddress16):
.long 0
pushq $0x28 # CS
pushq %rax
lret
ASM_GLOBAL ASM_PFX(AsmTransferControl16)
ASM_PFX(AsmTransferControl16):
.byte 0xb8,0x30,0 # mov ax, 30h as selector
movw %ax,%ds
movw %ax,%es
movw %ax,%fs
movw %ax,%gs
movw %ax,%ss
movq %cr0, %rax # Get control register 0
.byte 0x66
.byte 0x83,0xe0,0xfe # and eax, 0fffffffeh ; Clear PE bit (bit #0)
.byte 0xf,0x22,0xc0 # mov cr0, eax ; Activate real mode
.byte 0xea # jmp far AsmJmpAddr32
ASM_GLOBAL ASM_PFX(AsmJmpAddr32)
ASM_PFX(AsmJmpAddr32):
.long 0
ASM_GLOBAL ASM_PFX(PageFaultHandlerHook)
ASM_PFX(PageFaultHandlerHook):
pushq %rax # save all volatile registers
pushq %rcx
pushq %rdx
pushq %r8
pushq %r9
pushq %r10
pushq %r11
# save volatile fp registers
addq $-0x68, %rsp
stmxcsr 0x60(%rsp)
movdqa %xmm0, 0x0(%rsp)
movdqa %xmm1, 0x10(%rsp)
movdqa %xmm2, 0x20(%rsp)
movdqa %xmm3, 0x30(%rsp)
movdqa %xmm4, 0x40(%rsp)
movdqa %xmm5, 0x50(%rsp)
addq $-0x20, %rsp
call ASM_PFX(PageFaultHandler)
addq $0x20, %rsp
# load volatile fp registers
ldmxcsr 0x60(%rsp)
movdqa 0x0(%rsp), %xmm0
movdqa 0x10(%rsp), %xmm1
movdqa 0x20(%rsp), %xmm2
movdqa 0x30(%rsp), %xmm3
movdqa 0x40(%rsp), %xmm4
movdqa 0x50(%rsp), %xmm5
addq $0x68, %rsp
testb %al, %al
popq %r11
popq %r10
popq %r9
popq %r8
popq %rdx
popq %rcx
popq %rax # restore all volatile registers
jnz L1
jmpq *ASM_PFX(mOriginalHandler)(%rip)
L1:
addq $0x08, %rsp # skip error code for PF
iretq
|