summaryrefslogtreecommitdiff
path: root/src/security/intel/txt/getsec_enteraccs.S
diff options
context:
space:
mode:
Diffstat (limited to 'src/security/intel/txt/getsec_enteraccs.S')
-rw-r--r--src/security/intel/txt/getsec_enteraccs.S319
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