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

Reply via email to