Files
2023-06-28 10:52:19 -07:00

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