diff options
Diffstat (limited to 'src/security/intel/txt/getsec_enteraccs.S')
-rw-r--r-- | src/security/intel/txt/getsec_enteraccs.S | 319 |
1 files changed, 319 insertions, 0 deletions
diff --git a/src/security/intel/txt/getsec_enteraccs.S b/src/security/intel/txt/getsec_enteraccs.S new file mode 100644 index 0000000000..0dd5237e7a --- /dev/null +++ b/src/security/intel/txt/getsec_enteraccs.S @@ -0,0 +1,319 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <cpu/x86/mtrr.h> +#include <cpu/x86/cr.h> +#include <cpu/x86/msr.h> + +#define MTRR_HIGH_MASK $((1 << (CONFIG_CPU_ADDR_BITS - 32)) - 1) + +.macro PUSH_MSR x + movl $(\x), %ecx + rdmsr + push %eax + push %edx +.endm + +.macro POP_MSR x + movl $(\x), %ecx + pop %edx + pop %eax + wrmsr +.endm + +.macro CLEAR_MSR x + movl $(\x), %ecx + xorl %edx, %edx + xorl %eax, %eax + wrmsr +.endm + +/* Variable MTRR index is passed through %ebx */ +.macro PUSH_VAR_MTRR + movl %ebx, %ecx + shll %ecx + addl MTRR_PHYS_BASE(0), %ecx + rdmsr + push %eax + push %edx + incl %ecx /* MTRR_PHYS_MASK */ + rdmsr + push %eax + push %edx +.endm + +.macro POP_VAR_MTRR + movl %ebx, %ecx + shll %ecx + addl MTRR_PHYS_MASK(0), %ecx + pop %edx + pop %eax + wrmsr + decl %ecx /* MTRR_PHYS_BASE */ + pop %edx + pop %eax + wrmsr +.endm + +.macro CLEAR_VAR_MTRR + movl %ebx, %ecx + shll %ecx + addl MTRR_PHYS_BASE(0), %ecx + xorl %edx, %edx + xorl %eax, %eax + wrmsr + incl %ecx /* MTRR_PHYS_MASK */ + xorl %edx, %edx + xorl %eax, %eax + wrmsr +.endm + +.align 4 +.text + +/* + * See "SAFER MODE EXTENSIONS REFERENCE." + * Chapter "GETSEC[ENTERACCS] - Execute Authenticated Chipset Code" for reference. + * Intel 64 and IA-32 Architectures Software Developer Manuals Vol 2D + * + * void getsec_enteraccs(uint32_t esi, + * uint32_t acm_base, + * uint32_t acm_size); + */ +.global getsec_enteraccs +getsec_enteraccs: + + /* Backup current register state */ + pushl %ebp + movl %esp, %ebp + + pushal + + movl %cr0, %eax + pushl %eax + movl %cr4, %eax + pushl %eax + + /* Pushed 10 32bit registers */ + + /* Reserve space on stack for GDT */ + subl $8, %esp + + PUSH_MSR IA32_MISC_ENABLE + PUSH_MSR MTRR_FIX_64K_00000 + PUSH_MSR MTRR_FIX_16K_80000 + PUSH_MSR MTRR_FIX_16K_A0000 + PUSH_MSR MTRR_FIX_4K_C0000 + PUSH_MSR MTRR_FIX_4K_C8000 + PUSH_MSR MTRR_FIX_4K_D0000 + PUSH_MSR MTRR_FIX_4K_D8000 + PUSH_MSR MTRR_FIX_4K_E0000 + PUSH_MSR MTRR_FIX_4K_F0000 + PUSH_MSR MTRR_FIX_4K_F8000 + + /* Push variable MTRRs in ascending order */ + xorl %ebx, %ebx + jmp cond_push_var_mtrrs + +body_push_var_mtrrs: + + PUSH_VAR_MTRR + incl %ebx + +cond_push_var_mtrrs: + + movl $(MTRR_CAP_MSR), %ecx + rdmsr + andl $(0xff), %eax + cmp %ebx, %eax + jge body_push_var_mtrrs + + /* + * Disable cache. + * Chapter 2.2.4.3 + * Intel TXT Software Development Guide (Document: 315168-015) + */ + movl %cr0, %eax + orl $(CR0_CD | CR0_NW), %eax + movl %eax, %cr0 + + /* Disable fixed MTRRs */ + movl $(MTRR_DEF_TYPE_MSR), %ecx + rdmsr + andl $(~MTRR_DEF_TYPE_FIX_EN), %eax + wrmsr + + /* + * Clear fixed MTRRs. + * Chapter 2.2.5.1 + * Intel TXT Software Development Guide (Document: 315168-015) + */ + CLEAR_MSR MTRR_FIX_64K_00000 + CLEAR_MSR MTRR_FIX_16K_80000 + CLEAR_MSR MTRR_FIX_16K_A0000 + CLEAR_MSR MTRR_FIX_4K_C0000 + CLEAR_MSR MTRR_FIX_4K_C8000 + CLEAR_MSR MTRR_FIX_4K_D0000 + CLEAR_MSR MTRR_FIX_4K_D8000 + CLEAR_MSR MTRR_FIX_4K_E0000 + CLEAR_MSR MTRR_FIX_4K_F0000 + CLEAR_MSR MTRR_FIX_4K_F8000 + + /* + * Clear variable MTRRs + * Chapter 2.2.5.1 + * Intel TXT Software Development Guide (Document: 315168-015) + */ + movl $(MTRR_CAP_MSR), %ecx + rdmsr + andl $(0xff), %eax + movl %eax, %ebx + +body_clear_var_mtrrs: + + CLEAR_VAR_MTRR + decl %ebx + jnz body_clear_var_mtrrs + + /* + * Setup BIOS ACM as WB + * Chapter A.1.1 + * Intel TXT Software Development Guide (Document: 315168-015) + */ + movl $(MTRR_PHYS_BASE(0)), %ecx + movl 12(%ebp), %eax /* %eax = acmbase */ + orl $(6), %eax /* MTRR_TYPE_WB */ + movl $0, %edx + wrmsr + + /* Round acmsize to next power of two. Required for MTRR programming. */ + movl $1, %ebx + movl 16(%ebp), %ecx /* %ebx = acmsize */ + dec %ecx + bsr %ecx, %ecx /* find MSB */ + inc %ecx + shl %cl, %ebx + movl $(MTRR_PHYS_MASK(0)), %ecx + xorl %eax, %eax + subl %ebx, %eax /* %eax = 4GIB - log2_ceil(ACM SIZE) */ + orl $((1 << 11)), %eax /* MTRR_PHYS_MASK_VALID */ + movl MTRR_HIGH_MASK, %edx + wrmsr + + /* Enable cache - GPF# if not done */ + movl %cr0, %eax + andl $(~(CR0_CD | CR0_NW)), %eax + movl %eax, %cr0 + + /* Enable Numeric error - GPE# if not done */ + movl %cr0, %eax + orl $(CR0_NE), %eax + movl %eax, %cr0 + + /* Enable SMX and FXSTORE - for getsec */ + movl %cr4, %eax + orl $(CR4_SMXE | CR4_OSFXSR), %eax + movl %eax, %cr4 + + /* + * Save GDT + * Chapter A.1.2 + * Intel TXT Software Development Guide (Document: 315168-015) + */ + sgdt -48(%ebp) + + /* Backup stack pointer */ + movd %esp, %xmm0 + movd %ebp, %xmm1 + + /* + * Get function arguments. + * It's important to pass the exact ACM size as it's used by getsec to verify + * the integrity of ACM. Unlike the size for MTRR programming, which needs to + * be power of two. + * + * The following assembly code is based on tboot's tboot/include/txt/smx.h. + */ + movl 8(%ebp), %esi /* flags */ + movl 12(%ebp), %ebx /* acm_base */ + movl 16(%ebp), %ecx /* acm_size */ + + movl $0, %edx /* reserved, must be zero */ + movl $0, %edi /* must be zero */ + movl $2, %eax /* GetSec[ENTERACCS] */ + + getsec + + /* Restore stack pointer */ + movd %xmm0, %esp + movd %xmm1, %ebp + + /* Reload GDT */ + lgdt -48(%ebp) + + /* Set cs */ + ljmp $0x10, $1f +1: + /* Fix segment registers */ + movl $0x18, %eax + movl %eax, %ds + movl %eax, %es + movl %eax, %ss + movl %eax, %fs + movl %eax, %gs + + /* Disable cache */ + movl %cr0, %eax + orl $(CR0_CD | CR0_NW), %eax + movl %eax, %cr0 + + /* Restore MTTRs */ + + /* Pop variable MTRRs in descending order */ + movl $(MTRR_CAP_MSR), %ecx + rdmsr + andl $(0xff), %eax + movl %eax, %ebx + +body_pop_var_mtrrs: + + POP_VAR_MTRR + decl %ebx + jnz body_pop_var_mtrrs + + POP_MSR MTRR_FIX_4K_F8000 + POP_MSR MTRR_FIX_4K_F0000 + POP_MSR MTRR_FIX_4K_E0000 + POP_MSR MTRR_FIX_4K_D8000 + POP_MSR MTRR_FIX_4K_D0000 + POP_MSR MTRR_FIX_4K_C8000 + POP_MSR MTRR_FIX_4K_C0000 + POP_MSR MTRR_FIX_16K_A0000 + POP_MSR MTRR_FIX_16K_80000 + POP_MSR MTRR_FIX_64K_00000 + POP_MSR IA32_MISC_ENABLE + + /* Enable fixed MTRRs */ + movl $(MTRR_DEF_TYPE_MSR), %ecx + rdmsr + orl $(MTRR_DEF_TYPE_FIX_EN), %eax + wrmsr + + /* Enable cache */ + movl %cr0, %eax + andl $(~(CR0_CD | CR0_NW)), %eax + movl %eax, %cr0 + + /* Pop GDT */ + addl $8, %esp + + popl %eax + movl %eax, %cr4 + popl %eax + movl %eax, %cr0 + + popal + + movl %ebp, %esp + popl %ebp + + ret |