mirror of
https://github.com/chipsec/chipsec
synced 2026-06-08 13:31:00 +00:00
491b951f5b
Signed-off-by: Jason Zhou <jun2.zhou@intel.com>
702 lines
16 KiB
NASM
702 lines
16 KiB
NASM
TITLE cpu.asm: Assembly code for the x64 resources
|
|
|
|
.CODE chipsec_code$__a
|
|
|
|
PUBLIC DisableInterrupts
|
|
PUBLIC WritePortDword
|
|
PUBLIC WritePortWord
|
|
PUBLIC WritePortByte
|
|
PUBLIC ReadPortDword
|
|
PUBLIC ReadPortWord
|
|
PUBLIC ReadPortByte
|
|
PUBLIC WriteHighCMOSByte
|
|
PUBLIC WriteLowCMOSByte
|
|
PUBLIC SendAPMSMI
|
|
PUBLIC WritePCIByte
|
|
PUBLIC WritePCIWord
|
|
PUBLIC WritePCIDword
|
|
PUBLIC ReadPCIByte
|
|
PUBLIC ReadPCIWord
|
|
PUBLIC ReadPCIDword
|
|
PUBLIC _rdmsr
|
|
PUBLIC _wrmsr
|
|
PUBLIC _load_gdt
|
|
PUBLIC _rflags
|
|
PUBLIC ReadCR0
|
|
PUBLIC ReadCR2
|
|
PUBLIC ReadCR3
|
|
PUBLIC ReadCR4
|
|
PUBLIC ReadCR8
|
|
PUBLIC WriteCR0
|
|
PUBLIC WriteCR2
|
|
PUBLIC WriteCR3
|
|
PUBLIC WriteCR4
|
|
PUBLIC WriteCR8
|
|
PUBLIC hypercall
|
|
PUBLIC hypercall_page
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; UINT64 _rflags()
|
|
;------------------------------------------------------------------------------
|
|
_rflags PROC
|
|
pushfq
|
|
pop rax
|
|
ret
|
|
_rflags ENDP
|
|
|
|
;------------------------------------------------------------------------------
|
|
; void _store_idtr(
|
|
; unsigned char *address // rcx
|
|
; )
|
|
;------------------------------------------------------------------------------
|
|
_store_idtr PROC
|
|
sidt fword ptr [rcx]
|
|
ret
|
|
_store_idtr ENDP
|
|
|
|
;------------------------------------------------------------------------------
|
|
; void _load_idtr(
|
|
; unsigned char *address // rcx
|
|
; )
|
|
;------------------------------------------------------------------------------
|
|
_load_idtr PROC
|
|
lidt fword ptr [rcx]
|
|
ret
|
|
_load_idtr ENDP
|
|
|
|
;------------------------------------------------------------------------------
|
|
; void _store_gdtr(
|
|
; unsigned char *address // rcx
|
|
; )
|
|
;------------------------------------------------------------------------------
|
|
_store_gdtr PROC
|
|
sgdt fword ptr [rcx]
|
|
ret
|
|
_store_gdtr ENDP
|
|
|
|
;------------------------------------------------------------------------------
|
|
; void _load_gdtr(
|
|
; unsigned char *address // rcx
|
|
; )
|
|
;------------------------------------------------------------------------------
|
|
_load_gdtr PROC
|
|
lgdt fword ptr [rcx]
|
|
ret
|
|
_load_gdtr ENDP
|
|
|
|
;------------------------------------------------------------------------------
|
|
; void _store_ldtr(
|
|
; unsigned char *address // rcx
|
|
; )
|
|
;------------------------------------------------------------------------------
|
|
_store_ldtr PROC
|
|
;sldt fword ptr [rcx]
|
|
ret
|
|
_store_ldtr ENDP
|
|
|
|
;------------------------------------------------------------------------------
|
|
; void _load_ldtr(
|
|
; unsigned char *address // rcx
|
|
; )
|
|
;------------------------------------------------------------------------------
|
|
_load_ldtr PROC
|
|
;lldt fword ptr [rcx]
|
|
ret
|
|
_load_ldtr ENDP
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; void _load_gdt(
|
|
; unsigned char *value // rcx
|
|
; )
|
|
;------------------------------------------------------------------------------
|
|
_load_gdt PROC
|
|
|
|
sgdt fword ptr [rcx]
|
|
lgdt fword ptr [rcx]
|
|
|
|
ret
|
|
_load_gdt ENDP
|
|
|
|
;------------------------------------------------------------------------------
|
|
; void _rdmsr(
|
|
; unsigned int msr_num, // rcx
|
|
; unsigned int* msr_lo, // rdx
|
|
; unsigned int* msr_hi // r8
|
|
; )
|
|
;------------------------------------------------------------------------------
|
|
_rdmsr PROC FRAME
|
|
push r10
|
|
.ALLOCSTACK 8
|
|
push r11
|
|
.ALLOCSTACK 8
|
|
push rax
|
|
.ALLOCSTACK 8
|
|
push rdx
|
|
.ALLOCSTACK 8
|
|
.endprolog
|
|
|
|
mov r10, rdx ; msr_lo
|
|
mov r11, r8 ; msr_hi
|
|
|
|
; rcx has msr_num
|
|
rdmsr
|
|
|
|
; Write MSR results in edx:eax
|
|
mov dword ptr [r10], eax
|
|
mov dword ptr [r11], edx
|
|
|
|
pop rdx
|
|
pop rax
|
|
pop r11
|
|
pop r10
|
|
|
|
ret
|
|
_rdmsr ENDP
|
|
|
|
;------------------------------------------------------------------------------
|
|
; void _wrmsr(
|
|
; unsigned int msr_num, // rcx
|
|
; unsigned int msr_hi, // rdx
|
|
; unsigned int msr_lo // r8
|
|
; )
|
|
;------------------------------------------------------------------------------
|
|
_wrmsr PROC FRAME
|
|
push rax
|
|
.ALLOCSTACK 8
|
|
.endprolog
|
|
|
|
; rcx has msr_num
|
|
; rdx has msr_hi
|
|
; move msr_lo from r8 to rax
|
|
mov rax, r8
|
|
wrmsr
|
|
|
|
pop rax
|
|
ret
|
|
_wrmsr ENDP
|
|
|
|
;------------------------------------------------------------------------------
|
|
; void
|
|
; DisableInterrupts (
|
|
; )
|
|
;------------------------------------------------------------------------------
|
|
DisableInterrupts PROC
|
|
cli
|
|
ret
|
|
DisableInterrupts ENDP
|
|
|
|
;------------------------------------------------------------------------------
|
|
; void
|
|
; WritePortDword (
|
|
; unsigned int out_value // rcx
|
|
; unsigned short port_num // rdx
|
|
; )
|
|
;------------------------------------------------------------------------------
|
|
WritePortDword PROC FRAME
|
|
push rax
|
|
.ALLOCSTACK 8
|
|
.endprolog
|
|
|
|
mov rax, rcx
|
|
out dx, rax
|
|
|
|
pop rax
|
|
ret
|
|
WritePortDword ENDP
|
|
|
|
;------------------------------------------------------------------------------
|
|
; void
|
|
; WritePortWord (
|
|
; unsigned short out_value // rcx
|
|
; unsigned short port_num // rdx
|
|
; )
|
|
;------------------------------------------------------------------------------
|
|
WritePortWord PROC FRAME
|
|
push rax
|
|
.ALLOCSTACK 8
|
|
.endprolog
|
|
|
|
mov rax, rcx
|
|
out dx, ax
|
|
|
|
pop rax
|
|
ret
|
|
WritePortWord ENDP
|
|
|
|
;------------------------------------------------------------------------------
|
|
; void
|
|
; WritePortByte (
|
|
; unsigned char out_value // rcx
|
|
; unsigned short port_num // rdx
|
|
; )
|
|
;------------------------------------------------------------------------------
|
|
WritePortByte PROC FRAME
|
|
push rax
|
|
.ALLOCSTACK 8
|
|
.endprolog
|
|
|
|
mov rax, rcx
|
|
out dx, al
|
|
|
|
pop rax
|
|
ret
|
|
WritePortByte ENDP
|
|
|
|
;------------------------------------------------------------------------------
|
|
; unsigned int
|
|
; ReadPortDword (
|
|
; unsigned short port_num // rcx
|
|
; )
|
|
;------------------------------------------------------------------------------
|
|
ReadPortDword PROC FRAME
|
|
push rdx
|
|
.ALLOCSTACK 8
|
|
.endprolog
|
|
|
|
xor rax, rax
|
|
mov rdx, rcx
|
|
in eax, dx
|
|
|
|
pop rdx
|
|
ret
|
|
ReadPortDword ENDP
|
|
|
|
;------------------------------------------------------------------------------
|
|
; unsigned short
|
|
; ReadPortWord (
|
|
; unsigned short port_num // rcx
|
|
; )
|
|
;------------------------------------------------------------------------------
|
|
ReadPortWord PROC FRAME
|
|
push rdx
|
|
.ALLOCSTACK 8
|
|
.endprolog
|
|
|
|
xor rax, rax
|
|
mov rdx, rcx
|
|
in ax, dx
|
|
|
|
pop rdx
|
|
ret
|
|
ReadPortWord ENDP
|
|
|
|
;------------------------------------------------------------------------------
|
|
; unsigned char
|
|
; ReadPortByte (
|
|
; unsigned short port_num // rcx
|
|
; )
|
|
;------------------------------------------------------------------------------
|
|
ReadPortByte PROC FRAME
|
|
push rdx
|
|
.ALLOCSTACK 8
|
|
.endprolog
|
|
|
|
xor rax, rax
|
|
mov rdx, rcx
|
|
in al, dx
|
|
|
|
pop rdx
|
|
ret
|
|
ReadPortByte ENDP
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; void
|
|
; WriteHighCMOSByte (
|
|
; unsigned char cmos_off // rcx
|
|
; unsigned char val // rdx
|
|
; )
|
|
;------------------------------------------------------------------------------
|
|
WriteHighCMOSByte PROC FRAME
|
|
push rax
|
|
.ALLOCSTACK 8
|
|
.endprolog
|
|
|
|
mov rax, rcx
|
|
out 72h, al
|
|
mov rax, rdx
|
|
out 73h, al
|
|
|
|
pop rax
|
|
ret
|
|
WriteHighCMOSByte ENDP
|
|
;------------------------------------------------------------------------------
|
|
; void
|
|
; WriteLowCMOSByte (
|
|
; unsigned char cmos_off // rcx
|
|
; unsigned char val // rdx
|
|
; )
|
|
;------------------------------------------------------------------------------
|
|
WriteLowCMOSByte PROC FRAME
|
|
push rax
|
|
.ALLOCSTACK 8
|
|
.endprolog
|
|
|
|
mov rax, rcx
|
|
or al, 80h
|
|
out 70h, al
|
|
mov rax, rdx
|
|
out 71h, al
|
|
|
|
pop rax
|
|
ret
|
|
WriteLowCMOSByte ENDP
|
|
|
|
|
|
; @TODO: looks incorrect
|
|
;------------------------------------------------------------------------------
|
|
; void
|
|
; SendAPMSMI (
|
|
; unsigned int apm_port_value // rcx
|
|
; IN UINT64 rax_value // rdx
|
|
; )
|
|
;------------------------------------------------------------------------------
|
|
SendAPMSMI PROC FRAME
|
|
push rax
|
|
.ALLOCSTACK 8
|
|
push rdx
|
|
.ALLOCSTACK 8
|
|
.endprolog
|
|
|
|
mov rax, rcx
|
|
mov dx, 0B2h
|
|
out dx, rax
|
|
|
|
pop rdx
|
|
pop rax
|
|
ret
|
|
SendAPMSMI ENDP
|
|
|
|
;------------------------------------------------------------------------------
|
|
;This function has one argument: swsmi_msg_t structure pointer which contain SMI code and data values and 6 regs: rax, rbx, rcx, rdx, rsi, rdi:
|
|
; IN UINT64 code_data (only lower 16 bit used)
|
|
; IN/OUT UINT64 rax_value
|
|
; IN/OUT UINT64 rbx_value
|
|
; IN/OUT UINT64 rcx_value
|
|
; IN/OUT UINT64 rdx_value
|
|
; IN/OUT UINT64 rsi_value
|
|
; IN/OUT UINT64 rdi_value
|
|
;------------------------------------------------------------------------------
|
|
; void
|
|
; _swsmi (
|
|
; swsmi_msg_t*
|
|
; )
|
|
;------------------------------------------------------------------------------
|
|
_swsmi PROC
|
|
; setting up GPR (arguments) to SMI handler call
|
|
; notes:
|
|
; RAX will get partially overwritten (AX) by code_data
|
|
mov r10, rcx ; //pointer for struct into r10
|
|
xchg rax, [r10+08h] ; //rax_value (partially overwritten by code_data)
|
|
mov ax, [r10] ; //code_data
|
|
xchg rbx, [r10+10h] ; //rbx value
|
|
xchg rcx, [r10+18h] ; //rcx value
|
|
xchg rdx, [r10+20h] ; //rdx value
|
|
xchg rsi, [r10+28h] ; //rsi value
|
|
xchg rdi, [r10+30h] ; //rdi value
|
|
|
|
; Output smi_code_data split up to their designated ports, SW SMI data
|
|
; (0xB3) and SW SMI control (0xB2), respectively.
|
|
;
|
|
; Resist from outputting both at once as a single word, as some systems
|
|
; reject the request if the i/o spans more than a byte, e.g.:
|
|
; https://github.com/tianocore/edk2-platforms/blob/aa3f6fd542e99dde4206537b095f1a2201275e75/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSw.c#L314
|
|
ror ax, 8
|
|
out 0B3h, al ; SW SMI data
|
|
ror ax, 8
|
|
out 0B2h, al ; SW SMI control
|
|
|
|
; some SMI handlers return data/errorcode in GPRs, need to return this to the caller
|
|
xchg [r10+08h], rax ; //rax value
|
|
xchg [r10+10h], rbx ; //rbx value
|
|
xchg [r10+18h], rcx ; //rcx value
|
|
xchg [r10+20h], rdx ; //rdx value
|
|
xchg [r10+28h], rsi ; //rsi value
|
|
xchg [r10+30h], rdi ; //rdi value
|
|
|
|
ret
|
|
_swsmi ENDP
|
|
|
|
;------------------------------------------------------------------------------
|
|
; void
|
|
; WritePCIByte (
|
|
; unsigned int pci_reg // rcx
|
|
; unsigned short cfg_data_port // rdx
|
|
; unsigned char byte_value // r8
|
|
; )
|
|
;------------------------------------------------------------------------------
|
|
WritePCIByte PROC FRAME
|
|
push rax
|
|
.ALLOCSTACK 8
|
|
push rdx
|
|
.ALLOCSTACK 8
|
|
.endprolog
|
|
|
|
cli
|
|
mov rax, rcx ; pci_reg
|
|
mov dx, 0CF8h
|
|
out dx, rax
|
|
|
|
mov rax, r8 ; byte_value
|
|
pop rdx ; cfg_data_port
|
|
out dx, al
|
|
sti
|
|
|
|
pop rax
|
|
ret
|
|
WritePCIByte ENDP
|
|
|
|
;------------------------------------------------------------------------------
|
|
; void
|
|
; WritePCIWord (
|
|
; unsigned int pci_reg // rcx
|
|
; unsigned short cfg_data_port // rdx
|
|
; unsigned short word_value // r8
|
|
; )
|
|
;------------------------------------------------------------------------------
|
|
WritePCIWord PROC FRAME
|
|
push rax
|
|
.ALLOCSTACK 8
|
|
push rdx
|
|
.ALLOCSTACK 8
|
|
.endprolog
|
|
|
|
cli
|
|
mov rax, rcx ; pci_reg
|
|
mov dx, 0CF8h
|
|
out dx, rax
|
|
|
|
mov rax, r8 ; byte_value
|
|
pop rdx ; cfg_data_port
|
|
out dx, ax
|
|
sti
|
|
|
|
pop rax
|
|
ret
|
|
WritePCIWord ENDP
|
|
|
|
;------------------------------------------------------------------------------
|
|
; void
|
|
; WritePCIDword (
|
|
; unsigned int pci_reg // rcx
|
|
; unsigned short cfg_data_port // rdx
|
|
; unsigned int dword_value // r8
|
|
; )
|
|
;------------------------------------------------------------------------------
|
|
WritePCIDword PROC FRAME
|
|
push rax
|
|
.ALLOCSTACK 8
|
|
push rdx
|
|
.ALLOCSTACK 8
|
|
.endprolog
|
|
|
|
cli
|
|
mov rax, rcx ; pci_reg
|
|
mov dx, 0CF8h
|
|
out dx, rax
|
|
|
|
mov rax, r8 ; byte_value
|
|
pop rdx ; cfg_data_port
|
|
out dx, eax
|
|
sti
|
|
|
|
pop rax
|
|
ret
|
|
WritePCIDword ENDP
|
|
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; unsigned char
|
|
; ReadPCIByte (
|
|
; unsigned int pci_reg // rcx
|
|
; unsigned short cfg_data_port // rdx
|
|
; )
|
|
;------------------------------------------------------------------------------
|
|
ReadPCIByte PROC FRAME
|
|
push rdx
|
|
.ALLOCSTACK 8
|
|
.endprolog
|
|
|
|
cli
|
|
mov rax, rcx ; pci_reg
|
|
mov dx, 0CF8h
|
|
out dx, rax
|
|
|
|
xor rax, rax
|
|
pop rdx ; cfg_data_port
|
|
in al, dx
|
|
sti
|
|
|
|
ret
|
|
ReadPCIByte ENDP
|
|
|
|
;------------------------------------------------------------------------------
|
|
; unsigned short
|
|
; ReadPCIWord (
|
|
; unsigned int pci_reg // rcx
|
|
; unsigned short cfg_data_port // rdx
|
|
; )
|
|
;------------------------------------------------------------------------------
|
|
ReadPCIWord PROC FRAME
|
|
push rdx
|
|
.ALLOCSTACK 8
|
|
.endprolog
|
|
|
|
cli
|
|
mov rax, rcx ; pci_reg
|
|
mov dx, 0CF8h
|
|
out dx, rax
|
|
|
|
xor rax, rax
|
|
pop rdx ; cfg_data_port
|
|
in ax, dx
|
|
sti
|
|
|
|
ret
|
|
ReadPCIWord ENDP
|
|
|
|
;------------------------------------------------------------------------------
|
|
; unsigned int
|
|
; ReadPCIDword (
|
|
; unsigned int pci_reg // rcx
|
|
; unsigned short cfg_data_port // rdx
|
|
; )
|
|
;------------------------------------------------------------------------------
|
|
ReadPCIDword PROC FRAME
|
|
push rdx
|
|
.ALLOCSTACK 8
|
|
.endprolog
|
|
|
|
cli
|
|
mov rax, rcx ; pci_reg
|
|
mov dx, 0CF8h
|
|
out dx, rax
|
|
|
|
xor rax, rax
|
|
pop rdx ; cfg_data_port
|
|
in eax, dx
|
|
sti
|
|
|
|
ret
|
|
ReadPCIDword ENDP
|
|
|
|
ReadCR0 PROC
|
|
xor rax, rax
|
|
mov rax, cr0
|
|
ret
|
|
ReadCR0 ENDP
|
|
|
|
ReadCR2 PROC
|
|
xor rax, rax
|
|
mov rax, cr2
|
|
ret
|
|
ReadCR2 ENDP
|
|
|
|
ReadCR3 PROC
|
|
xor rax, rax
|
|
mov rax, cr3
|
|
ret
|
|
ReadCR3 ENDP
|
|
|
|
ReadCR4 PROC
|
|
xor rax, rax
|
|
mov rax, cr4
|
|
ret
|
|
ReadCR4 ENDP
|
|
|
|
ReadCR8 PROC
|
|
xor rax, rax
|
|
mov rax, cr8
|
|
ret
|
|
ReadCR8 ENDP
|
|
|
|
WriteCR0 PROC
|
|
mov cr0, rcx
|
|
ret
|
|
WriteCR0 ENDP
|
|
|
|
WriteCR2 PROC
|
|
mov cr2, rcx
|
|
ret
|
|
WriteCR2 ENDP
|
|
|
|
WriteCR3 PROC
|
|
mov cr3, rcx
|
|
ret
|
|
WriteCR3 ENDP
|
|
|
|
WriteCR4 PROC
|
|
mov cr4, rcx
|
|
ret
|
|
WriteCR4 ENDP
|
|
|
|
WriteCR8 PROC
|
|
mov cr8, rcx
|
|
ret
|
|
WriteCR8 ENDP
|
|
|
|
;------------------------------------------------------------------------------
|
|
; CPU_REG_TYPE
|
|
; hypercall(
|
|
; CPU_REG_TYPE rcx_val, // rcx +08h
|
|
; CPU_REG_TYPE rdx_val, // rdx +10h
|
|
; CPU_REG_TYPE r8_val, // r8 +18h
|
|
; CPU_REG_TYPE r9_val, // r9 +20h
|
|
; CPU_REG_TYPE r10_val, // on stack +28h
|
|
; CPU_REG_TYPE r11_val, // on stack +30h
|
|
; CPU_REG_TYPE rax_val, // on stack +38h
|
|
; CPU_REG_TYPE rbx_val, // on stack +40h
|
|
; CPU_REG_TYPE rdi_val, // on stack +48h
|
|
; CPU_REG_TYPE rsi_val, // on stack +50h
|
|
; CPU_REG_TYPE xmm_buffer, // on stack +58h
|
|
; CPU_REG_TYPE hypercall_page // on stack +60h
|
|
; )
|
|
;------------------------------------------------------------------------------
|
|
|
|
hypercall PROC
|
|
push rsi
|
|
push rdi
|
|
push rbx
|
|
mov r11, qword ptr [rsp + 18h + 58h]
|
|
test r11, r11
|
|
jz hypercall_skip_xmm
|
|
pinsrq xmm0, qword ptr [r11 + 000h], 00h
|
|
pinsrq xmm0, qword ptr [r11 + 008h], 01h
|
|
pinsrq xmm1, qword ptr [r11 + 010h], 00h
|
|
pinsrq xmm1, qword ptr [r11 + 018h], 01h
|
|
pinsrq xmm2, qword ptr [r11 + 020h], 00h
|
|
pinsrq xmm2, qword ptr [r11 + 028h], 01h
|
|
pinsrq xmm3, qword ptr [r11 + 030h], 00h
|
|
pinsrq xmm3, qword ptr [r11 + 038h], 01h
|
|
pinsrq xmm4, qword ptr [r11 + 040h], 00h
|
|
pinsrq xmm4, qword ptr [r11 + 048h], 01h
|
|
pinsrq xmm5, qword ptr [r11 + 050h], 00h
|
|
pinsrq xmm5, qword ptr [r11 + 058h], 01h
|
|
hypercall_skip_xmm:
|
|
mov r10, qword ptr [rsp + 18h + 28h]
|
|
mov r11, qword ptr [rsp + 18h + 30h]
|
|
mov rax, qword ptr [rsp + 18h + 38h]
|
|
mov rbx, qword ptr [rsp + 18h + 40h]
|
|
mov rdi, qword ptr [rsp + 18h + 48h]
|
|
mov rsi, qword ptr [rsp + 18h + 50h]
|
|
call qword ptr [rsp + 18h + 60h]
|
|
pop rbx
|
|
pop rdi
|
|
pop rsi
|
|
ret
|
|
hypercall ENDP
|
|
|
|
;------------------------------------------------------------------------------
|
|
; CPU_REG_TYPE hypercall_page ( )
|
|
;------------------------------------------------------------------------------
|
|
|
|
hypercall_page PROC
|
|
vmcall
|
|
ret
|
|
hypercall_page ENDP
|
|
|
|
END
|