grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 20/24] multiboot2: Implement TXT slaunch support


From: Sergii Dmytruk
Subject: [PATCH 20/24] multiboot2: Implement TXT slaunch support
Date: Mon, 26 Aug 2024 15:44:30 +0300

From: Michał Żygowski <michal.zygowski@3mdeb.com>

The code makes sure that MBI entry goes first in DRTM, so the payload
can measure it first on launch.

SLRT table is allocated on the heap first, size for it is reserved
inside TXT heap by TXT code and data is later copied into its final
place.

To avoid mismatch between OS SINIT data MLE size and MLE size from
MLE header, take the mle_size from MLE header as is (without aligning
it).

Signed-off-by: Michał Żygowski <michal.zygowski@3mdeb.com>
Signed-off-by: Tomasz Żyjewski <tomasz.zyjewski@3mdeb.com>
Signed-off-by: Krystian Hebel <krystian.hebel@3mdeb.com>
Signed-off-by: Sergii Dmytruk <sergii.dmytruk@3mdeb.com>
---
 grub-core/loader/multiboot.c       | 23 ++++++-
 grub-core/loader/multiboot_elfxx.c | 88 ++++++++++++++++++++++++++-
 grub-core/loader/multiboot_mbi2.c  | 96 ++++++++++++++++++++++++++++++
 include/grub/multiboot2.h          |  2 +
 4 files changed, 207 insertions(+), 2 deletions(-)

diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c
index 8288a1f49..bd2de587f 100644
--- a/grub-core/loader/multiboot.c
+++ b/grub-core/loader/multiboot.c
@@ -52,6 +52,7 @@
 #include <grub/i18n.h>
 #if defined (__i386__) || defined (__x86_64__)
 #include <grub/i386/slaunch.h>
+#include <grub/i386/txt.h>
 #endif
 
 GRUB_MOD_LICENSE ("GPLv3+");
