Skip to content

Commit

Permalink
multiboot2: Implement TXT slaunch support
Browse files Browse the repository at this point in the history
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.

Signed-off-by: Sergii Dmytruk <[email protected]>
Signed-off-by: Michał Żygowski <[email protected]>
Signed-off-by: Tomasz Żyjewski <[email protected]>
Signed-off-by: Krystian Hebel <[email protected]>
  • Loading branch information
miczyg1 authored and krystian-hebel committed Jan 31, 2024
1 parent ba801cc commit 66004ae
Show file tree
Hide file tree
Showing 4 changed files with 219 additions and 9 deletions.
23 changes: 22 additions & 1 deletion grub-core/loader/multiboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -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+");
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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
Expand Down
104 changes: 96 additions & 8 deletions grub-core/loader/multiboot_elfxx.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,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)
Expand All @@ -60,6 +62,9 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
grub_uint32_t load_offset = 0, load_size;
int i;
void *source = NULL;
struct grub_slaunch_params *slparams = grub_slaunch_params();
grub_size_t total_size;
grub_uint32_t mle_hdr_offset;

if (ehdr->e_ident[EI_MAG0] != ELFMAG0
|| ehdr->e_ident[EI_MAG1] != ELFMAG1
Expand Down Expand Up @@ -106,25 +111,87 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
(long) mld->align, mld->preference, load_size,
mld->avoid_efi_boot_services);

if (load_size > mld->max_addr || mld->min_addr > mld->max_addr - load_size)
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 the binary together with page tables to make one
* contiguous block for MLE. We have to align up to PMR (2MB).
*/
total_size = ALIGN_UP(load_size, GRUB_TXT_PMR_ALIGN);

slparams->mle_size = total_size;

slparams->mle_ptab_size = grub_txt_get_mle_ptab_size (total_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
{
total_size = load_size;
slparams->mle_ptab_size = 0;
}

if (total_size > mld->max_addr || mld->min_addr > mld->max_addr - total_size)
return grub_error (GRUB_ERR_BAD_OS, "invalid min/max address and/or load size");

err = grub_relocator_alloc_chunk_align_safe (GRUB_MULTIBOOT (relocator), &ch,
mld->min_addr, mld->max_addr,
load_size, mld->align ? mld->align : 1,
mld->min_addr, mld->max_addr - total_size,
total_size, mld->align ? mld->align : 1,
mld->preference, mld->avoid_efi_boot_services);

if (err)
{
grub_dprintf ("multiboot_loader", "Cannot allocate memory for OS image\n");
return err;
}
{
grub_dprintf ("multiboot_loader", "Cannot allocate memory for OS image\n");
return err;
}

mld->load_base_addr = get_physical_target_address (ch);
source = get_virtual_current_address (ch);
grub_memset (get_virtual_current_address (ch), 0, total_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,
Expand Down Expand Up @@ -180,6 +247,27 @@ 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)
{
if ( !grub_memcmp ((void *)((grub_addr_t) source + mle_hdr_offset), 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);
}

for (i = 0; i < ehdr->e_phnum; i++)
if (phdr(i)->p_vaddr <= ehdr->e_entry
&& phdr(i)->p_vaddr + phdr(i)->p_memsz > ehdr->e_entry)
Expand Down
99 changes: 99 additions & 0 deletions grub-core/loader/multiboot_mbi2.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -722,7 +757,12 @@ grub_multiboot2_make_mbi (grub_uint32_t *target, grub_uint32_t *size)

ptrorig = get_virtual_current_address (ch);
#if defined (__i386__) || defined (__x86_64__)
struct grub_slaunch_params *slparams = grub_slaunch_params();

*target = get_physical_target_address (ch);
/* Save MBI pointer in the TXT heap area */
if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
slparams->boot_params_addr = *target;
#elif defined (__mips)
*target = get_physical_target_address (ch) | 0x80000000;
#else
Expand Down Expand Up @@ -1128,3 +1168,62 @@ 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->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;
}
2 changes: 2 additions & 0 deletions include/grub/multiboot2.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 66004ae

Please sign in to comment.