From 6c173bd84bc980ebc7b771853c159d9bce8256b3 Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Mon, 11 Nov 2024 20:54:45 +0200 Subject: [PATCH 01/26] loader/slaunch/psp.c: don't cause use of __udivmoddi4() Just use grub_divmod64() explicitly like all other code does. Signed-off-by: Sergii Dmytruk --- grub-core/loader/slaunch/psp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/grub-core/loader/slaunch/psp.c b/grub-core/loader/slaunch/psp.c index 80b8eaec2..ca5232b30 100644 --- a/grub-core/loader/slaunch/psp.c +++ b/grub-core/loader/slaunch/psp.c @@ -377,10 +377,11 @@ int grub_drtm_setup_tmrs (grub_uint64_t tmr_end) { grub_uint64_t tmr_count = 0; + grub_uint64_t rem = 0; grub_uint32_t status = 0; - tmr_count = tmr_end / drtm_capability.tmr_alignment; - if (tmr_end % drtm_capability.tmr_alignment == 1) + tmr_count = grub_divmod64 (tmr_end, drtm_capability.tmr_alignment, &rem); + if (rem == 1) tmr_count++; if (tmr_count > GRUB_UINT_MAX) From c9ffe3f8c89fbf53d010d2e817629b3cf74265f2 Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Sun, 10 Nov 2024 20:13:19 +0200 Subject: [PATCH 02/26] grub-core: fix non-EFI build Signed-off-by: Sergii Dmytruk --- grub-core/Makefile.core.def | 2 +- grub-core/loader/slaunch/skl.c | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 1dc0f7560..c5429394c 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1878,12 +1878,12 @@ module = { x86 = loader/slaunch/acmod.c; x86 = loader/slaunch/verify.c; x86 = loader/slaunch/i386_linux.c; - x86 = loader/slaunch/x86_efi_linux.c; x86 = loader/slaunch/psp.c; x86 = loader/slaunch/skinit.c; x86 = loader/slaunch/skl.c; x86 = loader/slaunch/dlstub.c; x86 = loader/efi/dltrampoline.S; + x86_64_efi = loader/slaunch/x86_efi_linux.c; enable = x86; }; diff --git a/grub-core/loader/slaunch/skl.c b/grub-core/loader/slaunch/skl.c index 9bff0076f..03cdb866d 100644 --- a/grub-core/loader/slaunch/skl.c +++ b/grub-core/loader/slaunch/skl.c @@ -94,8 +94,10 @@ grub_skl_setup_module (struct grub_slaunch_params *slparams) grub_relocator_chunk_t ch; grub_phys_addr_t p_addr; grub_uint8_t *v_addr; - grub_addr_t max_addr; grub_err_t err; +#ifdef GRUB_MACHINE_EFI + grub_addr_t max_addr; +#endif if (slparams->boot_type == GRUB_SL_BOOT_TYPE_LINUX) { @@ -113,6 +115,7 @@ grub_skl_setup_module (struct grub_slaunch_params *slparams) } else { +#ifdef GRUB_MACHINE_EFI max_addr = ALIGN_DOWN ((GRUB_EFI_MAX_USABLE_ADDRESS - skl_size), GRUB_PAGE_SIZE); @@ -125,6 +128,9 @@ grub_skl_setup_module (struct grub_slaunch_params *slparams) v_addr = (grub_uint8_t *) ALIGN_UP ((grub_addr_t) v_addr, SKL_MIN_AIGNMENT); p_addr = (grub_addr_t) v_addr; +#else + return GRUB_ERR_BUG; +#endif } grub_memcpy (v_addr, skl_module, skl_size); From 682497dc61198a6274fd85325404bab4abe400e7 Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Fri, 29 Nov 2024 19:47:51 +0200 Subject: [PATCH 03/26] grub-core/loader/slaunch/psp.c: fix rounding up after division Signed-off-by: Sergii Dmytruk --- grub-core/loader/slaunch/psp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/loader/slaunch/psp.c b/grub-core/loader/slaunch/psp.c index ca5232b30..1513d2aed 100644 --- a/grub-core/loader/slaunch/psp.c +++ b/grub-core/loader/slaunch/psp.c @@ -381,7 +381,7 @@ grub_drtm_setup_tmrs (grub_uint64_t tmr_end) grub_uint32_t status = 0; tmr_count = grub_divmod64 (tmr_end, drtm_capability.tmr_alignment, &rem); - if (rem == 1) + if (rem != 0) tmr_count++; if (tmr_count > GRUB_UINT_MAX) From 8147876964aa9c17c939716a3a4628fca5602c05 Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Sun, 10 Nov 2024 20:09:09 +0200 Subject: [PATCH 04/26] loader: fix pointer <-> integer conversions The behaviour is implementation specific and in case of GCC 32-bit pointers are **sign-extended** on conversions to a larger integer type, thus producing invalid values. The opposite isn't dangerous, but still generates compiler warnings. Go through `grub_addr_t` in both cases. https://gcc.gnu.org/onlinedocs/gcc/Arrays-and-pointers-implementation.html Signed-off-by: Sergii Dmytruk --- grub-core/loader/i386/linux.c | 2 +- grub-core/loader/slaunch/dlstub.c | 6 +++--- grub-core/loader/slaunch/skinit.c | 8 ++++---- grub-core/loader/slaunch/skl.c | 4 ++-- grub-core/loader/slaunch/slrt.c | 28 ++++++++++++++-------------- grub-core/loader/slaunch/txt.c | 8 ++++---- 6 files changed, 28 insertions(+), 28 deletions(-) diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c index dcfbf619d..8ac07229c 100644 --- a/grub-core/loader/i386/linux.c +++ b/grub-core/loader/i386/linux.c @@ -703,7 +703,7 @@ grub_linux_boot (void) return GRUB_ERR_BAD_DEVICE; dlinfo = grub_slr_next_entry_by_tag (slrt, NULL, GRUB_SLR_ENTRY_DL_INFO); - dl_entry ((grub_uint64_t)&dlinfo->bl_context); + dl_entry ((grub_uint64_t)(grub_addr_t)&dlinfo->bl_context); /* If this returns, something failed miserably */ return GRUB_ERR_BAD_DEVICE; diff --git a/grub-core/loader/slaunch/dlstub.c b/grub-core/loader/slaunch/dlstub.c index 9c052f2be..1da8abb70 100644 --- a/grub-core/loader/slaunch/dlstub.c +++ b/grub-core/loader/slaunch/dlstub.c @@ -37,8 +37,8 @@ extern void dl_trampoline(grub_uint32_t dce_base, grub_uint32_t dce_size, grub_u void dl_entry (grub_uint64_t dl_ctx) { - struct grub_slr_bl_context *bl_ctx = (struct grub_slr_bl_context *)dl_ctx; - struct grub_slaunch_params *slparams = (struct grub_slaunch_params *)bl_ctx->context; + 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; grub_err_t err; @@ -50,7 +50,7 @@ void dl_entry (grub_uint64_t dl_ctx) if (state.edi == SLP_INTEL_TXT) { - err = grub_set_mtrrs_for_acmod ((void *)slparams->dce_base); + 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")); diff --git a/grub-core/loader/slaunch/skinit.c b/grub-core/loader/slaunch/skinit.c index cd469f4f2..98bd1bcb2 100644 --- a/grub-core/loader/slaunch/skinit.c +++ b/grub-core/loader/slaunch/skinit.c @@ -145,11 +145,11 @@ grub_skinit_psp_memory_protect (struct grub_slaunch_params *slparams) * On legacy Linux boots, the relocator is used to map the EFI memory map buffer * and return a virtual address to use. This virtual address is stashed in slparams. */ - efi_memmap = (grub_uint64_t)slparams->efi_memmap_mem; + efi_memmap = (grub_uint64_t)(grub_addr_t)slparams->efi_memmap_mem; } - desc = (grub_efi_memory_descriptor_t *) efi_memmap; - memory_map_end = (grub_efi_memory_descriptor_t *) (efi_memmap + efi_info->efi_mmap_size); + desc = (grub_efi_memory_descriptor_t *)(grub_addr_t) efi_memmap; + memory_map_end = (grub_efi_memory_descriptor_t *)(grub_addr_t) (efi_memmap + efi_info->efi_mmap_size); for (; desc < memory_map_end; desc = (grub_efi_memory_descriptor_t *) ((char *) desc + efi_info->efi_mem_desc_size)) { tmr_end = desc->physical_start + (desc->num_pages << 12); @@ -192,7 +192,7 @@ grub_skinit_send_init_ipi_shorthand (void) /* mask off low order bits to get base address */ apic_base &= GRUB_MSR_X86_APICBASE_BASE; /* access ICR through MMIO */ - icr_reg = (grub_uint32_t *)(grub_uint64_t)(apic_base + GRUB_MSR_X86_LAPIC_ICR_LO); + icr_reg = (grub_uint32_t *)(grub_addr_t)(apic_base + GRUB_MSR_X86_LAPIC_ICR_LO); grub_writel ((GRUB_MSR_X86_ICR_DELIVER_EXCL_SELF|GRUB_MSR_X86_ICR_MODE_INIT), icr_reg); } diff --git a/grub-core/loader/slaunch/skl.c b/grub-core/loader/slaunch/skl.c index 03cdb866d..99278eb1f 100644 --- a/grub-core/loader/slaunch/skl.c +++ b/grub-core/loader/slaunch/skl.c @@ -153,12 +153,12 @@ grub_skl_link_amd_info (struct grub_slaunch_params *slparams) { struct grub_slr_entry_amd_info *amd_info; - amd_info = grub_slr_next_entry_by_tag ((struct grub_slr_table *)slparams->slr_table_base, + amd_info = grub_slr_next_entry_by_tag ((struct grub_slr_table *)(grub_addr_t) slparams->slr_table_base, NULL, GRUB_SLR_ENTRY_AMD_INFO); amd_info->next = slparams->boot_params->setup_data; - slparams->boot_params->setup_data = (grub_uint64_t)amd_info + sizeof (struct grub_slr_entry_hdr); + slparams->boot_params->setup_data = (grub_uint64_t)(grub_addr_t)amd_info + sizeof (struct grub_slr_entry_hdr); } grub_err_t diff --git a/grub-core/loader/slaunch/slrt.c b/grub-core/loader/slaunch/slrt.c index 26fc874ec..6138015fe 100644 --- a/grub-core/loader/slaunch/slrt.c +++ b/grub-core/loader/slaunch/slrt.c @@ -81,7 +81,7 @@ grub_setup_slrt_policy (struct grub_slaunch_params *slparams, /* boot params have everything needed to setup policy except OS2MLE data */ slr_policy_staging->policy_entries[i].pcr = 18; slr_policy_staging->policy_entries[i].entity_type = GRUB_SLR_ET_BOOT_PARAMS; - slr_policy_staging->policy_entries[i].entity = (grub_uint64_t)boot_params; + slr_policy_staging->policy_entries[i].entity = (grub_uint64_t)(grub_addr_t)boot_params; slr_policy_staging->policy_entries[i].size = GRUB_PAGE_SIZE; grub_strcpy (slr_policy_staging->policy_entries[i].evt_info, "Measured boot parameters"); i++; @@ -160,12 +160,12 @@ grub_setup_slrt_dl_info (struct grub_slaunch_params *slparams) { struct grub_txt_mle_header *mle_header; - mle_header = (struct grub_txt_mle_header *)(grub_addr_t) (slparams->mle_start + slparams->mle_header_offset); + mle_header = (struct grub_txt_mle_header *)((grub_addr_t) slparams->mle_start + slparams->mle_header_offset); /* Setup DL entry point, DCE and DLME information */ slr_dl_info_staging.bl_context.bootloader = GRUB_SLR_BOOTLOADER_GRUB; - slr_dl_info_staging.bl_context.context = (grub_uint64_t)slparams; - slr_dl_info_staging.dl_handler = (grub_uint64_t)dl_entry_trampoline; + slr_dl_info_staging.bl_context.context = (grub_addr_t)slparams; + slr_dl_info_staging.dl_handler = (grub_addr_t)dl_entry_trampoline; slr_dl_info_staging.dlme_size = slparams->mle_size; slr_dl_info_staging.dlme_base = slparams->mle_start; slr_dl_info_staging.dlme_entry = mle_header->entry_point; @@ -187,16 +187,16 @@ void grub_setup_slr_table (struct grub_slaunch_params *slparams, struct grub_slr_entry_hdr *platform_info) { - grub_slr_add_entry ((struct grub_slr_table *)slparams->slr_table_base, - (struct grub_slr_entry_hdr *)&slr_dl_info_staging); - grub_slr_add_entry ((struct grub_slr_table *)slparams->slr_table_base, - (struct grub_slr_entry_hdr *)&slr_log_info_staging); - grub_slr_add_entry ((struct grub_slr_table *)slparams->slr_table_base, - (struct grub_slr_entry_hdr *)slr_policy_staging); + struct grub_slr_table *slrt = + (struct grub_slr_table *)(grub_addr_t)slparams->slr_table_base; + + grub_slr_add_entry (slrt, &slr_dl_info_staging.hdr); + grub_slr_add_entry (slrt, &slr_log_info_staging.hdr); + grub_slr_add_entry (slrt, &slr_policy_staging->hdr); + /* Add in any platform specific info if present */ if (platform_info) - grub_slr_add_entry ((struct grub_slr_table *)slparams->slr_table_base, - platform_info); + grub_slr_add_entry (slrt, platform_info); } void @@ -208,7 +208,7 @@ grub_update_slrt_policy (struct grub_slaunch_params *slparams) grub_uint64_t hi_val; int i, next = 0; - policy = grub_slr_next_entry_by_tag ((struct grub_slr_table *)slparams->slr_table_base, + policy = grub_slr_next_entry_by_tag ((struct grub_slr_table *)(grub_addr_t)slparams->slr_table_base, NULL, GRUB_SLR_ENTRY_ENTRY_POLICY); @@ -217,7 +217,7 @@ grub_update_slrt_policy (struct grub_slaunch_params *slparams) { if (policy->policy_entries[i].entity_type == GRUB_SLR_ET_BOOT_PARAMS) { - boot_params = (struct linux_kernel_params *)policy->policy_entries[i].entity; + boot_params = (struct linux_kernel_params *)(grub_addr_t)policy->policy_entries[i].entity; slparams->boot_params = boot_params; break; } diff --git a/grub-core/loader/slaunch/txt.c b/grub-core/loader/slaunch/txt.c index b07b1f37f..aab2c2147 100644 --- a/grub-core/loader/slaunch/txt.c +++ b/grub-core/loader/slaunch/txt.c @@ -509,10 +509,10 @@ set_txt_info_ptr (struct grub_slaunch_params *slparams, { struct grub_slr_entry_hdr *txt_info; - txt_info = grub_slr_next_entry_by_tag ((struct grub_slr_table *)slparams->slr_table_base, + txt_info = grub_slr_next_entry_by_tag ((struct grub_slr_table *)(grub_addr_t)slparams->slr_table_base, NULL, GRUB_SLR_ENTRY_INTEL_INFO); - os_mle_data->txt_info = (grub_uint64_t)txt_info; + os_mle_data->txt_info = (grub_addr_t)txt_info; } static grub_err_t @@ -560,7 +560,7 @@ init_txt_heap (struct grub_slaunch_params *slparams, struct grub_txt_acm_header /* Setup the TXT specific SLR information and policy entry */ slr_intel_info_staging.hdr.tag = GRUB_SLR_ENTRY_INTEL_INFO; slr_intel_info_staging.hdr.size = sizeof(struct grub_slr_entry_intel_info); - slr_intel_info_staging.txt_heap = (grub_uint64_t)txt_heap; + slr_intel_info_staging.txt_heap = (grub_addr_t)txt_heap; slr_intel_info_staging.saved_misc_enable_msr = grub_rdmsr (GRUB_MSR_X86_MISC_ENABLE); grub_memcpy (&(slr_intel_info_staging.saved_bsp_mtrrs), &saved_mtrrs_state, @@ -568,7 +568,7 @@ init_txt_heap (struct grub_slaunch_params *slparams, struct grub_txt_acm_header slr_intel_policy_staging.pcr = 18; slr_intel_policy_staging.entity_type = GRUB_SLR_ET_TXT_OS2MLE; - slr_intel_policy_staging.entity = (grub_uint64_t)os_mle_data; + slr_intel_policy_staging.entity = (grub_addr_t)os_mle_data; slr_intel_policy_staging.size = sizeof(struct grub_txt_os_mle_data); grub_strcpy (slr_intel_policy_staging.evt_info, "Measured TXT OS-MLE data"); From 025f421a4a1cf3b129400e36ca39e89e5bf504da Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Sun, 10 Nov 2024 20:14:52 +0200 Subject: [PATCH 05/26] loader/slaunch: fix invalid format specifiers Signed-off-by: Sergii Dmytruk --- grub-core/loader/slaunch/skinit.c | 3 ++- grub-core/loader/slaunch/txt.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/grub-core/loader/slaunch/skinit.c b/grub-core/loader/slaunch/skinit.c index 98bd1bcb2..3b3ff251d 100644 --- a/grub-core/loader/slaunch/skinit.c +++ b/grub-core/loader/slaunch/skinit.c @@ -108,7 +108,8 @@ grub_skinit_prepare_cpu (void) { mcg_stat = grub_rdmsr (GRUB_MSR_X86_MC0_STATUS + i * 4); if (mcg_stat & (1ULL << 63)) - return grub_error (GRUB_ERR_BAD_DEVICE, N_("secure launch MCG[%u] = %lx ERROR"), i, mcg_stat); + return grub_error (GRUB_ERR_BAD_DEVICE, N_("secure launch MCG[%u] = %llx ERROR"), + i, (unsigned long long)mcg_stat); } return GRUB_ERR_NONE; diff --git a/grub-core/loader/slaunch/txt.c b/grub-core/loader/slaunch/txt.c index aab2c2147..f98631dd4 100644 --- a/grub-core/loader/slaunch/txt.c +++ b/grub-core/loader/slaunch/txt.c @@ -229,7 +229,7 @@ grub_txt_prepare_cpu (void) mcg_stat = grub_rdmsr (GRUB_MSR_X86_MC0_STATUS + i * 4); if (mcg_stat & (1ULL << 63)) return grub_error (GRUB_ERR_BAD_DEVICE, - N_("secure launch MCG[%u] = %lx ERROR"), i, mcg_stat); + N_("secure launch MCG[%u] = %llx ERROR"), i, (unsigned long long)mcg_stat); } } From 8b80806f6ad5cf34bb55bef6a5facea4a35b991f Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Tue, 19 Nov 2024 19:27:47 +0200 Subject: [PATCH 06/26] loader/slaunch/txt.c: FIXME cleanup Signed-off-by: Sergii Dmytruk --- grub-core/loader/slaunch/txt.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/grub-core/loader/slaunch/txt.c b/grub-core/loader/slaunch/txt.c index f98631dd4..c5deaa043 100644 --- a/grub-core/loader/slaunch/txt.c +++ b/grub-core/loader/slaunch/txt.c @@ -668,14 +668,8 @@ init_txt_heap (struct grub_slaunch_params *slparams, struct grub_txt_acm_header heap_event_log_pointer2_1_element->type = GRUB_TXT_HEAP_EXTDATA_TYPE_EVENT_LOG_POINTER2_1; heap_event_log_pointer2_1_element->size = sizeof (*heap_event_log_pointer2_1_element); - /* FIXME: First option is correct way to do!!! */ -#if 1 heap_event_log_pointer2_1_element->phys_addr = slparams->tpm_evt_log_base; heap_event_log_pointer2_1_element->allocated_event_container_size = slparams->tpm_evt_log_size; -#else - heap_event_log_pointer2_1_element->phys_addr = (grub_addr_t) &os_mle_data->event_log_buffer; - heap_event_log_pointer2_1_element->allocated_event_container_size = sizeof (os_mle_data->event_log_buffer); -#endif heap_end_element = (struct grub_txt_heap_end_element *) ((grub_addr_t) heap_event_log_pointer2_1_element + heap_event_log_pointer2_1_element->size); From e69ea65133917d68d3ca6b5d0c512226187416c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=BBygowski?= Date: Wed, 31 Aug 2022 14:37:49 +0200 Subject: [PATCH 07/26] i386/txt: Initialize TPM 1.2 event log in TXT heap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Żygowski Signed-off-by: Krystian Hebel Signed-off-by: Sergii Dmytruk --- grub-core/loader/slaunch/txt.c | 68 +++++++++++++++++++++++++++++++++- include/grub/i386/txt.h | 34 +++++++++++++++++ 2 files changed, 101 insertions(+), 1 deletion(-) diff --git a/grub-core/loader/slaunch/txt.c b/grub-core/loader/slaunch/txt.c index c5deaa043..3fcaa249b 100644 --- a/grub-core/loader/slaunch/txt.c +++ b/grub-core/loader/slaunch/txt.c @@ -503,6 +503,32 @@ grub_set_mtrrs_for_acmod (struct grub_txt_acm_header *hdr) return GRUB_ERR_NONE; } +void +grub_txt_init_tpm_event_log (void *buf, grub_size_t size) +{ + struct grub_txt_event_log_container *elog; + + if (buf == NULL || size < sizeof (*elog)) + return; + + /* For TPM 2.0 just clear the area, only TPM 1.2 requires initialization. */ + grub_memset (buf, 0, size); + + if (grub_get_tpm_ver () != GRUB_TPM_12) + return; + + elog = (struct grub_txt_event_log_container *) buf; + + grub_memcpy ((void *) elog->signature, EVTLOG_SIGNATURE, sizeof (elog->signature)); + elog->container_ver_major = EVTLOG_CNTNR_MAJOR_VER; + elog->container_ver_minor = EVTLOG_CNTNR_MINOR_VER; + elog->pcr_event_ver_major = EVTLOG_EVT_MAJOR_VER; + elog->pcr_event_ver_minor = EVTLOG_EVT_MINOR_VER; + elog->size = size; + elog->pcr_events_offset = sizeof (*elog); + elog->next_event_offset = sizeof (*elog); +} + static void set_txt_info_ptr (struct grub_slaunch_params *slparams, struct grub_txt_os_mle_data *os_mle_data) @@ -524,6 +550,7 @@ init_txt_heap (struct grub_slaunch_params *slparams, struct grub_txt_acm_header struct grub_txt_os_mle_data *os_mle_data; struct grub_txt_os_sinit_data *os_sinit_data; struct grub_txt_heap_end_element *heap_end_element; + struct grub_txt_heap_tpm_event_log_element *heap_tpm_event_log_element; struct grub_txt_heap_event_log_pointer2_1_element *heap_event_log_pointer2_1_element; #ifdef GRUB_MACHINE_EFI struct grub_acpi_rsdp_v20 *rsdp; @@ -634,10 +661,31 @@ init_txt_heap (struct grub_slaunch_params *slparams, struct grub_txt_acm_header sinit_caps = grub_txt_get_sinit_capabilities (sinit); + grub_dprintf ("slaunch", "SINIT capabilities 0x%08x\n", sinit_caps); + /* CBnT bits 5:4 must be 11b, since D/A mapping is the only one supported. */ os_sinit_data->capabilities = GRUB_TXT_CAPS_TPM_12_NO_LEGACY_PCR_USAGE | GRUB_TXT_CAPS_TPM_12_AUTH_PCR_USAGE; + if (grub_get_tpm_ver () == GRUB_TPM_20) + { + if ((sinit_caps & os_sinit_data->capabilities) != os_sinit_data->capabilities) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("Details/authorities PCR usage is not supported")); + } + else + { + if (!(sinit_caps & GRUB_TXT_CAPS_TPM_12_AUTH_PCR_USAGE)) + { + grub_dprintf ("slaunch", "Details/authorities PCR usage is not supported. Trying legacy"); + if (sinit_caps & GRUB_TXT_CAPS_TPM_12_NO_LEGACY_PCR_USAGE) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("Not a single PCR usage available in SINIT capabilities")); + + os_sinit_data->capabilities = 0; + } + } + /* Choose monitor RLP wakeup mechanism first. */ if (sinit_caps & GRUB_TXT_CAPS_MONITOR_SUPPORT) os_sinit_data->capabilities |= GRUB_TXT_CAPS_MONITOR_SUPPORT; @@ -650,9 +698,27 @@ init_txt_heap (struct grub_slaunch_params *slparams, struct grub_txt_acm_header os_sinit_data->capabilities |= GRUB_TXT_CAPS_ECX_PT_SUPPORT; if (grub_get_tpm_ver () == GRUB_TPM_12) - return grub_error (GRUB_ERR_BAD_DEVICE, N_("TPM 1.2 is not supported")); + { + grub_dprintf ("slaunch", "TPM 1.2 detected\n"); + grub_dprintf ("slaunch", "Setting up TXT HEAP TPM event log element\n"); + os_sinit_data->flags = GRUB_TXT_PCR_EXT_MAX_PERF_POLICY; + os_sinit_data->version = OS_SINIT_DATA_TPM_12_VER; + + heap_tpm_event_log_element = + (struct grub_txt_heap_tpm_event_log_element *) os_sinit_data->ext_data_elts; + heap_tpm_event_log_element->type = GRUB_TXT_HEAP_EXTDATA_TYPE_TPM_EVENT_LOG_PTR; + heap_tpm_event_log_element->size = sizeof (*heap_tpm_event_log_element); + heap_tpm_event_log_element->event_log_phys_addr = slparams->tpm_evt_log_base; + + heap_end_element = (struct grub_txt_heap_end_element *) + ((grub_addr_t) heap_tpm_event_log_element + heap_tpm_event_log_element->size); + heap_end_element->type = GRUB_TXT_HEAP_EXTDATA_TYPE_END; + heap_end_element->size = sizeof (*heap_end_element); + } else { + grub_dprintf ("slaunch", "TPM 2.0 detected\n"); + grub_dprintf ("slaunch", "Setting up TXT HEAP TPM event log element\n"); if (!(sinit_caps & GRUB_TXT_CAPS_TPM_20_EVTLOG_SUPPORT)) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("original TXT TPM 2.0 event log format is not supported")); diff --git a/include/grub/i386/txt.h b/include/grub/i386/txt.h index a171ab437..0b4e33191 100644 --- a/include/grub/i386/txt.h +++ b/include/grub/i386/txt.h @@ -21,6 +21,8 @@ #ifndef GRUB_TXT_H #define GRUB_TXT_H 1 +#include + /* Intel TXT Software Developers Guide */ /* Chapter 2, Table 2 MLE/SINIT Capabilities Field Bit Definitions */ @@ -634,6 +636,36 @@ struct grub_smx_parameters grub_uint32_t txt_feature_ext_flags; } GRUB_PACKED; +/* Structures and constants used for TPM 1.2 event log initialization */ +struct grub_tpm12_pcr_event +{ + grub_uint32_t pcr_index; + grub_uint32_t type; + grub_uint8_t digest[SHA1_DIGEST_SIZE]; + grub_uint32_t data_size; + grub_uint8_t data[]; +} GRUB_PACKED; + +#define EVTLOG_SIGNATURE "TXT Event Container" +#define EVTLOG_CNTNR_MAJOR_VER 1 +#define EVTLOG_CNTNR_MINOR_VER 0 +#define EVTLOG_EVT_MAJOR_VER 1 +#define EVTLOG_EVT_MINOR_VER 0 + +struct grub_txt_event_log_container +{ + grub_uint8_t signature[20]; + grub_uint8_t reserved[12]; + grub_uint8_t container_ver_major; + grub_uint8_t container_ver_minor; + grub_uint8_t pcr_event_ver_major; + grub_uint8_t pcr_event_ver_minor; + grub_uint32_t size; + grub_uint32_t pcr_events_offset; + grub_uint32_t next_event_offset; + struct grub_tpm12_pcr_event pcr_events[]; +} GRUB_PACKED; + static inline void grub_txt_getsec_parameters (grub_uint32_t index, grub_uint32_t *eax_out, grub_uint32_t *ebx_out, grub_uint32_t *ecx_out) @@ -660,6 +692,8 @@ extern grub_err_t grub_txt_verify_platform (void); extern grub_err_t grub_txt_prepare_cpu (void); extern grub_err_t grub_set_mtrrs_for_acmod (struct grub_txt_acm_header *hdr); +extern void grub_txt_init_tpm_event_log (void *buf, grub_size_t size); + extern grub_uint32_t grub_txt_get_mle_ptab_size (grub_uint32_t mle_size); extern void grub_txt_setup_mle_ptab (struct grub_slaunch_params *slparams); From 0231aa98ae6e86081d06cd1bd056f850ae169338 Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Sun, 10 Nov 2024 21:01:18 +0200 Subject: [PATCH 08/26] loader/slaunch: make SKINIT work on AMD without PSP Signed-off-by: Sergii Dmytruk --- grub-core/loader/slaunch/dlstub.c | 16 ++++++++++++---- grub-core/loader/slaunch/skinit.c | 4 ---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/grub-core/loader/slaunch/dlstub.c b/grub-core/loader/slaunch/dlstub.c index 1da8abb70..caf28fe26 100644 --- a/grub-core/loader/slaunch/dlstub.c +++ b/grub-core/loader/slaunch/dlstub.c @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include #include @@ -68,12 +70,18 @@ void dl_entry (grub_uint64_t dl_ctx) { grub_skl_link_amd_info (slparams); - err = grub_skinit_psp_memory_protect (slparams); - if ( err ) + err = grub_psp_discover (); + if (err == GRUB_ERR_NONE) { - grub_error (GRUB_ERR_BAD_DEVICE, N_("setup PSP TMR memory protection failed")); - return; + err = grub_skinit_psp_memory_protect (slparams); + if (err != GRUB_ERR_NONE) + { + grub_error (GRUB_ERR_BAD_DEVICE, N_("setup PSP TMR memory protection failed")); + return; + } } + else + grub_tpm_relinquish_locality (0); err = grub_skinit_prepare_cpu (); if ( err ) diff --git a/grub-core/loader/slaunch/skinit.c b/grub-core/loader/slaunch/skinit.c index 3b3ff251d..61ca8aa59 100644 --- a/grub-core/loader/slaunch/skinit.c +++ b/grub-core/loader/slaunch/skinit.c @@ -156,10 +156,6 @@ grub_skinit_psp_memory_protect (struct grub_slaunch_params *slparams) tmr_end = desc->physical_start + (desc->num_pages << 12); } - err = grub_psp_discover (); - if (err != GRUB_ERR_NONE) - return err; - grub_drtm_kick_psp (); err = grub_drtm_get_capability (); From 561f8648127aa3d68f8760b6aece6f6eede4d139 Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Sun, 10 Nov 2024 21:20:17 +0200 Subject: [PATCH 09/26] loader/slaunch: {SKL,SLB}_MIN_A{,L}IGNMENT Signed-off-by: Sergii Dmytruk --- grub-core/loader/slaunch/skl.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/grub-core/loader/slaunch/skl.c b/grub-core/loader/slaunch/skl.c index 99278eb1f..bfcc48844 100644 --- a/grub-core/loader/slaunch/skl.c +++ b/grub-core/loader/slaunch/skl.c @@ -44,7 +44,7 @@ #undef GRUB_MEMORY_CPU_HEADER #include -#define SKL_MIN_AIGNMENT 0x10000 +#define SLB_MIN_ALIGNMENT 0x10000 static struct grub_skl_info skl_info = { .uuid = { @@ -103,7 +103,7 @@ grub_skl_setup_module (struct grub_slaunch_params *slparams) { err = grub_relocator_alloc_chunk_align (slparams->relocator, &ch, 0, 0xFFFFFFFF, skl_size, - SKL_MIN_AIGNMENT, + SLB_MIN_ALIGNMENT, GRUB_RELOCATOR_PREFERENCE_HIGH, 1); @@ -120,13 +120,13 @@ grub_skl_setup_module (struct grub_slaunch_params *slparams) GRUB_PAGE_SIZE); v_addr = grub_efi_allocate_pages_real (max_addr, - GRUB_EFI_BYTES_TO_PAGES(skl_size + SKL_MIN_AIGNMENT), + GRUB_EFI_BYTES_TO_PAGES(skl_size + SLB_MIN_ALIGNMENT), GRUB_EFI_ALLOCATE_MAX_ADDRESS, GRUB_EFI_LOADER_DATA); if (!v_addr) return GRUB_ERR_OUT_OF_MEMORY; - v_addr = (grub_uint8_t *) ALIGN_UP ((grub_addr_t) v_addr, SKL_MIN_AIGNMENT); + v_addr = (grub_uint8_t *) ALIGN_UP ((grub_addr_t) v_addr, SLB_MIN_ALIGNMENT); p_addr = (grub_addr_t) v_addr; #else return GRUB_ERR_BUG; From 3fbbb7963727650180f537c35324366b6f8bc733 Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Sun, 10 Nov 2024 21:21:45 +0200 Subject: [PATCH 10/26] loader/slaunch/skl.c: fix allocating SKL and placing SLRT Signed-off-by: Sergii Dmytruk --- grub-core/loader/slaunch/skl.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/grub-core/loader/slaunch/skl.c b/grub-core/loader/slaunch/skl.c index bfcc48844..1984478d3 100644 --- a/grub-core/loader/slaunch/skl.c +++ b/grub-core/loader/slaunch/skl.c @@ -45,6 +45,7 @@ #include #define SLB_MIN_ALIGNMENT 0x10000 +#define SLB_SIZE 0x10000 static struct grub_skl_info skl_info = { .uuid = { @@ -102,7 +103,7 @@ grub_skl_setup_module (struct grub_slaunch_params *slparams) if (slparams->boot_type == GRUB_SL_BOOT_TYPE_LINUX) { err = grub_relocator_alloc_chunk_align (slparams->relocator, &ch, - 0, 0xFFFFFFFF, skl_size, + 0, UP_TO_TOP32(SLB_SIZE), SLB_SIZE, SLB_MIN_ALIGNMENT, GRUB_RELOCATOR_PREFERENCE_HIGH, 1); @@ -116,11 +117,11 @@ grub_skl_setup_module (struct grub_slaunch_params *slparams) else { #ifdef GRUB_MACHINE_EFI - max_addr = ALIGN_DOWN ((GRUB_EFI_MAX_USABLE_ADDRESS - skl_size), + max_addr = ALIGN_DOWN ((GRUB_EFI_MAX_USABLE_ADDRESS - SLB_SIZE), GRUB_PAGE_SIZE); v_addr = grub_efi_allocate_pages_real (max_addr, - GRUB_EFI_BYTES_TO_PAGES(skl_size + SLB_MIN_ALIGNMENT), + GRUB_EFI_BYTES_TO_PAGES(SLB_SIZE + SLB_MIN_ALIGNMENT), GRUB_EFI_ALLOCATE_MAX_ADDRESS, GRUB_EFI_LOADER_DATA); if (!v_addr) @@ -142,7 +143,7 @@ grub_skl_setup_module (struct grub_slaunch_params *slparams) /* The SLRT resides in the relocated SKL bootloader_data section, set the values here */ slparams->slr_table_base = (grub_uint64_t)p_addr + skl_module->bootloader_data_offset; - slparams->slr_table_size = skl_size - skl_module->bootloader_data_offset; + slparams->slr_table_size = SLB_SIZE - skl_module->bootloader_data_offset; slparams->slr_table_mem = v_addr + skl_module->bootloader_data_offset; return GRUB_ERR_NONE; From 81876ee0478043a77fc9c907e43882924125188c Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Sun, 10 Nov 2024 21:30:47 +0200 Subject: [PATCH 11/26] loader/slaunch: fix reading mle_header Only the case of legacy boot has slparams->mle_start and slparams->mle_mem different. Other places are updated for consistency. Signed-off-by: Sergii Dmytruk --- grub-core/loader/slaunch/i386_linux.c | 2 ++ grub-core/loader/slaunch/slrt.c | 2 +- grub-core/loader/slaunch/x86_efi_linux.c | 2 ++ include/grub/slaunch.h | 1 + 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/grub-core/loader/slaunch/i386_linux.c b/grub-core/loader/slaunch/i386_linux.c index 3b2b5b81b..2a830c0b3 100644 --- a/grub-core/loader/slaunch/i386_linux.c +++ b/grub-core/loader/slaunch/i386_linux.c @@ -159,6 +159,7 @@ grub_sl_txt_setup_linux (struct grub_slaunch_params *slparams, struct grub_reloc *prot_mode_mem = (char *)*prot_mode_mem + slparams->mle_ptab_size; *prot_mode_target += slparams->mle_ptab_size; + slparams->mle_mem = *prot_mode_mem; slparams->mle_start = *prot_mode_target; slparams->mle_size = prot_size; @@ -231,6 +232,7 @@ grub_sl_skinit_setup_linux (struct grub_slaunch_params *slparams, struct grub_re /* Zero out memory to get stable MLE measurements. */ grub_memset (prot_mode_mem, 0, total_size); + slparams->mle_mem = prot_mode_mem; slparams->mle_start = prot_mode_target; slparams->mle_size = prot_file_size; diff --git a/grub-core/loader/slaunch/slrt.c b/grub-core/loader/slaunch/slrt.c index 6138015fe..6f9bf4e67 100644 --- a/grub-core/loader/slaunch/slrt.c +++ b/grub-core/loader/slaunch/slrt.c @@ -160,7 +160,7 @@ grub_setup_slrt_dl_info (struct grub_slaunch_params *slparams) { struct grub_txt_mle_header *mle_header; - mle_header = (struct grub_txt_mle_header *)((grub_addr_t) slparams->mle_start + slparams->mle_header_offset); + mle_header = (struct grub_txt_mle_header *)((grub_addr_t) slparams->mle_mem + slparams->mle_header_offset); /* Setup DL entry point, DCE and DLME information */ slr_dl_info_staging.bl_context.bootloader = GRUB_SLR_BOOTLOADER_GRUB; diff --git a/grub-core/loader/slaunch/x86_efi_linux.c b/grub-core/loader/slaunch/x86_efi_linux.c index 4ae792f01..4ead208c7 100644 --- a/grub-core/loader/slaunch/x86_efi_linux.c +++ b/grub-core/loader/slaunch/x86_efi_linux.c @@ -171,6 +171,7 @@ grub_sl_efi_txt_setup (struct grub_slaunch_params *slparams, void *kernel_addr, * header is in the startup section before the protected mode piece begins. * In legacy world this part of the image would have been stripped off. */ + slparams->mle_mem = image_base + start; slparams->mle_start = image_base + start; slparams->mle_size = image_size - start; @@ -233,6 +234,7 @@ grub_sl_efi_skinit_setup (struct grub_slaunch_params *slparams, void *kernel_add start = (lh->setup_sects + 1) * 512; /* See comment in TXT setup function grub_efi_slaunch_setup_txt() */ + slparams->mle_mem = image_base + start; slparams->mle_start = image_base + start; slparams->mle_size = image_size - start; diff --git a/include/grub/slaunch.h b/include/grub/slaunch.h index 37af7fbfb..6d542f681 100644 --- a/include/grub/slaunch.h +++ b/include/grub/slaunch.h @@ -55,6 +55,7 @@ struct grub_slaunch_params grub_uint64_t slr_table_base; grub_uint32_t slr_table_size; void *slr_table_mem; + void *mle_mem; grub_uint32_t mle_start; grub_uint32_t mle_size; grub_uint64_t mle_ptab_target; From b883adcaaddd5f6d07f4f280d69058b26ddd7947 Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Mon, 11 Nov 2024 00:38:39 +0200 Subject: [PATCH 12/26] loader/slaunch: allow multiple "slaunch_module" commands Signed-off-by: Sergii Dmytruk --- grub-core/loader/slaunch/skl.c | 7 ++--- grub-core/loader/slaunch/slaunch.c | 41 +++++++++++++++++++----------- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/grub-core/loader/slaunch/skl.c b/grub-core/loader/slaunch/skl.c index 1984478d3..c5269e624 100644 --- a/grub-core/loader/slaunch/skl.c +++ b/grub-core/loader/slaunch/skl.c @@ -64,8 +64,7 @@ int grub_skl_set_module (const void *skl_base, grub_uint32_t size) { struct grub_skl_info *info; - skl_module = (struct grub_sl_header *) skl_base; - skl_size = size; + struct grub_sl_header *module = (struct grub_sl_header *) skl_base; if (skl_size < (8*GRUB_PAGE_SIZE)) { @@ -73,7 +72,7 @@ grub_skl_set_module (const void *skl_base, grub_uint32_t size) return 0; } - info = (struct grub_skl_info *) ((grub_uint8_t *) skl_module + skl_module->skl_info_offset); + info = (struct grub_skl_info *) ((grub_uint8_t *) module + module->skl_info_offset); if (info->version != GRUB_SKL_VERSION) { grub_dprintf ("slaunch", "Possible SKL module incorrect version\n"); @@ -86,6 +85,8 @@ grub_skl_set_module (const void *skl_base, grub_uint32_t size) return 0; } + skl_module = module; + skl_size = size; return 1; } diff --git a/grub-core/loader/slaunch/slaunch.c b/grub-core/loader/slaunch/slaunch.c index 874a5810c..39e6e0ad8 100644 --- a/grub-core/loader/slaunch/slaunch.c +++ b/grub-core/loader/slaunch/slaunch.c @@ -103,13 +103,18 @@ grub_cmd_slaunch_module (grub_command_t cmd __attribute__ ((unused)), { grub_file_t file; grub_ssize_t size; + void *new_module = NULL; - if (!argc) - return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected: filename")); if (slp == SLP_NONE) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("secure launch not enabled")); + if (slp > SLP_AMD_SKINIT) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("unknown secure launch platform type: %d"), slp); + grub_errno = GRUB_ERR_NONE; file = grub_file_open (argv[0], GRUB_FILE_TYPE_SLAUNCH_MODULE); @@ -125,12 +130,12 @@ grub_cmd_slaunch_module (grub_command_t cmd __attribute__ ((unused)), goto fail; } - slaunch_module = grub_malloc (size); + new_module = grub_malloc (size); - if (slaunch_module == NULL) + if (new_module == NULL) goto fail; - if (grub_file_read (file, slaunch_module, size) != size) + if (grub_file_read (file, new_module, size) != size) { if (grub_errno == GRUB_ERR_NONE) grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file: %s"), @@ -140,13 +145,13 @@ grub_cmd_slaunch_module (grub_command_t cmd __attribute__ ((unused)), if (slp == SLP_INTEL_TXT) { - if (!grub_txt_is_sinit_acmod (slaunch_module, size)) + if (!grub_txt_is_sinit_acmod (new_module, size)) { grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("it does not look like SINIT ACM")); goto fail; } - if (!grub_txt_acmod_match_platform (slaunch_module)) + if (!grub_txt_acmod_match_platform (new_module)) { grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("SINIT ACM does not match platform")); goto fail; @@ -154,7 +159,7 @@ grub_cmd_slaunch_module (grub_command_t cmd __attribute__ ((unused)), } else if (slp == SLP_AMD_SKINIT) { - if (!grub_skl_set_module (slaunch_module, size)) + if (!grub_skl_set_module (new_module, size)) { grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("SKL module isn't correct")); goto fail; @@ -163,16 +168,17 @@ grub_cmd_slaunch_module (grub_command_t cmd __attribute__ ((unused)), grub_file_close (file); + grub_free (slaunch_module); + slaunch_module = new_module; + return GRUB_ERR_NONE; fail: grub_error_push (); - grub_free (slaunch_module); + grub_free (new_module); grub_file_close (file); - slaunch_module = NULL; - grub_error_pop (); return grub_errno; @@ -206,16 +212,21 @@ GRUB_MOD_INIT (slaunch) N_("[--legacy-linux]"), N_("Enable secure launcher")); cmd_slaunch_module = grub_register_command ("slaunch_module", grub_cmd_slaunch_module, - NULL, N_("Secure launcher module command")); + NULL, N_("Load secure launcher module from file")); cmd_slaunch_state = grub_register_command ("slaunch_state", grub_cmd_slaunch_state, NULL, N_("Display secure launcher state")); } GRUB_MOD_FINI (slaunch) { - grub_unregister_command (cmd_slaunch_state); - grub_unregister_command (cmd_slaunch_module); - grub_unregister_command (cmd_slaunch); + if (cmd_slaunch_state) + grub_unregister_command (cmd_slaunch_state); + + if (cmd_slaunch_module) + grub_unregister_command (cmd_slaunch_module); + + if (cmd_slaunch) + grub_unregister_command (cmd_slaunch); if (slp == SLP_INTEL_TXT) grub_txt_shutdown (); From 8a6928920b5d3788bb735a2e10668024300205eb Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Mon, 11 Nov 2024 00:38:10 +0200 Subject: [PATCH 13/26] loader/slaunch/skl.c: improve grub_skl_set_module() checks Make them more comprehensive and remove the `skl_size < (8*GRUB_PAGE_SIZE)` one which doesn't make much sense. Signed-off-by: Sergii Dmytruk --- grub-core/loader/slaunch/skl.c | 55 +++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/grub-core/loader/slaunch/skl.c b/grub-core/loader/slaunch/skl.c index c5269e624..dd1dd6f27 100644 --- a/grub-core/loader/slaunch/skl.c +++ b/grub-core/loader/slaunch/skl.c @@ -44,6 +44,8 @@ #undef GRUB_MEMORY_CPU_HEADER #include +#define SLRT_SIZE GRUB_PAGE_SIZE + #define SLB_MIN_ALIGNMENT 0x10000 #define SLB_SIZE 0x10000 @@ -66,22 +68,67 @@ grub_skl_set_module (const void *skl_base, grub_uint32_t size) struct grub_skl_info *info; struct grub_sl_header *module = (struct grub_sl_header *) skl_base; - if (skl_size < (8*GRUB_PAGE_SIZE)) + /* We need unused space after the module to fit SLRT there. */ + const grub_uint32_t max_size = SLB_SIZE - SLRT_SIZE; + + if (size > max_size) + { + grub_dprintf ("slaunch", "Possible SKL module is too large: %u > %u\n", + size, max_size); + return 0; + } + + if (module->length > size) + { + grub_dprintf ("slaunch", + "Possible SKL module has wrong measured size: %u > %u\n", + module->length, size); + return 0; + } + + if (module->skl_entry_point >= module->length) + { + grub_dprintf ("slaunch", + "Possible SKL module doesn't measure its entry: %u >= %u\n", + module->skl_entry_point, module->length); + return 0; + } + + if (module->skl_info_offset > module->length - sizeof (info->uuid)) + { + grub_dprintf ("slaunch", + "Possible SKL module doesn't measure info: %u > %u\n", + module->skl_info_offset, + module->length - sizeof (info->uuid)); + return 0; + } + + if (SLB_SIZE - module->bootloader_data_offset < SLRT_SIZE) + { + grub_dprintf ("slaunch", + "Possible SKL module has not enough space for SLRT: %u < %u\n", + SLB_SIZE - module->bootloader_data_offset, SLRT_SIZE); + return 0; + } + + if (module->length > module->bootloader_data_offset) { - grub_dprintf ("slaunch", "Possible SKL module too small\n"); + grub_dprintf ("slaunch", + "Possible SKL module measures bootloader data: %u (measured prefix) > %u (data offset)\n", + module->length, module->bootloader_data_offset); return 0; } info = (struct grub_skl_info *) ((grub_uint8_t *) module + module->skl_info_offset); if (info->version != GRUB_SKL_VERSION) { - grub_dprintf ("slaunch", "Possible SKL module incorrect version\n"); + grub_dprintf ("slaunch", "Possible SKL module has unexpected version\n"); return 0; } if (grub_memcmp (info->uuid, skl_info.uuid, 16)) { - grub_dprintf ("slaunch", "Possible SKL module incorrect UUID\n"); + grub_dprintf ("slaunch", "Possible SKL module has unexpected UUID\n"); return 0; } From 4d853d2b9a0bf1cc54096a0a33cdcb1489ddfc1a Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Tue, 19 Nov 2024 01:29:20 +0200 Subject: [PATCH 14/26] loader/slaunch/dlstub.c: better checks/errors Signed-off-by: Sergii Dmytruk --- grub-core/loader/slaunch/dlstub.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/grub-core/loader/slaunch/dlstub.c b/grub-core/loader/slaunch/dlstub.c index caf28fe26..f8917d6a2 100644 --- a/grub-core/loader/slaunch/dlstub.c +++ b/grub-core/loader/slaunch/dlstub.c @@ -93,6 +93,11 @@ void dl_entry (grub_uint64_t dl_ctx) /* Have to do this after EBS or things blow up */ grub_skinit_send_init_ipi_shorthand (); } + else + { + grub_error (GRUB_ERR_BUG, N_("unknown dynamic launch platform: %d"), state.edi); + return; + } if (!(grub_rdmsr (GRUB_MSR_X86_APICBASE) & GRUB_MSR_X86_APICBASE_BSP)) { @@ -110,13 +115,19 @@ void dl_entry (grub_uint64_t dl_ctx) state.ecx = slparams->dce_size; state.edx = 0; } - else /* SLP_AMD_SKINIT */ - state.eax = slparams->dce_base; + else if (state.edi == SLP_AMD_SKINIT) + { + state.eax = slparams->dce_base; + } grub_relocator32_boot (slparams->relocator, state, 0); } - else /* GRUB_SL_BOOT_TYPE_EFI */ + else if (slparams->boot_type == GRUB_SL_BOOT_TYPE_EFI) { dl_trampoline (slparams->dce_base, slparams->dce_size, state.edi); } + else + { + grub_error (GRUB_ERR_BUG, N_("unknown dynamic launch boot type: %d"), slparams->boot_type); + } } From d4b61e396af2d239be6d1d75b84ad0e44c8077e3 Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Tue, 19 Nov 2024 19:42:55 +0200 Subject: [PATCH 15/26] loader/slaunch/dlstub.c: start with zeroed relocator state Signed-off-by: Sergii Dmytruk --- grub-core/loader/slaunch/dlstub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/loader/slaunch/dlstub.c b/grub-core/loader/slaunch/dlstub.c index f8917d6a2..4a4fb451e 100644 --- a/grub-core/loader/slaunch/dlstub.c +++ b/grub-core/loader/slaunch/dlstub.c @@ -41,7 +41,7 @@ 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; + struct grub_relocator32_state state = {0}; grub_err_t err; state.edi = slparams->platform_type; From b64de8bffc826d3b7eeb1066b690a3813037a02c Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Tue, 19 Nov 2024 16:51:23 +0200 Subject: [PATCH 16/26] loader/slaunch/skl.c: better errors and checks Signed-off-by: Sergii Dmytruk --- grub-core/loader/slaunch/skl.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/grub-core/loader/slaunch/skl.c b/grub-core/loader/slaunch/skl.c index dd1dd6f27..a1bc7a0fa 100644 --- a/grub-core/loader/slaunch/skl.c +++ b/grub-core/loader/slaunch/skl.c @@ -157,12 +157,12 @@ grub_skl_setup_module (struct grub_slaunch_params *slparams) 1); if (err != GRUB_ERR_NONE) - return err; + return grub_error (err, N_("failed to allocate SLB")); v_addr = get_virtual_current_address (ch); p_addr = get_physical_target_address (ch); } - else + else if (slparams->boot_type == GRUB_SL_BOOT_TYPE_EFI) { #ifdef GRUB_MACHINE_EFI max_addr = ALIGN_DOWN ((GRUB_EFI_MAX_USABLE_ADDRESS - SLB_SIZE), @@ -181,6 +181,10 @@ grub_skl_setup_module (struct grub_slaunch_params *slparams) return GRUB_ERR_BUG; #endif } + else + { + return grub_error (GRUB_ERR_BUG, N_("unknown dynamic launch boot type: %d"), slparams->boot_type); + } grub_memcpy (v_addr, skl_module, skl_size); skl_module = (struct grub_sl_header *) v_addr; From 5fc2a42865e96feec987491b09c5412c632b94b7 Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Tue, 19 Nov 2024 16:52:32 +0200 Subject: [PATCH 17/26] include/grub/i386/txt.h: add missing #include Signed-off-by: Sergii Dmytruk --- include/grub/i386/txt.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/grub/i386/txt.h b/include/grub/i386/txt.h index 0b4e33191..f41ab7588 100644 --- a/include/grub/i386/txt.h +++ b/include/grub/i386/txt.h @@ -22,6 +22,7 @@ #define GRUB_TXT_H 1 #include +#include /* Intel TXT Software Developers Guide */ From 54100f582eadd2b64a614f5a5927630e26d2296d Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Tue, 19 Nov 2024 17:00:16 +0200 Subject: [PATCH 18/26] loader/slaunch/slrt.c: add NULL checks Not all boot methods are Linux EFI boot methods. Signed-off-by: Sergii Dmytruk --- grub-core/loader/slaunch/slrt.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/grub-core/loader/slaunch/slrt.c b/grub-core/loader/slaunch/slrt.c index 6f9bf4e67..b336780ee 100644 --- a/grub-core/loader/slaunch/slrt.c +++ b/grub-core/loader/slaunch/slrt.c @@ -62,13 +62,14 @@ grub_setup_slrt_policy (struct grub_slaunch_params *slparams, struct grub_slr_policy_entry *platform_entry) { struct linux_kernel_params *boot_params = slparams->boot_params; - struct grub_efi_info *efi_info; + struct grub_efi_info *efi_info = NULL; grub_uint64_t hi_val; int i = 0; /* A bit of work to extract the v2.08 EFI info from the linux params */ - efi_info = (struct grub_efi_info *)((grub_uint8_t *)&(boot_params->v0208) - + 2*sizeof(grub_uint32_t)); + if (boot_params != NULL) + efi_info = (struct grub_efi_info *)((grub_uint8_t *)&(boot_params->v0208) + + 2*sizeof(grub_uint32_t)); /* the SLR table should be measured too, at least parts of it */ slr_policy_staging->policy_entries[i].pcr = 18; @@ -78,15 +79,20 @@ grub_setup_slrt_policy (struct grub_slaunch_params *slparams, grub_strcpy (slr_policy_staging->policy_entries[i].evt_info, "Measured SLR Table"); i++; - /* boot params have everything needed to setup policy except OS2MLE data */ - slr_policy_staging->policy_entries[i].pcr = 18; - slr_policy_staging->policy_entries[i].entity_type = GRUB_SLR_ET_BOOT_PARAMS; - slr_policy_staging->policy_entries[i].entity = (grub_uint64_t)(grub_addr_t)boot_params; - slr_policy_staging->policy_entries[i].size = GRUB_PAGE_SIZE; - grub_strcpy (slr_policy_staging->policy_entries[i].evt_info, "Measured boot parameters"); + if (boot_params != NULL) + { + /* boot params have everything needed to setup policy except OS2MLE data */ + slr_policy_staging->policy_entries[i].pcr = 18; + slr_policy_staging->policy_entries[i].entity_type = GRUB_SLR_ET_BOOT_PARAMS; + slr_policy_staging->policy_entries[i].entity = (grub_uint64_t)(grub_addr_t)boot_params; + slr_policy_staging->policy_entries[i].size = GRUB_PAGE_SIZE; + grub_strcpy (slr_policy_staging->policy_entries[i].evt_info, "Measured boot parameters"); + } + else + slr_policy_staging->policy_entries[i].entity_type = GRUB_SLR_ET_UNUSED; i++; - if (boot_params->setup_data) + if (boot_params != NULL && boot_params->setup_data) { slr_policy_staging->policy_entries[i].pcr = 18; slr_policy_staging->policy_entries[i].entity_type = GRUB_SLR_ET_SETUP_DATA; @@ -98,7 +104,7 @@ grub_setup_slrt_policy (struct grub_slaunch_params *slparams, slr_policy_staging->policy_entries[i].entity_type = GRUB_SLR_ET_UNUSED; i++; - if (boot_params->cmd_line_ptr) + if (boot_params != NULL && boot_params->cmd_line_ptr) { slr_policy_staging->policy_entries[i].pcr = 18; slr_policy_staging->policy_entries[i].entity_type = GRUB_SLR_ET_CMDLINE; @@ -112,7 +118,7 @@ grub_setup_slrt_policy (struct grub_slaunch_params *slparams, slr_policy_staging->policy_entries[i].entity_type = GRUB_SLR_ET_UNUSED; i++; - if (!grub_memcmp(&efi_info->efi_signature, "EL64", sizeof(grub_uint32_t))) + if (efi_info != NULL && !grub_memcmp(&efi_info->efi_signature, "EL64", sizeof(grub_uint32_t))) { slr_policy_staging->policy_entries[i].pcr = 18; slr_policy_staging->policy_entries[i].entity_type = GRUB_SLR_ET_UEFI_MEMMAP; @@ -126,7 +132,7 @@ grub_setup_slrt_policy (struct grub_slaunch_params *slparams, slr_policy_staging->policy_entries[i].entity_type = GRUB_SLR_ET_UNUSED; i++; - if (boot_params->ramdisk_image) + if (boot_params != NULL && boot_params->ramdisk_image) { slr_policy_staging->policy_entries[i].pcr = 17; slr_policy_staging->policy_entries[i].entity_type = GRUB_SLR_ET_RAMDISK; From d92ba0911ab1b71cb54bc34c094d3bedd3b3c4fa Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Wed, 20 Nov 2024 00:47:45 +0200 Subject: [PATCH 19/26] include/grub/slaunch.h: add missing forward declaration Signed-off-by: Sergii Dmytruk --- include/grub/slaunch.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/grub/slaunch.h b/include/grub/slaunch.h index 6d542f681..753c48514 100644 --- a/include/grub/slaunch.h +++ b/include/grub/slaunch.h @@ -42,6 +42,7 @@ struct linux_kernel_params; struct linux_i386_kernel_header; struct grub_relocator; struct grub_efi_loaded_image; +struct grub_slr_entry_hdr; typedef struct grub_efi_loaded_image grub_efi_loaded_image_t; struct grub_slaunch_params From 6e77edd2615300a330b79a9971b78411c2aafba4 Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Tue, 19 Nov 2024 17:01:31 +0200 Subject: [PATCH 20/26] loader/slaunch/skl.c: fix a comment typo Signed-off-by: Sergii Dmytruk --- grub-core/loader/slaunch/skl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/loader/slaunch/skl.c b/grub-core/loader/slaunch/skl.c index a1bc7a0fa..34c4cbd39 100644 --- a/grub-core/loader/slaunch/skl.c +++ b/grub-core/loader/slaunch/skl.c @@ -244,7 +244,7 @@ grub_skl_prepare_bootloader_data (struct grub_slaunch_params *slparams) /* Setup the DRTM log info */ grub_setup_slrt_log_info (slparams); - /* Final move of staging inforation into the actual SLRT */ + /* Final move of staging information into the actual SLRT */ grub_setup_slr_table (slparams, (struct grub_slr_entry_hdr *)&slr_amd_info_staging); return GRUB_ERR_NONE; From 8c705ef29a29356ffa418d4ad5646082e74b5409 Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Tue, 19 Nov 2024 17:02:19 +0200 Subject: [PATCH 21/26] slaunch: introduce a hook for filling SLRT policy Signed-off-by: Sergii Dmytruk --- grub-core/loader/slaunch/slrt.c | 14 +++++++++++++- include/grub/slaunch.h | 10 ++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/grub-core/loader/slaunch/slrt.c b/grub-core/loader/slaunch/slrt.c index b336780ee..0135137c2 100644 --- a/grub-core/loader/slaunch/slrt.c +++ b/grub-core/loader/slaunch/slrt.c @@ -30,7 +30,7 @@ #include #include -#define SLR_MAX_POLICY_ENTRIES 7 +#define SLR_MAX_POLICY_ENTRIES 16 /* Area to collect and build SLR Table information */ static grub_uint8_t slr_policy_buf[GRUB_PAGE_SIZE] = {0}; @@ -71,6 +71,10 @@ grub_setup_slrt_policy (struct grub_slaunch_params *slparams, efi_info = (struct grub_efi_info *)((grub_uint8_t *)&(boot_params->v0208) + 2*sizeof(grub_uint32_t)); + if (slparams->fill_policy_hook) + i += slparams->fill_policy_hook (1, &slr_policy_staging->policy_entries[i], + slparams->fill_policy_hook_data); + /* the SLR table should be measured too, at least parts of it */ slr_policy_staging->policy_entries[i].pcr = 18; slr_policy_staging->policy_entries[i].entity_type = GRUB_SLR_ET_SLRT; @@ -159,6 +163,14 @@ grub_setup_slrt_policy (struct grub_slaunch_params *slparams, } else slr_policy_staging->policy_entries[i].entity_type = GRUB_SLR_ET_UNUSED; + + if (slparams->fill_policy_hook) + i += slparams->fill_policy_hook (0, &slr_policy_staging->policy_entries[i], + slparams->fill_policy_hook_data); + + /* Mark any unused entries with an appropriate type */ + for (; i < SLR_MAX_POLICY_ENTRIES; ++i) + slr_policy_staging->policy_entries[i].entity_type = GRUB_SLR_ET_UNUSED; } void diff --git a/include/grub/slaunch.h b/include/grub/slaunch.h index 753c48514..b77c23426 100644 --- a/include/grub/slaunch.h +++ b/include/grub/slaunch.h @@ -43,6 +43,7 @@ struct linux_i386_kernel_header; struct grub_relocator; struct grub_efi_loaded_image; struct grub_slr_entry_hdr; +struct grub_slr_policy_entry; typedef struct grub_efi_loaded_image grub_efi_loaded_image_t; struct grub_slaunch_params @@ -69,6 +70,15 @@ struct grub_slaunch_params grub_uint32_t dce_size; grub_uint64_t tpm_evt_log_base; grub_uint32_t tpm_evt_log_size; + + /* + * Can be NULL. Called twice: when starting to add standard SLRT entries and + * after adding them. Should returns the number of entries added by the hook. + */ + int (*fill_policy_hook)(int is_start, + struct grub_slr_policy_entry *next_entry, void *data); + /* Data passed to fill_policy_hook. */ + void *fill_policy_hook_data; }; struct grub_efi_info From d00a1a6597a78114e1ecc5a9a62b1aa794cafba1 Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Wed, 22 Nov 2023 21:08:35 +0200 Subject: [PATCH 22/26] multiboot: Make GRUB_MULTIBOOT(make_mbi) return MBI's size GRUB_MULTIBOOT(get_mbi_size) returns an upper bound on MBI's size instead of the actual size. It could also be used for measurements after zeroing unused parts of the buffer, but using an actual size seems like a better option as the same MBI will always have the same hash regardless of the amount of extra memory that follows it. Signed-off-by: Sergii Dmytruk --- grub-core/loader/i386/multiboot_mbi.c | 4 +++- grub-core/loader/multiboot.c | 3 ++- grub-core/loader/multiboot_mbi2.c | 6 ++++-- include/grub/multiboot.h | 2 +- include/grub/multiboot2.h | 3 ++- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/grub-core/loader/i386/multiboot_mbi.c b/grub-core/loader/i386/multiboot_mbi.c index bdaf67ad0..f058f4645 100644 --- a/grub-core/loader/i386/multiboot_mbi.c +++ b/grub-core/loader/i386/multiboot_mbi.c @@ -453,7 +453,7 @@ retrieve_video_parameters (struct multiboot_info *mbi, } grub_err_t -grub_multiboot_make_mbi (grub_uint32_t *target) +grub_multiboot_make_mbi (grub_uint32_t *target, grub_uint32_t *size) { struct multiboot_info *mbi; struct multiboot_mod_list *modlist; @@ -621,6 +621,8 @@ grub_multiboot_make_mbi (grub_uint32_t *target) return err; #endif + *size = (char *) ptrorig - (char *) mbi; + return GRUB_ERR_NONE; } diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c index 7110bae13..d9466f0e5 100644 --- a/grub-core/loader/multiboot.c +++ b/grub-core/loader/multiboot.c @@ -177,6 +177,7 @@ static grub_err_t grub_multiboot_boot (void) { grub_err_t err; + grub_uint32_t mbi_size; #ifdef GRUB_USE_MULTIBOOT2 struct grub_relocator32_state state = MULTIBOOT2_INITIAL_STATE; @@ -185,7 +186,7 @@ grub_multiboot_boot (void) #endif state.MULTIBOOT_ENTRY_REGISTER = GRUB_MULTIBOOT (payload_eip); - err = GRUB_MULTIBOOT (make_mbi) (&state.MULTIBOOT_MBI_REGISTER); + err = GRUB_MULTIBOOT (make_mbi) (&state.MULTIBOOT_MBI_REGISTER, &mbi_size); if (err) return err; diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c index 00a48413c..1945b3ac6 100644 --- a/grub-core/loader/multiboot_mbi2.c +++ b/grub-core/loader/multiboot_mbi2.c @@ -701,7 +701,7 @@ retrieve_video_parameters (grub_properly_aligned_t **ptrorig) } grub_err_t -grub_multiboot2_make_mbi (grub_uint32_t *target) +grub_multiboot2_make_mbi (grub_uint32_t *target, grub_uint32_t *size) { grub_properly_aligned_t *ptrorig; grub_properly_aligned_t *mbistart; @@ -1002,7 +1002,9 @@ grub_multiboot2_make_mbi (grub_uint32_t *target) / sizeof (grub_properly_aligned_t); } - ((grub_uint32_t *) mbistart)[0] = (char *) ptrorig - (char *) mbistart; + *size = (char *) ptrorig - (char *) mbistart; + + ((grub_uint32_t *) mbistart)[0] = *size; ((grub_uint32_t *) mbistart)[1] = 0; return GRUB_ERR_NONE; diff --git a/include/grub/multiboot.h b/include/grub/multiboot.h index d8847f753..020c54847 100644 --- a/include/grub/multiboot.h +++ b/include/grub/multiboot.h @@ -41,7 +41,7 @@ void grub_multiboot (int argc, char *argv[]); void grub_module (int argc, char *argv[]); void grub_multiboot_set_accepts_video (int val); -grub_err_t grub_multiboot_make_mbi (grub_uint32_t *target); +grub_err_t grub_multiboot_make_mbi (grub_uint32_t *target, grub_uint32_t *size); void grub_multiboot_free_mbi (void); grub_err_t grub_multiboot_init_mbi (int argc, char *argv[]); grub_err_t grub_multiboot_add_module (grub_addr_t start, grub_size_t size, diff --git a/include/grub/multiboot2.h b/include/grub/multiboot2.h index b90aa6989..3417a1447 100644 --- a/include/grub/multiboot2.h +++ b/include/grub/multiboot2.h @@ -33,7 +33,8 @@ void grub_multiboot2 (int argc, char *argv[]); void grub_module2 (int argc, char *argv[]); void grub_multiboot2_set_accepts_video (int val); -grub_err_t grub_multiboot2_make_mbi (grub_uint32_t *target); +grub_err_t grub_multiboot2_make_mbi (grub_uint32_t *target, + grub_uint32_t *size); void grub_multiboot2_free_mbi (void); grub_err_t grub_multiboot2_init_mbi (int argc, char *argv[]); grub_err_t grub_multiboot2_add_module (grub_addr_t start, grub_size_t size, From e383612af9f211145ccb8fc47455e88c20d908f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=BBygowski?= Date: Thu, 1 Sep 2022 17:58:53 +0200 Subject: [PATCH 23/26] multiboot2: Support TXT and SKINIT slaunch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The code makes sure that MBI entry goes first in DRTM, so the payload can measure it first on launch. Then goes SLRT and other typical entries, while MB2 modules are added at the end. Signed-off-by: Michał Żygowski Signed-off-by: Tomasz Żyjewski Signed-off-by: Krystian Hebel Signed-off-by: Sergii Dmytruk --- grub-core/loader/multiboot.c | 11 +++ grub-core/loader/multiboot_elfxx.c | 90 ++++++++++++++++++- grub-core/loader/multiboot_mbi2.c | 138 +++++++++++++++++++++++++++++ grub-core/loader/slaunch/dlstub.c | 2 +- grub-core/loader/slaunch/skl.c | 2 +- include/grub/i386/txt.h | 2 + include/grub/multiboot2.h | 3 + include/grub/slaunch.h | 1 + include/grub/slr_table.h | 2 + 9 files changed, 248 insertions(+), 3 deletions(-) diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c index d9466f0e5..fb81eba51 100644 --- a/grub-core/loader/multiboot.c +++ b/grub-core/loader/multiboot.c @@ -50,6 +50,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -191,6 +192,16 @@ grub_multiboot_boot (void) if (err) return err; +#ifdef GRUB_USE_MULTIBOOT2 + if (grub_slaunch_platform_type () != SLP_NONE) + { + err = grub_multiboot2_perform_slaunch (state.MULTIBOOT_MBI_REGISTER, + mbi_size); + if (err) + return grub_error (err, N_("failed to perform Multiboot2 slaunch")); + } +#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..ee05a4d99 100644 --- a/grub-core/loader/multiboot_elfxx.c +++ b/grub-core/loader/multiboot_elfxx.c @@ -44,7 +44,9 @@ #error "I'm confused" #endif +#include #include +#include #define CONCAT(a,b) CONCAT_(a, b) #define CONCAT_(a,b) a ## b @@ -73,6 +75,11 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld) grub_off_t phlimit; unsigned int i; void *source = NULL; +#ifdef GRUB_USE_MULTIBOOT2 + struct grub_slaunch_params *slparams = &grub_multiboot2_slparams; + grub_uint32_t mle_hdr_offset; + struct grub_txt_mle_header *mle_hdr; +#endif if (ehdr->e_ident[EI_MAG0] != ELFMAG0 || ehdr->e_ident[EI_MAG1] != ELFMAG1 @@ -127,6 +134,18 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld) { load_size = highest_load - mld->link_base_addr; +#ifndef GRUB_USE_MULTIBOOT2 + if (grub_slaunch_platform_type () != SLP_NONE) + return grub_error (GRUB_ERR_BAD_OS, "Only multiboot2 supported for slaunch"); +#else + if (grub_slaunch_platform_type () == SLP_INTEL_TXT) + { + /* Do not go below GRUB_TXT_PMR_ALIGN. */ + if (mld->align < GRUB_TXT_PMR_ALIGN) + mld->align = GRUB_TXT_PMR_ALIGN; + } +#endif + 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 +167,57 @@ 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); + +#ifdef GRUB_USE_MULTIBOOT2 + grub_memset (source, 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_NONE) + { + slparams->mle_start = mld->load_base_addr; + slparams->mle_mem = source; + slparams->mle_ptab_size = 0; + } + + if (grub_slaunch_platform_type () == SLP_INTEL_TXT) + { + /* + * 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); + + 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; + { +#ifdef GRUB_USE_MULTIBOOT2 + /* TODO: support non-relocatable */ + if (grub_slaunch_platform_type () != SLP_NONE) + return grub_error (GRUB_ERR_BAD_OS, "Non-relocatable ELF not supported with slaunch"); +#endif + + mld->load_base_addr = mld->link_base_addr; + } grub_dprintf ("multiboot_loader", "relocatable=%d, link_base_addr=0x%x, " "load_base_addr=0x%x\n", mld->relocatable, @@ -213,6 +280,27 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld) } } +#ifdef GRUB_USE_MULTIBOOT2 + if (grub_slaunch_platform_type () != SLP_NONE) + { + /* 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 (mle_hdr->uuid, GRUB_TXT_MLE_UUID, 16)) + { + break; + } + } + + if (mle_hdr_offset >= 0x1000) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "MLE header not found"); + + slparams->mle_header_offset = mle_hdr_offset; + slparams->mle_size = mle_hdr->mle_end - mle_hdr->mle_start; + } +#endif + 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..86941762c 100644 --- a/grub-core/loader/multiboot_mbi2.c +++ b/grub-core/loader/multiboot_mbi2.c @@ -36,6 +36,11 @@ #include #include #include +#include +#include +#include +#include +#include #if defined (GRUB_MACHINE_EFI) #include @@ -63,6 +68,12 @@ struct module int cmdline_size; }; +struct fill_policy_hook_data +{ + grub_uint32_t mbi_target; + grub_uint32_t mbi_size; +}; + static struct module *modules, *modules_last; static grub_size_t cmdline_size; static grub_size_t total_modcmd; @@ -76,6 +87,8 @@ static void *elf_sections; static int keep_bs = 0; static grub_uint32_t load_base_addr; +struct grub_slaunch_params grub_multiboot2_slparams = {0}; + void grub_multiboot2_add_elfsyms (grub_size_t num, grub_size_t entsize, unsigned shndx, void *data) @@ -119,6 +132,7 @@ grub_multiboot2_load (grub_file_t file, const char *filename) grub_uint32_t console_required = 0; struct multiboot_header_tag_framebuffer *fbtag = NULL; int accepted_consoles = GRUB_MULTIBOOT2_CONSOLE_EGA_TEXT; + struct grub_slaunch_params *slparams = &grub_multiboot2_slparams; mbi_load_data_t mld; mld.mbi_ver = 2; @@ -275,8 +289,18 @@ grub_multiboot2_load (grub_file_t file, const char *filename) "load address tag without entry address tag"); } + if (grub_slaunch_platform_type () != SLP_NONE) + { + slparams->relocator = grub_multiboot2_relocator; + slparams->boot_type = GRUB_SL_BOOT_TYPE_MB2; + slparams->platform_type = grub_slaunch_platform_type (); + } + if (addr_tag) { + if (slparams->platform_type != SLP_NONE) + 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 +414,36 @@ 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 (slparams->platform_type != SLP_NONE) + { + grub_relocator_chunk_t ch; + + 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; + + /* It's OK to call this for AMD SKINIT because SKL erases the log before use. */ + if (slparams->platform_type == SLP_INTEL_TXT || slparams->platform_type == SLP_AMD_SKINIT) + grub_txt_init_tpm_event_log (get_virtual_current_address (ch), + slparams->tpm_evt_log_size); + + grub_dprintf ("multiboot_loader", "tpm_evt_log_base = 0x%lx, tpm_evt_log_size = 0x%x\n", + (unsigned long) slparams->tpm_evt_log_base, + (unsigned) slparams->tpm_evt_log_size); + + if (slparams->platform_type == SLP_INTEL_TXT) + grub_txt_setup_mle_ptab (slparams); + } + return err; } @@ -1128,3 +1182,87 @@ grub_multiboot2_set_bootdev (void) bootdev_set = 1; } + +static int +fill_policy_hook(int is_start, struct grub_slr_policy_entry *next_entry, + void *data) +{ + int i = 0; + unsigned m; + struct module *cur; + struct fill_policy_hook_data *hook_data = data; + + if (is_start) + { + next_entry->pcr = 18; + next_entry->entity_type = GRUB_SLR_ET_MULTIBOOT2_INFO; + next_entry->entity = hook_data->mbi_target; + next_entry->size = hook_data->mbi_size; + next_entry->flags = 0; + grub_strcpy (next_entry->evt_info, "Measured MB2 information"); + i = 1; + } + else + { + for (m = 0, cur = modules; m < modcnt; m++, cur = cur->next) + { + next_entry[i].pcr = 17; + next_entry[i].entity_type = GRUB_SLR_ET_MULTIBOOT2_MODULE; + next_entry[i].entity = cur->start; + next_entry[i].size = cur->size; + next_entry[i].flags = 0; + grub_strcpy (next_entry[i].evt_info, "Measured MB2 module"); + i++; + } + } + + return i; +} + +grub_err_t +grub_multiboot2_perform_slaunch (grub_uint32_t mbi_target, + grub_uint32_t mbi_size) +{ + grub_err_t err; + struct grub_slaunch_params *slparams = &grub_multiboot2_slparams; + struct grub_slr_entry_dl_info *dlinfo; + struct fill_policy_hook_data hook_data = { + .mbi_target = mbi_target, + .mbi_size = mbi_size, + }; + + slparams->boot_params_base = mbi_target; + + slparams->fill_policy_hook = &fill_policy_hook; + slparams->fill_policy_hook_data = &hook_data; + + if (slparams->platform_type == SLP_INTEL_TXT) + { + err = grub_txt_boot_prepare (slparams); + if (err != GRUB_ERR_NONE) + return grub_error (err, "TXT boot preparation failed"); + } + else if (slparams->platform_type == SLP_AMD_SKINIT) + { + err = grub_skl_setup_module (slparams); + if (err != GRUB_ERR_NONE) + return grub_error (err, "Failed to setup SKL for Multiboot2"); + + err = grub_skl_prepare_bootloader_data (slparams); + if (err != GRUB_ERR_NONE) + return grub_error (err, "SKL preparations have failed"); + } + else + return grub_error (GRUB_ERR_BAD_DEVICE, + N_("Unknown secure launcher platform type: %d\n"), slparams->platform_type); + + grub_dprintf ("multiboot_loader", "slr_table_base = 0x%lx, slr_table_size = 0x%x\n", + (unsigned long) slparams->slr_table_base, + (unsigned) slparams->slr_table_size); + + dlinfo = grub_slr_next_entry_by_tag (slparams->slr_table_mem, NULL, GRUB_SLR_ENTRY_DL_INFO); + dl_entry ((grub_uint64_t)(grub_addr_t) &dlinfo->bl_context); + + /* If this returns, something failed miserably */ + return GRUB_ERR_BAD_DEVICE; +} diff --git a/grub-core/loader/slaunch/dlstub.c b/grub-core/loader/slaunch/dlstub.c index 4a4fb451e..9d336392e 100644 --- a/grub-core/loader/slaunch/dlstub.c +++ b/grub-core/loader/slaunch/dlstub.c @@ -105,7 +105,7 @@ void dl_entry (grub_uint64_t dl_ctx) return; } - if (slparams->boot_type == GRUB_SL_BOOT_TYPE_LINUX) + if (slparams->boot_type == GRUB_SL_BOOT_TYPE_LINUX || slparams->boot_type == GRUB_SL_BOOT_TYPE_MB2) { if (state.edi == SLP_INTEL_TXT) { diff --git a/grub-core/loader/slaunch/skl.c b/grub-core/loader/slaunch/skl.c index 34c4cbd39..15089bd70 100644 --- a/grub-core/loader/slaunch/skl.c +++ b/grub-core/loader/slaunch/skl.c @@ -148,7 +148,7 @@ grub_skl_setup_module (struct grub_slaunch_params *slparams) grub_addr_t max_addr; #endif - if (slparams->boot_type == GRUB_SL_BOOT_TYPE_LINUX) + if (slparams->boot_type == GRUB_SL_BOOT_TYPE_LINUX || slparams->boot_type == GRUB_SL_BOOT_TYPE_MB2) { err = grub_relocator_alloc_chunk_align (slparams->relocator, &ch, 0, UP_TO_TOP32(SLB_SIZE), SLB_SIZE, diff --git a/include/grub/i386/txt.h b/include/grub/i386/txt.h index f41ab7588..25e38bc98 100644 --- a/include/grub/i386/txt.h +++ b/include/grub/i386/txt.h @@ -420,6 +420,8 @@ struct grub_txt_sinit_memory_descriptor_records /* 2.1 MLE Architecture Overview */ /* Table 1. MLE Header structure */ +#define GRUB_TXT_MLE_UUID "\x5a\xac\x82\x90\x6f\x47\xa7\x74\x0f\x5c\x55\xa2\xcb\x51\xb6\x42" + struct grub_txt_mle_header { grub_uint8_t uuid[16]; diff --git a/include/grub/multiboot2.h b/include/grub/multiboot2.h index 3417a1447..1a3be5f48 100644 --- a/include/grub/multiboot2.h +++ b/include/grub/multiboot2.h @@ -28,6 +28,7 @@ #include extern struct grub_relocator *grub_multiboot2_relocator; +extern struct grub_slaunch_params grub_multiboot2_slparams; void grub_multiboot2 (int argc, char *argv[]); void grub_module2 (int argc, char *argv[]); @@ -43,6 +44,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_perform_slaunch (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); diff --git a/include/grub/slaunch.h b/include/grub/slaunch.h index b77c23426..e9ab97a09 100644 --- a/include/grub/slaunch.h +++ b/include/grub/slaunch.h @@ -33,6 +33,7 @@ #define GRUB_SL_BOOT_TYPE_INVALID 0 #define GRUB_SL_BOOT_TYPE_LINUX 1 #define GRUB_SL_BOOT_TYPE_EFI 2 +#define GRUB_SL_BOOT_TYPE_MB2 3 #define GRUB_KERNEL_INFO_HEADER "LToP" #define GRUB_KERNEL_INFO_MIN_SIZE_TOTAL 12 diff --git a/include/grub/slr_table.h b/include/grub/slr_table.h index f5e891f7d..8e37bd2bd 100644 --- a/include/grub/slr_table.h +++ b/include/grub/slr_table.h @@ -72,6 +72,8 @@ #define GRUB_SLR_ET_CMDLINE 0x0004 #define GRUB_SLR_ET_UEFI_MEMMAP 0x0005 #define GRUB_SLR_ET_RAMDISK 0x0006 +#define GRUB_SLR_ET_MULTIBOOT2_INFO 0x0007 +#define GRUB_SLR_ET_MULTIBOOT2_MODULE 0x0008 #define GRUB_SLR_ET_TXT_OS2MLE 0x0010 #define GRUB_SLR_ET_UNUSED 0xffff From a655a9e31e3d6408441bf08817cfd997630913d8 Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Mon, 25 Nov 2024 01:05:06 +0200 Subject: [PATCH 24/26] grub-core/loader/slaunch/psp.c: simplify is_drtm_device() Just return bool. Signed-off-by: Sergii Dmytruk --- grub-core/loader/slaunch/psp.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/grub-core/loader/slaunch/psp.c b/grub-core/loader/slaunch/psp.c index 1513d2aed..a6c7c39d3 100644 --- a/grub-core/loader/slaunch/psp.c +++ b/grub-core/loader/slaunch/psp.c @@ -153,7 +153,7 @@ get_psp_bar_addr (void) return (grub_uint64_t) pspbaselo; } -static const struct pci_psp_device * +static bool is_drtm_device (grub_uint16_t vendor_id, grub_uint16_t dev_id) { grub_uint32_t max_psp_devs = sizeof (psp_devs_list) / sizeof (psp_devs_list[0]); @@ -174,10 +174,10 @@ is_drtm_device (grub_uint16_t vendor_id, grub_uint16_t dev_id) { grub_dprintf ("slaunch", "DRTM: AMD SP device (PCI info: 0x%04x, 0x%04x) does not have PSP\n", psp->vendor_id, psp->dev_id); - psp = NULL; + return false; } - return psp; + return true; } grub_err_t @@ -186,7 +186,6 @@ grub_psp_discover (void) grub_pci_device_t dev; grub_pci_address_t addr; grub_uint16_t vendor_id, dev_id; - const struct pci_psp_device *psp = NULL; grub_uint64_t bar2_addr = 0; for (dev.bus = 0; dev.bus < GRUB_PCI_NUM_BUS; dev.bus++) @@ -199,15 +198,13 @@ grub_psp_discover (void) vendor_id = grub_pci_read_word (addr); addr = grub_pci_make_address (dev, 2); dev_id = grub_pci_read_word (addr); - psp = is_drtm_device (vendor_id, dev_id); - if (psp) + if (is_drtm_device (vendor_id, dev_id)) goto psp_found; } } } - if (!psp) - return grub_error (GRUB_ERR_BAD_DEVICE, N_("DRTM: failed to find PSP\n")); + return grub_error (GRUB_ERR_BAD_DEVICE, N_("DRTM: failed to find PSP\n")); psp_found: init_drtm_device (dev); From 8b35409955d3a71197e268b46aae3954b98a2c8e Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Mon, 25 Nov 2024 01:05:55 +0200 Subject: [PATCH 25/26] grub-core/loader/slaunch/psp.c: fix comment capitalization Signed-off-by: Sergii Dmytruk --- grub-core/loader/slaunch/psp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/loader/slaunch/psp.c b/grub-core/loader/slaunch/psp.c index a6c7c39d3..b4a3ee360 100644 --- a/grub-core/loader/slaunch/psp.c +++ b/grub-core/loader/slaunch/psp.c @@ -251,7 +251,7 @@ init_drtm_device (grub_pci_device_t dev) pci_cmd |= 0x4; grub_pci_write_word (pci_cmd_addr, pci_cmd); - /* SET PCI latency timer */ + /* Set PCI latency timer */ lat = 0; lat_addr = grub_pci_make_address (dev, GRUB_PCI_REG_LAT_TIMER); lat = grub_pci_read_byte (lat_addr); From 805d4f39d323ab39d5794195a75efb1dcdcf170c Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Mon, 25 Nov 2024 01:15:30 +0200 Subject: [PATCH 26/26] grub-core/loader/slaunch/psp.c: drop extra assignments from init_drtm_device() Signed-off-by: Sergii Dmytruk --- grub-core/loader/slaunch/psp.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/grub-core/loader/slaunch/psp.c b/grub-core/loader/slaunch/psp.c index b4a3ee360..9ecd6db94 100644 --- a/grub-core/loader/slaunch/psp.c +++ b/grub-core/loader/slaunch/psp.c @@ -224,19 +224,15 @@ init_drtm_device (grub_pci_device_t dev) grub_pci_address_t pci_cmd_addr, pin_addr, lat_addr; /* Enable memory space access for PSP */ - pci_cmd = 0; pci_cmd_addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); - pci_cmd = grub_pci_read_word (pci_cmd_addr); - pci_cmd |= 0x2; + pci_cmd = grub_pci_read_word (pci_cmd_addr) | 0x2; grub_pci_write_word (pci_cmd_addr, pci_cmd); /* Enable PCI interrupts */ - pin = 0; pin_addr = grub_pci_make_address (dev, GRUB_PCI_REG_IRQ_PIN); pin = grub_pci_read_byte (pin_addr); if (pin) { - pci_cmd = 0; pci_cmd = grub_pci_read_word (pci_cmd_addr); if (pci_cmd & 0x400) { @@ -246,13 +242,10 @@ init_drtm_device (grub_pci_device_t dev) } /* Set PSP at bus master */ - pci_cmd = 0; - pci_cmd = grub_pci_read_word (pci_cmd_addr); - pci_cmd |= 0x4; + pci_cmd = grub_pci_read_word (pci_cmd_addr) | 0x4; grub_pci_write_word (pci_cmd_addr, pci_cmd); /* Set PCI latency timer */ - lat = 0; lat_addr = grub_pci_make_address (dev, GRUB_PCI_REG_LAT_TIMER); lat = grub_pci_read_byte (lat_addr); if (lat < 16)