@@ -164,7 +165,17 @@ efi_boot (struct grub_relocator *rel __attribute__ 
((unused)),
 static void
 normal_boot (struct grub_relocator *rel, struct grub_relocator32_state state)
 {
-  state.edi = SLP_NONE;
+  struct grub_slaunch_params *slparams = grub_slaunch_params();
+  state.edi = grub_slaunch_platform_type ();
+
+  if (state.edi == SLP_INTEL_TXT)
+    {
+      /* 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 (rel, state, 0);
 }
@@ -194,6 +205,16 @@ grub_multiboot_boot (void)
   if (err)
     return err;
 
+#ifdef GRUB_USE_MULTIBOOT2
+  if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
+    {
+      err = grub_multiboot2_prepare_slaunch_txt (state.MULTIBOOT_MBI_REGISTER,
+                                                 mbi_size);
+      if (err)
+        return err;
+    }
+#endif
+
   if (grub_efi_is_finished)
     normal_boot (GRUB_MULTIBOOT (relocator), state);
   else
diff --git a/grub-core/loader/multiboot_elfxx.c 
b/grub-core/loader/multiboot_elfxx.c
index 1edad0594..6bf3010fb 100644
--- a/grub-core/loader/multiboot_elfxx.c
+++ b/grub-core/loader/multiboot_elfxx.c
@@ -44,6 +44,8 @@
 #error "I'm confused"
 #endif
 
+#include <grub/i386/slaunch.h>
+#include <grub/i386/txt.h>
 #include <grub/i386/relocator.h>
 
 #define CONCAT(a,b)    CONCAT_(a, b)
@@ -73,6 +75,9 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
   grub_off_t phlimit;
   unsigned int i;
   void *source = NULL;
+  struct grub_slaunch_params *slparams = grub_slaunch_params();
+  grub_uint32_t mle_hdr_offset;
+  struct grub_txt_mle_header *mle_hdr;
 
   if (ehdr->e_ident[EI_MAG0] != ELFMAG0
       || ehdr->e_ident[EI_MAG1] != ELFMAG1
@@ -127,6 +132,28 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
     {
       load_size = highest_load - mld->link_base_addr;
 
+      if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
+        {
+#ifndef GRUB_USE_MULTIBOOT2
+          return grub_error (GRUB_ERR_BAD_OS, "Only multiboot2 supported for 
slaunch");
+#else
+          /*
+           * We allocate the binary together with the page tables to make one
+           * contiguous block for MLE.
+           */
+          slparams->mle_ptab_size = grub_txt_get_mle_ptab_size (load_size);
+          slparams->mle_ptab_size = ALIGN_UP (slparams->mle_ptab_size, 
GRUB_TXT_PMR_ALIGN);
+
+          /* Do not go below GRUB_TXT_PMR_ALIGN. */
+          if (mld->align < GRUB_TXT_PMR_ALIGN)
+            mld->align = GRUB_TXT_PMR_ALIGN;
+#endif
+        }
+      else
+        {
+          slparams->mle_ptab_size = 0;
+        }
+
       grub_dprintf ("multiboot_loader", "align=0x%lx, preference=0x%x, "
                    "load_size=0x%x, avoid_efi_boot_services=%d\n",
                    (long) mld->align, mld->preference, load_size,
@@ -148,9 +175,44 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
 
       mld->load_base_addr = get_physical_target_address (ch);
       source = get_virtual_current_address (ch);
+      grub_memset (get_virtual_current_address (ch), 0, load_size);
+      grub_dprintf ("multiboot_loader", "load_base_addr=0x%lx, source=0x%lx\n",
+                    (long) mld->load_base_addr, (long) source);
+
+      if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
+        {
+#ifndef GRUB_USE_MULTIBOOT2
+          return grub_error (GRUB_ERR_BAD_OS, "Only multiboot2 supported for 
slaunch");
+#else
+          slparams->mle_start = mld->load_base_addr;
+          slparams->mle_mem = source;
+
+          err = grub_relocator_alloc_chunk_align_safe (GRUB_MULTIBOOT 
(relocator), &ch,
+                                                       
GRUB_MEMORY_MACHINE_UPPER_START,
+                                                       mld->load_base_addr - 
slparams->mle_ptab_size,
+                                                       
slparams->mle_ptab_size, GRUB_TXT_PMR_ALIGN,
+                                                       
GRUB_RELOCATOR_PREFERENCE_NONE, 1);
+          if (err)
+            {
+              grub_dprintf ("multiboot_loader", "Cannot allocate memory for 
MLE page tables\n");
+              return err;
+            }
+
+          slparams->mle_ptab_mem = get_virtual_current_address (ch);
+          slparams->mle_ptab_target = (grub_uint64_t) 
get_physical_target_address (ch);
+          grub_dprintf ("multiboot_loader", "mle_ptab_mem = %p, 
mle_ptab_target = %lx, mle_ptab_size = %x\n",
+                        slparams->mle_ptab_mem, (unsigned long) 
slparams->mle_ptab_target,
+                        (unsigned) slparams->mle_ptab_size);
+#endif
+        }
     }
   else
-    mld->load_base_addr = mld->link_base_addr;
+    {
+      mld->load_base_addr = mld->link_base_addr;
+      /* TODO: support non-relocatable */
+      if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
+        return grub_error (GRUB_ERR_BAD_OS, "Non-relocatable ELF not supported 
with slaunch");
+    }
 
   grub_dprintf ("multiboot_loader", "relocatable=%d, link_base_addr=0x%x, "
                "load_base_addr=0x%x\n", mld->relocatable,
@@ -213,6 +275,30 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
         }
     }
 
+  if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
+    {
+      slparams->mle_header_offset = 0xffffffff;
+
+      /* TODO: decide on universal way of conveying location of MLE header */
+      for (mle_hdr_offset = 0;  mle_hdr_offset < 0x1000; mle_hdr_offset += 16)
+        {
+          mle_hdr = (struct grub_txt_mle_header *)((grub_addr_t)source + 
mle_hdr_offset);
+          if ( !grub_memcmp ((void *)mle_hdr->uuid, GRUB_TXT_MLE_UUID, 16) )
+            {
+              slparams->mle_header_offset = mle_hdr_offset;
+              break;
+            }
+        }
+
+      if (slparams->mle_header_offset == 0xffffffff)
+        return grub_error (GRUB_ERR_BAD_ARGUMENT, "MLE header not found");
+
+      grub_dprintf ("slaunch", "slparams->mle_header_offset: 0x%08x\n",
+                    slparams->mle_header_offset);
+
+      slparams->mle_size = mle_hdr->mle_end - mle_hdr->mle_start;
+    }
+
   for (i = 0; i < phnum; i++)
     if (phdr(i)->p_vaddr <= ehdr->e_entry
        && phdr(i)->p_vaddr + phdr(i)->p_memsz > ehdr->e_entry)
diff --git a/grub-core/loader/multiboot_mbi2.c 
b/grub-core/loader/multiboot_mbi2.c
index 1945b3ac6..40b859fb5 100644
--- a/grub-core/loader/multiboot_mbi2.c
+++ b/grub-core/loader/multiboot_mbi2.c
@@ -36,6 +36,10 @@
 #include <grub/i18n.h>
 #include <grub/net.h>
 #include <grub/lib/cmdline.h>
+#include <grub/i386/memory.h>
+#include <grub/i386/slaunch.h>
+#include <grub/i386/txt.h>
+#include <grub/slr_table.h>
 
 #if defined (GRUB_MACHINE_EFI)
 #include <grub/efi/efi.h>
@@ -277,6 +281,9 @@ grub_multiboot2_load (grub_file_t file, const char 
*filename)
 
   if (addr_tag)
     {
+      if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
+        return grub_error (GRUB_ERR_BAD_OS, "Slaunch not supported with 
multiboot addr tag");
+
       grub_uint64_t load_addr = (addr_tag->load_addr + 1)
        ? addr_tag->load_addr : (addr_tag->header_addr
                                 - ((char *) header - (char *) mld.buffer));
@@ -390,6 +397,34 @@ grub_multiboot2_load (grub_file_t file, const char 
*filename)
     err = grub_multiboot2_set_console (GRUB_MULTIBOOT2_CONSOLE_EGA_TEXT,
                                       accepted_consoles,
                                       0, 0, 0, console_required);
+
+  if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
+    {
+      grub_relocator_chunk_t ch;
+      struct grub_slaunch_params *slparams = grub_slaunch_params();
+
+      if (grub_relocator_alloc_chunk_align_safe (grub_multiboot2_relocator, 
&ch, 0x1000000,
+                                                 UP_TO_TOP32 
(GRUB_SLAUNCH_TPM_EVT_LOG_SIZE),
+                                                 
GRUB_SLAUNCH_TPM_EVT_LOG_SIZE, GRUB_PAGE_SIZE,
+                                                 
GRUB_RELOCATOR_PREFERENCE_HIGH, 1))
+        {
+          grub_free (mld.buffer);
+          return grub_error (GRUB_ERR_OUT_OF_MEMORY, "Could not allocate TPM 
event log area");
+        }
+
+      slparams->tpm_evt_log_base = get_physical_target_address (ch);
+      slparams->tpm_evt_log_size = GRUB_SLAUNCH_TPM_EVT_LOG_SIZE;
+
+      grub_txt_init_tpm_event_log(get_virtual_current_address (ch),
+                                  slparams->tpm_evt_log_size);
+
+      grub_dprintf ("multiboot_loader", "tpm_evt_log_base = %lx, 
tpm_evt_log_size = %x\n",
+                    (unsigned long) slparams->tpm_evt_log_base,
+                    (unsigned) slparams->tpm_evt_log_size);
+
+      grub_txt_setup_mle_ptab (slparams);
+    }
+
   return err;
 }
 
@@ -1128,3 +1163,64 @@ grub_multiboot2_set_bootdev (void)
 
   bootdev_set = 1;
 }
+
+static void
+add_multiboot2_slrt_policy_entries (void)
+{
+  unsigned i;
+  struct module *cur;
+
+  for (i = 0, cur = modules; i < modcnt; i++, cur = cur->next)
+    {
+      grub_slaunch_add_slrt_policy_entry (17,
+                                          GRUB_SLR_ET_MULTIBOOT2_MODULE,
+                                          /*flags=*/0,
+                                          cur->start,
+                                          cur->size,
+                                          "Measured MB2 module");
+    }
+}
+
+grub_err_t
+grub_multiboot2_prepare_slaunch_txt (grub_uint32_t mbi_target,
+                                     grub_uint32_t mbi_size)
+{
+  grub_err_t err;
+  struct grub_slaunch_params *slparams = grub_slaunch_params ();
+
+  slparams->boot_params_addr = mbi_target;
+
+  slparams->slr_table_base = GRUB_SLAUNCH_STORE_IN_OS2MLE;
+  slparams->slr_table_size = GRUB_PAGE_SIZE;
+
+  slparams->slr_table_mem = grub_zalloc (slparams->slr_table_size);
+  if (slparams->slr_table_mem == NULL)
+    return GRUB_ERR_OUT_OF_MEMORY;
+
+  err = grub_txt_boot_prepare (slparams);
+  if (err != GRUB_ERR_NONE)
+    {
+      grub_printf ("TXT boot preparation failed");
+      return err;
+    }
+
+  grub_slaunch_add_slrt_policy_entry (18,
+                                      GRUB_SLR_ET_MULTIBOOT2_INFO,
+                                      /*flags=*/0,
+                                      mbi_target,
+                                      mbi_size,
+                                      "Measured MB2 information");
+  grub_slaunch_add_slrt_policy_entries ();
+  grub_txt_add_slrt_policy_entries ();
+  add_multiboot2_slrt_policy_entries ();
+  grub_slaunch_finish_slr_table ();
+
+  grub_dprintf ("multiboot_loader", "slr_table_base = %lx, slr_table_size = 
%x\n",
+                (unsigned long) slparams->slr_table_base,
+                (unsigned) slparams->slr_table_size);
+  grub_memcpy ((void *)(grub_addr_t) slparams->slr_table_base,
+               slparams->slr_table_mem,
+               slparams->slr_table_size);
+
+  return GRUB_ERR_NONE;
+}
diff --git a/include/grub/multiboot2.h b/include/grub/multiboot2.h
index 3417a1447..2e843d24e 100644
--- a/include/grub/multiboot2.h
+++ b/include/grub/multiboot2.h
@@ -43,6 +43,8 @@ void grub_multiboot2_set_bootdev (void);
 void
 grub_multiboot2_add_elfsyms (grub_size_t num, grub_size_t entsize,
                            unsigned shndx, void *data);
+grub_err_t grub_multiboot2_prepare_slaunch_txt (grub_uint32_t mbi_target,
+                                                grub_uint32_t mbi_size);
 
 grub_uint32_t grub_multiboot2_get_mmap_count (void);
 grub_err_t grub_multiboot2_set_video_mode (void);
-- 
2.46.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]