From: Ross Philipson <ross.philip...@oracle.com> The purpose of the stub is allowing DLME to call back into GRUB to initiate a dynamic launch. GRUB essentially starts DLME twice: first without and then with DRTM. This allows DLME to properly initialize itself using EFI services before DRTM is initiated.
To avoid duplication legacy boot is performed through the stub as well, but GRUB calls it directly and DLME is started only once. Signed-off-by: Ross Philipson <ross.philip...@oracle.com> Signed-off-by: Sergii Dmytruk <sergii.dmyt...@3mdeb.com> --- grub-core/loader/slaunch/x86_dlstub.c | 93 ++++++++++++++++++++ grub-core/loader/slaunch/x86_dltrampoline.S | 94 +++++++++++++++++++++ 2 files changed, 187 insertions(+) create mode 100644 grub-core/loader/slaunch/x86_dlstub.c create mode 100644 grub-core/loader/slaunch/x86_dltrampoline.S diff --git a/grub-core/loader/slaunch/x86_dlstub.c b/grub-core/loader/slaunch/x86_dlstub.c new file mode 100644 index 000000000..d3c28645e --- /dev/null +++ b/grub-core/loader/slaunch/x86_dlstub.c @@ -0,0 +1,93 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2024, Oracle and/or its affiliates. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/loader.h> +#include <grub/normal.h> +#include <grub/err.h> +#include <grub/misc.h> +#include <grub/types.h> +#include <grub/dl.h> +#include <grub/slr_table.h> +#include <grub/slaunch.h> +#include <grub/cpu/relocator.h> +#include <grub/i386/msr.h> +#include <grub/i386/mmio.h> +#include <grub/i386/txt.h> + +GRUB_MOD_LICENSE ("GPLv3+"); + +extern void dl_trampoline(grub_uint32_t dce_base, grub_uint32_t dce_size); + +void dl_entry (grub_uint64_t dl_ctx) +{ + struct grub_slr_bl_context *bl_ctx = (struct grub_slr_bl_context *)(grub_addr_t)dl_ctx; + struct grub_slaunch_params *slparams = (struct grub_slaunch_params *)(grub_addr_t)bl_ctx->context; + struct grub_relocator32_state state = {0}; + grub_err_t err; + + state.edi = slparams->platform_type; + + if (slparams->platform_type == SLP_INTEL_TXT) + { + if (slparams->boot_type == GRUB_SL_BOOT_TYPE_EFI) + grub_update_slrt_policy (slparams); + + err = grub_set_mtrrs_for_acmod ((void *)(grub_addr_t)slparams->dce_base); + if (err) + { + grub_error (GRUB_ERR_BAD_DEVICE, N_("setting MTRRs for TXT SINIT failed")); + return; + } + + err = grub_txt_prepare_cpu (); + if ( err ) + { + grub_error (GRUB_ERR_BAD_DEVICE, N_("prepare CPU for TXT SENTER failed")); + return; + } + } + else + { + grub_error (GRUB_ERR_BUG, N_("unknown dynamic launch platform: %d"), slparams->platform_type); + return; + } + + if (!(grub_rdmsr (GRUB_MSR_X86_APICBASE) & GRUB_MSR_X86_APICBASE_BSP)) + { + grub_error (GRUB_ERR_BAD_DEVICE, N_("x86 dynamic launch event must be performed on the BSP")); + return; + } + + if (slparams->boot_type == GRUB_SL_BOOT_TYPE_LINUX) + { + /* Configure relocator GETSEC[SENTER] call. */ + state.eax = GRUB_SMX_LEAF_SENTER; + state.ebx = slparams->dce_base; + state.ecx = slparams->dce_size; + state.edx = 0; + grub_relocator32_boot (slparams->relocator, state, 0); + } + else if (slparams->boot_type == GRUB_SL_BOOT_TYPE_EFI) + { + dl_trampoline (slparams->dce_base, slparams->dce_size); + } + else + { + grub_error (GRUB_ERR_BUG, N_("unknown dynamic launch boot type: %d"), slparams->boot_type); + } +} diff --git a/grub-core/loader/slaunch/x86_dltrampoline.S b/grub-core/loader/slaunch/x86_dltrampoline.S new file mode 100644 index 000000000..461e14271 --- /dev/null +++ b/grub-core/loader/slaunch/x86_dltrampoline.S @@ -0,0 +1,94 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2024, Oracle and/or its affiliates. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <grub/symbol.h> + +#define GRUB_SMX_LEAF_SENTER 4 +#define CS_SEL32 0x0008 +#define DS_SEL 0x0010 + +#define CR0_PE 0x00000001 +#define CR0_MP 0x00000002 +#define CR0_TS 0x00000008 +#define CR0_NE 0x00000020 + + .file "dltrampoline.S" + .text + + .code64 + .globl dl_entry_trampoline +dl_entry_trampoline: + /* %edi should contain dl_context pointer */ + call EXT_C(dl_entry) + ud2 + + .globl dl_trampoline +dl_trampoline: + cli + leaq dl_gdt_base(%rip), %rax + leaq dl_gdt(%rip), %rbx + movl %ebx, (%eax) + lgdt dl_gdtr(%rip) + + /* Setup target to ret to compat mode */ + leal 1f(%rip), %ecx + pushq $CS_SEL32 + pushq %rcx + lretq + + .code32 +1: /* Now in IA-32e compatibility mode load data segments and do senter */ + movw $DS_SEL, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %ss + movw %ax, %fs + movw %ax, %gs + + movl $GRUB_SMX_LEAF_SENTER, %eax + movl %edi, %ebx + movl %esi, %ecx + xorl %edx, %edx + getsec + + .align 8 +dl_gdt: + /* Null Segment */ + .quad 0 + /* 32b Code Segment */ + .word 0xffff /* Limit 1 */ + .word 0x0000 /* Base 1 */ + .byte 0x00 /* Base 2 */ + .byte 0x9b /* P=1 DPL=0 S=1 Type=0010 C=0 W=1 A=1 */ + .byte 0xcf /* G=1 D=1 L=0 AVL=0 Limit 2 */ + .byte 0x00 /* Base 3 */ + /* Data Segment, can be used both in 32b and 64b */ + .word 0xffff /* Limit 1 */ + .word 0x0000 /* Base 1 */ + .byte 0x00 /* Base 2 */ + .byte 0x93 /* P=1 DPL=0 S=1 Type=0010 C=0 W=1 A=1 */ + .byte 0xcf /* G=1 D=1 L=0 AVL=0 Limit 2 */ + .byte 0x00 /* Base 3 */ + + .word 0 +dl_gdtr: + .word 23 /* Limit */ +dl_gdt_base: + .long 0 /* Base */ + .long 0 -- 2.49.0 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel