diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 1dc0f75603..c5429394cf 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/i386/linux.c b/grub-core/loader/i386/linux.c index dcfbf619de..8ac07229c9 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/i386/multiboot_mbi.c b/grub-core/loader/i386/multiboot_mbi.c index bdaf67ad01..f058f4645e 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 7110bae13c..fb81eba519 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+"); @@ -177,6 +178,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,11 +187,21 @@ 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; +#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 1edad05948..ee05a4d99d 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 00a48413c0..86941762c2 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; } @@ -701,7 +755,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 +1056,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; @@ -1126,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 9c052f2be8..9d336392e1 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 @@ -37,9 +39,9 @@ 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_relocator32_state state; + struct grub_slr_bl_context *bl_ctx = (struct grub_slr_bl_context *)(grub_addr_t)dl_ctx; + struct grub_slaunch_params *slparams = (struct grub_slaunch_params *)(grub_addr_t)bl_ctx->context; + struct grub_relocator32_state state = {0}; grub_err_t err; state.edi = slparams->platform_type; @@ -50,7 +52,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")); @@ -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 ) @@ -85,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)) { @@ -92,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) { @@ -102,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); + } } diff --git a/grub-core/loader/slaunch/i386_linux.c b/grub-core/loader/slaunch/i386_linux.c index 3b2b5b81b4..2a830c0b3f 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/psp.c b/grub-core/loader/slaunch/psp.c index 80b8eaec21..9ecd6db94a 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); @@ -227,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) { @@ -249,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; + /* Set PCI latency timer */ lat_addr = grub_pci_make_address (dev, GRUB_PCI_REG_LAT_TIMER); lat = grub_pci_read_byte (lat_addr); if (lat < 16) @@ -377,10 +367,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 != 0) tmr_count++; if (tmr_count > GRUB_UINT_MAX) diff --git a/grub-core/loader/slaunch/skinit.c b/grub-core/loader/slaunch/skinit.c index cd469f4f2b..61ca8aa59a 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; @@ -145,20 +146,16 @@ 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); } - err = grub_psp_discover (); - if (err != GRUB_ERR_NONE) - return err; - grub_drtm_kick_psp (); err = grub_drtm_get_capability (); @@ -192,7 +189,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 9bff0076f1..15089bd70c 100644 --- a/grub-core/loader/slaunch/skl.c +++ b/grub-core/loader/slaunch/skl.c @@ -44,7 +44,10 @@ #undef GRUB_MEMORY_CPU_HEADER #include -#define SKL_MIN_AIGNMENT 0x10000 +#define SLRT_SIZE GRUB_PAGE_SIZE + +#define SLB_MIN_ALIGNMENT 0x10000 +#define SLB_SIZE 0x10000 static struct grub_skl_info skl_info = { .uuid = { @@ -63,28 +66,74 @@ 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; + + /* 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 (skl_size < (8*GRUB_PAGE_SIZE)) + if (module->skl_info_offset > module->length - sizeof (info->uuid)) { - grub_dprintf ("slaunch", "Possible SKL module too small\n"); + grub_dprintf ("slaunch", + "Possible SKL module doesn't measure info: %u > %u\n", + module->skl_info_offset, + module->length - sizeof (info->uuid)); return 0; } - info = (struct grub_skl_info *) ((grub_uint8_t *) skl_module + skl_module->skl_info_offset); + 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 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; } + skl_module = module; + skl_size = size; return 1; } @@ -94,37 +143,47 @@ 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) + 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, 0xFFFFFFFF, skl_size, - SKL_MIN_AIGNMENT, + 0, UP_TO_TOP32(SLB_SIZE), SLB_SIZE, + SLB_MIN_ALIGNMENT, GRUB_RELOCATOR_PREFERENCE_HIGH, 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) { - max_addr = ALIGN_DOWN ((GRUB_EFI_MAX_USABLE_ADDRESS - skl_size), +#ifdef GRUB_MACHINE_EFI + 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 + SKL_MIN_AIGNMENT), + GRUB_EFI_BYTES_TO_PAGES(SLB_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; +#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); @@ -136,7 +195,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; @@ -147,12 +206,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 @@ -185,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; diff --git a/grub-core/loader/slaunch/slaunch.c b/grub-core/loader/slaunch/slaunch.c index 874a5810cf..39e6e0ad8a 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 (); diff --git a/grub-core/loader/slaunch/slrt.c b/grub-core/loader/slaunch/slrt.c index 26fc874ec2..0135137c21 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}; @@ -62,13 +62,18 @@ 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)); + + 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; @@ -78,15 +83,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)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 +108,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 +122,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 +136,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; @@ -153,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 @@ -160,12 +178,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_mem + 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 +205,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 +226,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 +235,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 b07b1f37fe..3fcaa249b6 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); } } @@ -503,16 +503,42 @@ 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) { 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 @@ -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; @@ -560,7 +587,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 +595,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"); @@ -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")); @@ -668,14 +734,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); diff --git a/grub-core/loader/slaunch/x86_efi_linux.c b/grub-core/loader/slaunch/x86_efi_linux.c index 4ae792f01e..4ead208c7e 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/i386/txt.h b/include/grub/i386/txt.h index a171ab4372..25e38bc98e 100644 --- a/include/grub/i386/txt.h +++ b/include/grub/i386/txt.h @@ -21,6 +21,9 @@ #ifndef GRUB_TXT_H #define GRUB_TXT_H 1 +#include +#include + /* Intel TXT Software Developers Guide */ /* Chapter 2, Table 2 MLE/SINIT Capabilities Field Bit Definitions */ @@ -417,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]; @@ -634,6 +639,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 +695,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); diff --git a/include/grub/multiboot.h b/include/grub/multiboot.h index d8847f7531..020c548478 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 b90aa69896..1a3be5f486 100644 --- a/include/grub/multiboot2.h +++ b/include/grub/multiboot2.h @@ -28,12 +28,14 @@ #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[]); 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, @@ -42,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 37af7fbfb7..e9ab97a099 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 @@ -42,6 +43,8 @@ struct linux_kernel_params; 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 @@ -55,6 +58,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; @@ -67,6 +71,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 diff --git a/include/grub/slr_table.h b/include/grub/slr_table.h index f5e891f7d6..8e37bd2bd9 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