[PATCH v2 00/19] i386: Intel TXT and AMD SKINIT secure launcher

2 views
Skip to first unread message

Sergii Dmytruk

unread,
Nov 1, 2024, 6:52:55 PM11/1/24
to grub-...@gnu.org, trenchbo...@googlegroups.com
Hello,

Continuing upstreaming [TrenchBoot] code changes. More context can be found in
the cover letter for [v1].

How the patches look now:

1. [01-03] Various additions in preparation for later commits
2. [04-05] TPM-related part (`tpm` module rename, addition of a simple TPM
driver) (relatively small in size)
3. [06-07] SecureLaunch with its SLRT (lots of definitions)
4. [08-12] Support for Intel TXT D-RTM (the bulk of the patches)
5. [13] Implementation of SecureLaunch commands
6. [14-15] Multiboot2 support for Intel TXT (medium)
7. [16-19] Support for AMD SKINIT D-RTM (medium size when combined)

This set of changes can also be viewed on GitHub at [TrenchBoot/grub].

Best regards,
Sergii

Changes in v2:
- 5 patches landed as a separate [generic-x86] series
- 3 patches were in [generic-x86] as well, got Reviewed-Bys and returned here;
one of them was extracted out of a different patch
- patches related to modules received some documentation additions
- several commit messages became more verbose
- some commits have seen cosmetic changes with no impact on functionality
- a leak fix got dropped to be sent separately (it's not really related to the
rest of changes)

[TrenchBoot]: https://trenchboot.org/
[v1]: https://lists.gnu.org/archive/html/grub-devel/2024-08/msg00088.html
[TrenchBoot/grub]: https://github.com/TrenchBoot/grub/compare/6c5d4b3...tb-2.12-97-v2
[generic-x86]: https://lists.gnu.org/archive/html/grub-devel/2024-10/msg00055.html

Daniel Kiper (3):
mmap: Add grub_mmap_get_lowest() and grub_mmap_get_highest()
i386/tpm: Rename tpm module to tpm_verifier
i386/tpm: Add TPM TIS and CRB driver

Krystian Hebel (4):
i386/memory: Define GRUB_PAGE_MASK and GRUB_PAGE_{UP,DOWN} macros
i386/skinit: Add AMD SKINIT implementation
i386/slaunch: Add support for AMD SKINIT
multiboot2: Support AMD SKINIT

Michał Żygowski (2):
i386/txt: Initialize TPM 1.2 event log in TXT heap
multiboot2: Implement TXT slaunch support

Ross Philipson (9):
i386: Add CRx, MMIO, MSR and extend CPUID definitions
include/grub: Introduce Secure Launch Resource Table (SLRT)
i386/slaunch: Add Secure Launch header
i386/txt: Add Intel TXT definitions header file
i386/txt: Add Intel TXT core implementation
i386/txt: Add Intel TXT ACM module support
i386/txt: Add Intel TXT verification routines
i386/slaunch: Add secure launch framework and commands
i386/linux: Add support for AMD SKINIT

Sergii Dmytruk (1):
multiboot: Make GRUB_MULTIBOOT(make_mbi) return MBI's size

docs/grub.texi | 32 +-
grub-core/Makefile.am | 6 +
grub-core/Makefile.core.def | 18 +-
grub-core/commands/i386/tpm.c | 151 +++
grub-core/commands/{tpm.c => tpm_verifier.c} | 6 +-
grub-core/lib/i386/relocator32.S | 14 +
grub-core/loader/i386/bsd.c | 4 +
grub-core/loader/i386/coreboot/chainloader.c | 2 +
grub-core/loader/i386/linux.c | 337 +++++-
grub-core/loader/i386/multiboot_mbi.c | 4 +-
grub-core/loader/i386/pc/plan9.c | 3 +-
grub-core/loader/i386/skinit.c | 156 +++
grub-core/loader/i386/slaunch.c | 337 ++++++
grub-core/loader/i386/txt/acmod.c | 605 ++++++++++
grub-core/loader/i386/txt/txt.c | 1110 ++++++++++++++++++
grub-core/loader/i386/txt/verify.c | 277 +++++
grub-core/loader/i386/xnu.c | 3 +
grub-core/loader/multiboot.c | 34 +-
grub-core/loader/multiboot_elfxx.c | 88 +-
grub-core/loader/multiboot_mbi2.c | 118 +-
grub-core/mmap/mmap.c | 83 ++
include/grub/file.h | 3 +
include/grub/i386/cpuid.h | 11 +
include/grub/i386/crfr.h | 127 ++
include/grub/i386/linux.h | 14 +-
include/grub/i386/memory.h | 5 +
include/grub/i386/mmio.h | 72 ++
include/grub/i386/msr.h | 63 +
include/grub/i386/skinit.h | 36 +
include/grub/i386/slaunch.h | 90 ++
include/grub/i386/tpm.h | 35 +
include/grub/i386/txt.h | 742 ++++++++++++
include/grub/memory.h | 3 +
include/grub/multiboot.h | 2 +-
include/grub/multiboot2.h | 5 +-
include/grub/slr_table.h | 328 ++++++
36 files changed, 4892 insertions(+), 32 deletions(-)
create mode 100644 grub-core/commands/i386/tpm.c
rename grub-core/commands/{tpm.c => tpm_verifier.c} (97%)
create mode 100644 grub-core/loader/i386/skinit.c
create mode 100644 grub-core/loader/i386/slaunch.c
create mode 100644 grub-core/loader/i386/txt/acmod.c
create mode 100644 grub-core/loader/i386/txt/txt.c
create mode 100644 grub-core/loader/i386/txt/verify.c
create mode 100644 include/grub/i386/crfr.h
create mode 100644 include/grub/i386/mmio.h
create mode 100644 include/grub/i386/skinit.h
create mode 100644 include/grub/i386/slaunch.h
create mode 100644 include/grub/i386/tpm.h
create mode 100644 include/grub/i386/txt.h
create mode 100644 include/grub/slr_table.h


base-commit: bd2d85a141236f454485b995c3a024669cd5a017
prerequisite-patch-id: 450e6ee179d407f3718821303500f65cb955b5db
--
2.47.0

Sergii Dmytruk

unread,
Nov 1, 2024, 6:53:07 PM11/1/24
to grub-...@gnu.org, trenchbo...@googlegroups.com
From: Krystian Hebel <krystia...@3mdeb.com>

GRUB_PAGE_MASK is intentionally signed to make use of sign extension.

Subsequent patches will use them.

Signed-off-by: Krystian Hebel <krystia...@3mdeb.com>
Signed-off-by: Sergii Dmytruk <sergii....@3mdeb.com>
Reviewed-by: Ross Philipson <ross.ph...@oracle.com>
---
include/grub/i386/memory.h | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/include/grub/i386/memory.h b/include/grub/i386/memory.h
index c64529630..ca4509497 100644
--- a/include/grub/i386/memory.h
+++ b/include/grub/i386/memory.h
@@ -22,6 +22,7 @@

#define GRUB_PAGE_SHIFT 12
#define GRUB_PAGE_SIZE (1UL << GRUB_PAGE_SHIFT)
+#define GRUB_PAGE_MASK (~((1L << GRUB_PAGE_SHIFT) - 1))

/* The flag for protected mode. */
#define GRUB_MEMORY_CPU_CR0_PE_ON 0x1
@@ -43,8 +44,12 @@

#define GRUB_MMAP_MALLOC_LOW 1

+#include <grub/misc.h>
#include <grub/types.h>

+#define GRUB_PAGE_UP(p) ALIGN_UP (p, GRUB_PAGE_SIZE)
+#define GRUB_PAGE_DOWN(p) ALIGN_DOWN (p, GRUB_PAGE_SIZE)
+
struct grub_e820_mmap_entry
{
grub_uint64_t addr;
--
2.47.0

Sergii Dmytruk

unread,
Nov 1, 2024, 6:53:10 PM11/1/24
to grub-...@gnu.org, trenchbo...@googlegroups.com
From: Daniel Kiper <daniel...@oracle.com>

The functions find the lowest and highest values with regard to the
passed in limit. Passing a low limit of 0 or a high limit of ~0
calculates lowest and highest available RAM addresses respectively.

Signed-off-by: Daniel Kiper <daniel...@oracle.com>
Signed-off-by: Sergii Dmytruk <sergii....@3mdeb.com>
Reviewed-by: Ross Philipson <ross.ph...@oracle.com>
---
grub-core/mmap/mmap.c | 83 +++++++++++++++++++++++++++++++++++++++++++
include/grub/memory.h | 3 ++
2 files changed, 86 insertions(+)

diff --git a/grub-core/mmap/mmap.c b/grub-core/mmap/mmap.c
index c8c8312c5..80d6c60b8 100644
--- a/grub-core/mmap/mmap.c
+++ b/grub-core/mmap/mmap.c
@@ -26,6 +26,7 @@
#include <grub/command.h>
#include <grub/dl.h>
#include <grub/i18n.h>
+#include <grub/safemath.h>

GRUB_MOD_LICENSE ("GPLv3+");

@@ -343,6 +344,88 @@ grub_mmap_unregister (int handle)

#endif /* ! GRUB_MMAP_REGISTER_BY_FIRMWARE */

+typedef struct
+{
+ grub_uint64_t addr;
+ grub_uint64_t limit;
+} addr_limit_t;
+
+/* Helper for grub_mmap_get_lowest(). */
+static int
+lowest_hook (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type,
+ void *data)
+{
+ addr_limit_t *al = data;
+ grub_uint64_t end;
+
+ if (type != GRUB_MEMORY_AVAILABLE)
+ return 0;
+
+ if (grub_add (addr, size, &end))
+ return 0;
+
+ if (addr >= al->limit)
+ al->addr = grub_min (al->addr, addr);
+
+ if ((addr < al->limit) && (end > al->limit))
+ al->addr = al->limit;
+
+ return 0;
+}
+
+/*
+ * This function calculates lowest available RAM address that is at or above
+ * the passed limit. If no RAM exists above the limit, ~0 is returned.
+ */
+grub_uint64_t
+grub_mmap_get_lowest (grub_uint64_t limit)
+{
+ addr_limit_t al = {~0, limit};
+
+ grub_mmap_iterate (lowest_hook, &al);
+
+ return al.addr;
+}
+
+/* Helper for grub_mmap_get_highest(). */
+static int
+highest_hook (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type,
+ void *data)
+{
+ addr_limit_t *al = data;
+ grub_uint64_t end;
+
+ if (type != GRUB_MEMORY_AVAILABLE)
+ return 0;
+
+ if (grub_add (addr, size, &end))
+ return 0;
+
+ if (end < al->limit)
+ al->addr = grub_max (al->addr, end);
+
+ if ((addr < al->limit) && (end >= al->limit))
+ al->addr = al->limit;
+
+ return 0;
+}
+
+/*
+ * This function calculates highest available RAM address that is below the
+ * passed limit. Returned address is either one byte after last byte of RAM or
+ * equal to limit, whichever is lower. If no RAM exists below limit, 0 is
+ * returned.
+ */
+grub_uint64_t
+grub_mmap_get_highest (grub_uint64_t limit)
+{
+ addr_limit_t al = {0, limit};
+
+ grub_mmap_iterate (highest_hook, &al);
+
+ return al.addr;
+}
+
#define CHUNK_SIZE 0x400

struct badram_entry {
diff --git a/include/grub/memory.h b/include/grub/memory.h
index 6da114a1b..8f22f7525 100644
--- a/include/grub/memory.h
+++ b/include/grub/memory.h
@@ -69,6 +69,9 @@ void *grub_mmap_malign_and_register (grub_uint64_t align, grub_uint64_t size,

void grub_mmap_free_and_unregister (int handle);

+extern grub_uint64_t grub_mmap_get_lowest (grub_uint64_t limit);
+extern grub_uint64_t grub_mmap_get_highest (grub_uint64_t limit);
+
#ifndef GRUB_MMAP_REGISTER_BY_FIRMWARE

struct grub_mmap_region
--
2.47.0

Sergii Dmytruk

unread,
Nov 1, 2024, 6:53:13 PM11/1/24
to grub-...@gnu.org, trenchbo...@googlegroups.com
From: Ross Philipson <ross.ph...@oracle.com>

Control registers and flags:
- CR0 read/write and flags (PE, MP, EM, TS, PG, NE, WP, AM, NW, CD)
- CR4 read/write and flags (VME, PVI, TSD, DE, PSE, PAE, MCE, PGE, PCE,
FXSR, XMM, VMXE, SMXE, PCIDE)
- EFLAGS read/write and flags (CF, PF, AF, ZF, SF, TF, IF, DF, OF,
IOPL, NT, RF, VM, AC, VIF, VIP, ID)

MMIO:
- read/write 8bit values
- read/write 32bit values
- read/write 64bit values

MSRs:
- platform ID
- APIC base
- feature control
- MTRR (capability, bases, masks, types)
- MCG (global machine check; capability, status)
- MISC_ENABLE
- MC0 (machine check error reporting status)
- EFER (LME, LMA, SVEM (AMD-V))
- AMD: SVM control

CPUID:
- flags for availability of vendor, features
- Intel: VMX, SMX
- AMD: SVM

Signed-off-by: Ross Philipson <ross.ph...@oracle.com>
Signed-off-by: Daniel Kiper <daniel...@oracle.com>
Signed-off-by: Krystian Hebel <krystia...@3mdeb.com>
Signed-off-by: Sergii Dmytruk <sergii....@3mdeb.com>
Reviewed-by: Alec Brown <alec.r...@oracle.com>
---
include/grub/i386/cpuid.h | 11 ++++
include/grub/i386/crfr.h | 127 ++++++++++++++++++++++++++++++++++++++
include/grub/i386/mmio.h | 72 +++++++++++++++++++++
include/grub/i386/msr.h | 63 +++++++++++++++++++
4 files changed, 273 insertions(+)
create mode 100644 include/grub/i386/crfr.h
create mode 100644 include/grub/i386/mmio.h

diff --git a/include/grub/i386/cpuid.h b/include/grub/i386/cpuid.h
index f7ae4b0a4..bf2a39ec3 100644
--- a/include/grub/i386/cpuid.h
+++ b/include/grub/i386/cpuid.h
@@ -19,6 +19,17 @@
#ifndef GRUB_CPU_CPUID_HEADER
#define GRUB_CPU_CPUID_HEADER 1

+/* General */
+#define GRUB_X86_CPUID_VENDOR 0x00000000
+#define GRUB_X86_CPUID_FEATURES 0x00000001
+/* Intel */
+#define GRUB_X86_CPUID_FEATURES_ECX_VMX (1<<5)
+#define GRUB_X86_CPUID_FEATURES_ECX_SMX (1<<6)
+/* AMD */
+#define GRUB_AMD_CPUID_FEATURES 0x80000001
+#define GRUB_AMD_CPUID_FEATURES_ECX_SVM (1<<2)
+#define GRUB_AMD_CPUID_FUNC 0x8000000a
+
extern unsigned char grub_cpuid_has_longmode;
extern unsigned char grub_cpuid_has_pae;

diff --git a/include/grub/i386/crfr.h b/include/grub/i386/crfr.h
new file mode 100644
index 000000000..aeb696a91
--- /dev/null
+++ b/include/grub/i386/crfr.h
@@ -0,0 +1,127 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2020 Oracle and/or its affiliates.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_CRFR_H
+#define GRUB_CRFR_H 1
+
+#include <grub/types.h>
+
+/* Routines for R/W of control and flags registers */
+
+#define GRUB_CR0_X86_PE 0x00000001 /* Enable Protected Mode */
+#define GRUB_CR0_X86_MP 0x00000002 /* "Math" (FPU) Present */
+#define GRUB_CR0_X86_EM 0x00000004 /* EMulate FPU */
+#define GRUB_CR0_X86_TS 0x00000008 /* Task Switched */
+#define GRUB_CR0_X86_PG 0x80000000 /* Enable PaGing */
+
+#define GRUB_CR0_X86_NE 0x00000020 /* Numeric Error enable (EX16 vs IRQ13) */
+#define GRUB_CR0_X86_WP 0x00010000 /* Write Protect */
+#define GRUB_CR0_X86_AM 0x00040000 /* Alignment Mask */
+#define GRUB_CR0_X86_NW 0x20000000 /* Not Write-through */
+#define GRUB_CR0_X86_CD 0x40000000 /* Cache Disable */
+
+#define GRUB_CR4_X86_VME 0x00000001 /* Virtual 8086 mode extensions */
+#define GRUB_CR4_X86_PVI 0x00000002 /* Protected-mode virtual interrupts */
+#define GRUB_CR4_X86_TSD 0x00000004 /* Time stamp disable */
+#define GRUB_CR4_X86_DE 0x00000008 /* Debugging extensions */
+#define GRUB_CR4_X86_PSE 0x00000010 /* Page size extensions */
+#define GRUB_CR4_X86_PAE 0x00000020 /* Physical address extension */
+#define GRUB_CR4_X86_MCE 0x00000040 /* Enable Machine check enable */
+#define GRUB_CR4_X86_PGE 0x00000080 /* Enable Page global */
+#define GRUB_CR4_X86_PCE 0x00000100 /* Enable Performance monitoring counter */
+#define GRUB_CR4_X86_FXSR 0x00000200 /* Fast FPU save/restore */
+#define GRUB_CR4_X86_XMM 0x00000400 /* Generate #XM instead of #UD for SIMD */
+#define GRUB_CR4_X86_VMXE 0x00002000 /* Enable VMX */
+#define GRUB_CR4_X86_SMXE 0x00004000 /* Enable SMX */
+#define GRUB_CR4_X86_PCIDE 0x00020000 /* Enable PCID */
+
+static inline unsigned long
+grub_read_cr0 (void)
+{
+ unsigned long val;
+
+ asm volatile ("mov %%cr0, %0" : "=r" (val) : : "memory");
+
+ return val;
+}
+
+static inline void
+grub_write_cr0 (unsigned long val)
+{
+ asm volatile ("mov %0, %%cr0" : : "r" (val) : "memory");
+}
+
+static inline unsigned long
+grub_read_cr4 (void)
+{
+ unsigned long val;
+
+ asm volatile ("mov %%cr4, %0" : "=r" (val) : : "memory");
+
+ return val;
+}
+
+static inline void
+grub_write_cr4 (unsigned long val)
+{
+ asm volatile ("mov %0, %%cr4" : : "r" (val) : "memory");
+}
+
+#define GRUB_EFLAGS_X86_CF 0x00000001 /* Carry Flag */
+#define GRUB_EFLAGS_X86_PF 0x00000004 /* Parity Flag */
+#define GRUB_EFLAGS_X86_AF 0x00000010 /* Auxillary carry Flag */
+#define GRUB_EFLAGS_X86_ZF 0x00000040 /* Zero Flag */
+#define GRUB_EFLAGS_X86_SF 0x00000080 /* Sign Flag */
+#define GRUB_EFLAGS_X86_TF 0x00000100 /* Trap Flag */
+#define GRUB_EFLAGS_X86_IF 0x00000200 /* Interrupt Flag */
+#define GRUB_EFLAGS_X86_DF 0x00000400 /* Direction Flag */
+#define GRUB_EFLAGS_X86_OF 0x00000800 /* Overflow Flag */
+#define GRUB_EFLAGS_X86_IOPL 0x00003000 /* IOPL mask */
+#define GRUB_EFLAGS_X86_NT 0x00004000 /* Nested Task */
+#define GRUB_EFLAGS_X86_RF 0x00010000 /* Resume Flag */
+#define GRUB_EFLAGS_X86_VM 0x00020000 /* Virtual Mode */
+#define GRUB_EFLAGS_X86_AC 0x00040000 /* Alignment Check */
+#define GRUB_EFLAGS_X86_VIF 0x00080000 /* Virtual Interrupt Flag */
+#define GRUB_EFLAGS_X86_VIP 0x00100000 /* Virtual Interrupt Pending */
+#define GRUB_EFLAGS_X86_ID 0x00200000 /* CPUID detection flag */
+
+static inline unsigned long
+grub_read_flags_register (void)
+{
+ unsigned long flags;
+
+#ifdef __x86_64__
+ asm volatile ("pushfq; popq %0" : "=r" (flags));
+#else
+ asm volatile ("pushfl; popl %0" : "=r" (flags));
+#endif
+
+ return flags;
+}
+
+static inline void
+grub_write_flags_register (unsigned long flags)
+{
+#ifdef __x86_64__
+ asm volatile ("pushq %0; popfq" : : "r" (flags));
+#else
+ asm volatile ("pushl %0; popfl" : : "r" (flags));
+#endif
+}
+
+#endif
diff --git a/include/grub/i386/mmio.h b/include/grub/i386/mmio.h
new file mode 100644
index 000000000..97a30f7d8
--- /dev/null
+++ b/include/grub/i386/mmio.h
@@ -0,0 +1,72 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2020 Oracle and/or its affiliates.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_I386_MMIO_H
+#define GRUB_I386_MMIO_H 1
+
+#include <grub/types.h>
+
+static inline grub_uint8_t
+grub_read8 (const grub_addr_t addr)
+{
+ grub_uint8_t val;
+
+ val = (*(volatile grub_uint8_t *) (addr));
+
+ return val;
+}
+
+static inline grub_uint32_t
+grub_read32 (const grub_addr_t addr)
+{
+ grub_uint32_t val;
+
+ val = (*(volatile grub_uint32_t *) (addr));
+
+ return val;
+}
+
+static inline grub_uint64_t
+grub_read64 (const grub_addr_t addr)
+{
+ grub_uint64_t val;
+
+ val = (*(volatile grub_uint64_t *) (addr));
+
+ return val;
+}
+
+static inline void
+grub_write8 (grub_uint8_t val, grub_addr_t addr)
+{
+ (*(volatile grub_uint8_t *) (addr)) = val;
+}
+
+static inline void
+grub_write32 (grub_uint32_t val, grub_addr_t addr)
+{
+ (*(volatile grub_uint32_t *) (addr)) = val;
+}
+
+static inline void
+grub_write64 (grub_uint64_t val, grub_addr_t addr)
+{
+ (*(volatile grub_uint64_t *) (addr)) = val;
+}
+
+#endif /* GRUB_I386_MMIO_H */
diff --git a/include/grub/i386/msr.h b/include/grub/i386/msr.h
index 1e838c022..05a0fd2f6 100644
--- a/include/grub/i386/msr.h
+++ b/include/grub/i386/msr.h
@@ -2,6 +2,9 @@
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2019 Free Software Foundation, Inc.
*
+ * Some definitions in this header are extracted from the Trusted Computing
+ * Group's "TPM Main Specification", Parts 1-3.
+ *
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@@ -19,6 +22,64 @@
#ifndef GRUB_I386_MSR_H
#define GRUB_I386_MSR_H 1

+/* General */
+#define GRUB_MSR_X86_PLATFORM_ID 0x00000017
+
+#define GRUB_MSR_X86_APICBASE 0x0000001b
+#define GRUB_MSR_X86_APICBASE_BSP (1<<8)
+#define GRUB_MSR_X86_APICBASE_ENABLE (1<<11)
+#define GRUB_MSR_X86_APICBASE_BASE (0xfffff<<12) /* Mask for APIC base address */
+
+#define GRUB_MSR_X86_FEATURE_CONTROL 0x0000003a
+#define GRUB_MSR_X86_FEATURE_CTRL_LOCK (1<<0) /* Lock writes to this register */
+#define GRUB_MSR_X86_ENABLE_VMX_IN_SMX (1<<1) /* Enable VMX inside SMX */
+#define GRUB_MSR_X86_ENABLE_VMX_OUT_SMX (1<<2) /* Enable VMX outside SMX */
+#define GRUB_MSR_X86_SENTER_FUNCTIONS (0x7f<<8) /* Bitmap of SENTER function enables */
+#define GRUB_MSR_X86_SENTER_ENABLE (1<<15) /* SENTER global enable */
+
+#define GRUB_MSR_X86_MTRRCAP 0x000000fe
+#define GRUB_MSR_X86_VCNT_MASK 0xff /* Number of variable MTRRs */
+
+#define GRUB_MSR_X86_MCG_CAP 0x00000179
+#define GRUB_MSR_MCG_BANKCNT_MASK 0xff /* Number of banks */
+#define GRUB_MSR_X86_MCG_STATUS 0x0000017a
+#define GRUB_MSR_MCG_STATUS_MCIP (1ULL<<2) /* MC in progress */
+
+#define GRUB_MSR_X86_MISC_ENABLE 0x000001a0
+#define GRUB_MSR_X86_ENABLE_MONITOR_FSM (1<<18)
+
+#define GRUB_MSR_X86_MTRR_PHYSBASE0 0x00000200
+#define GRUB_MSR_X86_MTRR_PHYSMASK0 0x00000201
+#define GRUB_MSR_X86_MTRR_PHYSBASE(n) (GRUB_MSR_X86_MTRR_PHYSBASE0 + 2 * (n))
+#define GRUB_MSR_X86_MTRR_PHYSMASK(n) (GRUB_MSR_X86_MTRR_PHYSMASK0 + 2 * (n))
+#define GRUB_MSR_X86_BASE_DEF_TYPE_MASK 0xff
+#define GRUB_MSR_X86_MASK_VALID (1<<11)
+
+#define GRUB_MSR_X86_MTRR_DEF_TYPE 0x000002ff
+#define GRUB_MSR_X86_DEF_TYPE_MASK 0xff
+#define GRUB_MSR_X86_MTRR_ENABLE_FIXED (1<<10)
+#define GRUB_MSR_X86_MTRR_ENABLE (1<<11)
+
+#define GRUB_MSR_X86_MC0_STATUS 0x00000401
+
+#define GRUB_MSR_X86_EFER 0xc0000080 /* Extended features */
+#define GRUB_MSR_EFER_LME (1<<8) /* Enable Long Mode/IA-32e */
+#define GRUB_MSR_EFER_LMA (1<<10) /* Long Mode/IA-32e Active */
+#define GRUB_MSR_EFER_SVME (1<<12) /* Enable SVM (AMD-V) */
+
+/* AMD Specific */
+#define GRUB_MSR_AMD64_VM_CR 0xc0010114 /* SVM control register */
+#define GRUB_MSR_SVM_VM_CR_SVM_DISABLE (1<<4) /* Disable writes to EFER.SVME */
+
+/* MTRR Specific */
+#define GRUB_MTRR_MEMORY_TYPE_UC 0
+#define GRUB_MTRR_MEMORY_TYPE_WC 1
+#define GRUB_MTRR_MEMORY_TYPE_WT 4
+#define GRUB_MTRR_MEMORY_TYPE_WP 5
+#define GRUB_MTRR_MEMORY_TYPE_WB 6
+
+#ifndef ASM_FILE
+
#include <grub/err.h>
#include <grub/i386/cpuid.h>
#include <grub/types.h>
@@ -71,4 +132,6 @@ grub_wrmsr (grub_uint32_t msr_id, grub_uint64_t msr_value)
asm volatile ("wrmsr" : : "c" (msr_id), "a" (low), "d" (high));
}

+#endif /* ASM_FILE */
+
#endif /* GRUB_I386_MSR_H */
--
2.47.0

Sergii Dmytruk

unread,
Nov 1, 2024, 6:53:14 PM11/1/24
to grub-...@gnu.org, trenchbo...@googlegroups.com
From: Daniel Kiper <daniel...@oracle.com>

This avoids naming collision with TPM TIS and CRB driver introduced
by subsequent patch and characterizes the functionality of the module
better.

Signed-off-by: Daniel Kiper <daniel...@oracle.com>
Signed-off-by: Sergii Dmytruk <sergii....@3mdeb.com>
---
docs/grub.texi | 21 ++++++++++----------
grub-core/Makefile.core.def | 4 ++--
grub-core/commands/{tpm.c => tpm_verifier.c} | 6 +++---
3 files changed, 16 insertions(+), 15 deletions(-)
rename grub-core/commands/{tpm.c => tpm_verifier.c} (97%)

diff --git a/docs/grub.texi b/docs/grub.texi
index 78d47f467..e6b6c2394 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -4136,7 +4136,7 @@ Modules can be loaded via the @command{insmod} (@pxref{insmod}) command.
* tftp_module::
* tga_module::
* time_module::
-* tpm_module::
+* tpm_verifier_module::
* tr_module::
* trig_module::
* true_module::
@@ -5703,8 +5703,8 @@ image files in GRUB.
This module provides support for the @command{time} command to measure the
time taken by a given command and output it to the terminal.

-@node tpm_module
-@section tpm
+@node tpm_verifier_module
+@section tpm_verifier
This module provides support for interacting with a Trusted Platform Module
(TPM) with GRUB to perform Measured Boot. @xref{Measured Boot} for more
information.
@@ -8714,10 +8714,10 @@ grub-mkimage -O x86_64-efi -o grubx64.efi -p '(tftp)/grub' --sbat sbat.csv efine
@node Measured Boot
@section Measuring boot components

-If the tpm module is loaded and the platform has a Trusted Platform Module
-installed, GRUB will log each command executed and each file loaded into the
-TPM event log and extend the PCR values in the TPM correspondingly. All events
-will be logged into the PCR described below with a type of EV_IPL and an
+If the tpm_verifier module is loaded and the platform has a Trusted Platform
+Module installed, GRUB will log each command executed and each file loaded into
+the TPM event log and extend the PCR values in the TPM correspondingly. All
+events will be logged into the PCR described below with a type of EV_IPL and an
event description as described below.

@multitable @columnfractions 0.3 0.1 0.6
@@ -8742,9 +8742,10 @@ corresponding to the filename.

GRUB will not measure its own @file{core.img} - it is expected that firmware
will carry this out. GRUB will also not perform any measurements until the
-tpm module is loaded. As such it is recommended that the tpm module be built
-into @file{core.img} in order to avoid a potential gap in measurement between
-@file{core.img} being loaded and the tpm module being loaded.
+tpm_verifier module is loaded. As such it is recommended that the tpm_verifier
+module be built into @file{core.img} in order to avoid a potential gap in
+measurement between @file{core.img} being loaded and the tpm_verifier module
+being loaded.

Measured boot is currently only supported on EFI and IBM IEEE1275 PowerPC
platforms.
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 063ef5dd7..29b64dfe9 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -2556,8 +2556,8 @@ module = {
};

module = {
- name = tpm;
- common = commands/tpm.c;
+ name = tpm_verifier;
+ common = commands/tpm_verifier.c;
efi = commands/efi/tpm.c;
enable = efi;
};
diff --git a/grub-core/commands/tpm.c b/grub-core/commands/tpm_verifier.c
similarity index 97%
rename from grub-core/commands/tpm.c
rename to grub-core/commands/tpm_verifier.c
index dde74ab83..e8efebc96 100644
--- a/grub-core/commands/tpm.c
+++ b/grub-core/commands/tpm_verifier.c
@@ -98,13 +98,13 @@ grub_tpm_verify_string (char *str, enum grub_verify_string_type type)
}

struct grub_file_verifier grub_tpm_verifier = {
- .name = "tpm",
+ .name = "tpm_verifier",
.init = grub_tpm_verify_init,
.write = grub_tpm_verify_write,
.verify_string = grub_tpm_verify_string,
};

-GRUB_MOD_INIT (tpm)
+GRUB_MOD_INIT (tpm_verifier)
{
/*
* Even though this now calls ibmvtpm's grub_tpm_present() from GRUB_MOD_INIT(),
@@ -117,7 +117,7 @@ GRUB_MOD_INIT (tpm)
grub_verifier_register (&grub_tpm_verifier);
}

-GRUB_MOD_FINI (tpm)
+GRUB_MOD_FINI (tpm_verifier)
{
if (!grub_tpm_present())
return;
--
2.47.0

Sergii Dmytruk

unread,
Nov 1, 2024, 6:53:29 PM11/1/24
to grub-...@gnu.org, trenchbo...@googlegroups.com
From: Michał Żygowski <michal....@3mdeb.com>

This extends the code to support TPM 1.2 in addition to already
available TPM 2.0.

Signed-off-by: Michał Żygowski <michal....@3mdeb.com>
Signed-off-by: Krystian Hebel <krystia...@3mdeb.com>
Signed-off-by: Sergii Dmytruk <sergii....@3mdeb.com>
---
grub-core/loader/i386/txt/txt.c | 62 +++++++++++++++++++++++++++++++--
include/grub/i386/txt.h | 33 ++++++++++++++++++
2 files changed, 93 insertions(+), 2 deletions(-)

diff --git a/grub-core/loader/i386/txt/txt.c b/grub-core/loader/i386/txt/txt.c
index ece482ec7..6a9bca685 100644
--- a/grub-core/loader/i386/txt/txt.c
+++ b/grub-core/loader/i386/txt/txt.c
@@ -530,6 +530,32 @@ set_mtrrs_for_acmod (struct grub_txt_acm_header *hdr)
return err;
}

+void
+grub_txt_init_tpm_event_log (void *buf, grub_size_t size)
+{
+ struct grub_txt_event_log_container *elog;
+
+ if (buf == NULL || size == 0)
+ 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
setup_txt_slrt_entry (struct grub_slaunch_params *slparams,
struct grub_txt_os_mle_data *os_mle_data)
@@ -702,6 +728,8 @@ 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 %08x\n", sinit_caps);
+
/*
* In the latest TXT Software Development Guide as of now (April 2023,
* Revision 017.4) bits 4 and 5 (used to be "no legacy PCR usage" and
@@ -716,6 +744,25 @@ init_txt_heap (struct grub_slaunch_params *slparams, struct grub_txt_acm_header
*/
os_sinit_data->capabilities = 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;
+ }
+ }
+
/*
* APs (application processors) can't be brought up by usual INIT-SIPI-SIPI
* sequence after Measured Launch, otherwise the MLE integrity is lost.
@@ -733,10 +780,21 @@ 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_NOT_IMPLEMENTED_YET,
- N_("TPM 1.2 detected, but not implemented yet"));
+ {
+ 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;
+
+ elt = add_ext_data_elt(os_sinit_data,
+ GRUB_TXT_HEAP_EXTDATA_TYPE_TPM_EVENT_LOG_PTR,
+ sizeof (struct grub_txt_heap_tpm_event_log_element));
+ elt->tpm_event_log.event_log_phys_addr = slparams->tpm_evt_log_base;
+ }
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 53e4b788c..ca4ce67ef 100644
--- a/include/grub/i386/txt.h
+++ b/include/grub/i386/txt.h
@@ -22,6 +22,7 @@
#define GRUB_TXT_H 1

#include <grub/err.h>
+#include <grub/tpm.h>
#include <grub/types.h>
#include <grub/i386/memory.h>
#include <grub/i386/mmio.h>
@@ -678,6 +679,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;
+
extern grub_uint32_t grub_txt_supported_os_sinit_data_ver (struct grub_txt_acm_header *hdr);

extern grub_uint32_t grub_txt_get_sinit_capabilities (struct grub_txt_acm_header *hdr);
@@ -691,6 +722,8 @@ extern struct grub_txt_acm_header *grub_txt_sinit_select (struct grub_txt_acm_he
extern grub_err_t grub_txt_verify_platform (void);
extern grub_err_t grub_txt_prepare_cpu (void);

+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);

--
2.47.0

Sergii Dmytruk

unread,
Nov 1, 2024, 6:53:35 PM11/1/24
to grub-...@gnu.org, trenchbo...@googlegroups.com
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.

Signed-off-by: Sergii Dmytruk <sergii....@3mdeb.com>
---
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 b764fcff4..73a34d3ff 100644
--- a/grub-core/loader/multiboot.c
+++ b/grub-core/loader/multiboot.c
@@ -180,6 +180,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;
@@ -188,7 +189,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,
--
2.47.0

Sergii Dmytruk

unread,
Nov 1, 2024, 6:53:36 PM11/1/24
to grub-...@gnu.org, trenchbo...@googlegroups.com
From: Michał Żygowski <michal....@3mdeb.com>

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

SLRT table is initially allocated on the heap, then an area for it is
reserved inside TXT heap by TXT code and the data is eventually copied
into its final place. This is done to be able to start building SLRT
before TXT heap is setup.

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

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

diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c
index 73a34d3ff..561523a2b 100644
--- a/grub-core/loader/multiboot.c
+++ b/grub-core/loader/multiboot.c
@@ -52,6 +52,7 @@
#include <grub/i18n.h>
#if defined (__i386__) || defined (__x86_64__)
#include <grub/i386/slaunch.h>
+#include <grub/i386/txt.h>
#endif

GRUB_MOD_LICENSE ("GPLv3+");
@@ -164,7 +165,17 @@ efi_boot (struct grub_relocator *rel __attribute__ ((unused)),
static void
normal_boot (struct grub_relocator *rel, struct grub_relocator32_state state)
{
- state.edi = SLP_NONE;
+ struct grub_slaunch_params *slparams = grub_slaunch_params();
+ state.edi = grub_slaunch_platform_type ();
+
+ if (state.edi == SLP_INTEL_TXT)
+ {
+ /* Configure relocator GETSEC[SENTER] call. */
+ state.eax = GRUB_SMX_LEAF_SENTER;
+ state.ebx = slparams->dce_base;
+ state.ecx = slparams->dce_size;
+ state.edx = 0;
+ }

grub_relocator32_boot (rel, state, 0);
}
@@ -194,6 +205,16 @@ grub_multiboot_boot (void)
if (err)
return err;

+#ifdef GRUB_USE_MULTIBOOT2
+ if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
+ {
+ err = grub_multiboot2_prepare_slaunch_txt (state.MULTIBOOT_MBI_REGISTER,
+ mbi_size);
+ if (err)
+ return err;
+ }
+#endif
+
if (grub_efi_is_finished)
normal_boot (GRUB_MULTIBOOT (relocator), state);
else
diff --git a/grub-core/loader/multiboot_elfxx.c b/grub-core/loader/multiboot_elfxx.c
index 1edad0594..f29fbb411 100644
--- a/grub-core/loader/multiboot_elfxx.c
+++ b/grub-core/loader/multiboot_elfxx.c
@@ -44,6 +44,8 @@
#error "I'm confused"
#endif

+#include <grub/i386/slaunch.h>
+#include <grub/i386/txt.h>
#include <grub/i386/relocator.h>

#define CONCAT(a,b) CONCAT_(a, b)
@@ -73,6 +75,9 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
grub_off_t phlimit;
unsigned int i;
void *source = NULL;
+ struct grub_slaunch_params *slparams = grub_slaunch_params();
+ grub_uint32_t mle_hdr_offset;
+ struct grub_txt_mle_header *mle_hdr;

if (ehdr->e_ident[EI_MAG0] != ELFMAG0
|| ehdr->e_ident[EI_MAG1] != ELFMAG1
@@ -127,6 +132,28 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
{
load_size = highest_load - mld->link_base_addr;

+ if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
+ {
+#ifndef GRUB_USE_MULTIBOOT2
+ return grub_error (GRUB_ERR_BAD_OS, "Only multiboot2 supported for slaunch");
+#else
+ /*
+ * We allocate the binary together with the page tables to make one
+ * contiguous block for MLE.
+ */
+ slparams->mle_ptab_size = grub_txt_get_mle_ptab_size (load_size);
+ slparams->mle_ptab_size = ALIGN_UP (slparams->mle_ptab_size, GRUB_TXT_PMR_ALIGN);
+
+ /* Do not go below GRUB_TXT_PMR_ALIGN. */
+ if (mld->align < GRUB_TXT_PMR_ALIGN)
+ mld->align = GRUB_TXT_PMR_ALIGN;
+#endif
+ }
+ else
+ {
+ slparams->mle_ptab_size = 0;
+ }
+
grub_dprintf ("multiboot_loader", "align=0x%lx, preference=0x%x, "
"load_size=0x%x, avoid_efi_boot_services=%d\n",
(long) mld->align, mld->preference, load_size,
@@ -148,9 +175,44 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)

mld->load_base_addr = get_physical_target_address (ch);
source = get_virtual_current_address (ch);
+ grub_memset (get_virtual_current_address (ch), 0, load_size);
+ grub_dprintf ("multiboot_loader", "load_base_addr=0x%lx, source=0x%lx\n",
+ (long) mld->load_base_addr, (long) source);
+
+ if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
+ {
+#ifndef GRUB_USE_MULTIBOOT2
+ return grub_error (GRUB_ERR_BAD_OS, "Only multiboot2 supported for slaunch");
+#else
+ slparams->mle_start = mld->load_base_addr;
+ slparams->mle_mem = source;
+
+ err = grub_relocator_alloc_chunk_align_safe (GRUB_MULTIBOOT (relocator), &ch,
+ GRUB_MEMORY_MACHINE_UPPER_START,
+ mld->load_base_addr - slparams->mle_ptab_size,
+ slparams->mle_ptab_size, GRUB_TXT_PMR_ALIGN,
+ GRUB_RELOCATOR_PREFERENCE_NONE, 1);
+ if (err)
+ {
+ grub_dprintf ("multiboot_loader", "Cannot allocate memory for MLE page tables\n");
+ return err;
+ }
+
+ slparams->mle_ptab_mem = get_virtual_current_address (ch);
+ slparams->mle_ptab_target = (grub_uint64_t) get_physical_target_address (ch);
+ grub_dprintf ("multiboot_loader", "mle_ptab_mem = %p, mle_ptab_target = %lx, mle_ptab_size = %x\n",
+ slparams->mle_ptab_mem, (unsigned long) slparams->mle_ptab_target,
+ (unsigned) slparams->mle_ptab_size);
+#endif
+ }
}
else
- mld->load_base_addr = mld->link_base_addr;
+ {
+ mld->load_base_addr = mld->link_base_addr;
+ /* TODO: support non-relocatable */
+ if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
+ return grub_error (GRUB_ERR_BAD_OS, "Non-relocatable ELF not supported with slaunch");
+ }

grub_dprintf ("multiboot_loader", "relocatable=%d, link_base_addr=0x%x, "
"load_base_addr=0x%x\n", mld->relocatable,
@@ -213,6 +275,30 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
}
}

+ if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
+ {
+ slparams->mle_header_offset = 0xffffffff;
+
+ /* TODO: decide on universal way of conveying location of MLE header */
+ for (mle_hdr_offset = 0; mle_hdr_offset < 0x1000; mle_hdr_offset += 16)
+ {
+ mle_hdr = (struct grub_txt_mle_header *)((grub_addr_t)source + mle_hdr_offset);
+ if ( !grub_memcmp ((void *)mle_hdr->uuid, GRUB_TXT_MLE_UUID, 16) )
+ {
+ slparams->mle_header_offset = mle_hdr_offset;
+ break;
+ }
+ }
+
+ if (slparams->mle_header_offset == 0xffffffff)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "MLE header not found");
+
+ grub_dprintf ("slaunch", "slparams->mle_header_offset: 0x%08x\n",
+ slparams->mle_header_offset);
+
+ slparams->mle_size = mle_hdr->mle_end - mle_hdr->mle_start;
+ }
+
for (i = 0; i < phnum; i++)
if (phdr(i)->p_vaddr <= ehdr->e_entry
&& phdr(i)->p_vaddr + phdr(i)->p_memsz > ehdr->e_entry)
diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c
index 1945b3ac6..a611b5d43 100644
--- a/grub-core/loader/multiboot_mbi2.c
+++ b/grub-core/loader/multiboot_mbi2.c
@@ -36,6 +36,10 @@
#include <grub/i18n.h>
#include <grub/net.h>
#include <grub/lib/cmdline.h>
+#include <grub/i386/memory.h>
+#include <grub/i386/slaunch.h>
+#include <grub/i386/txt.h>
+#include <grub/slr_table.h>

#if defined (GRUB_MACHINE_EFI)
#include <grub/efi/efi.h>
@@ -277,6 +281,9 @@ grub_multiboot2_load (grub_file_t file, const char *filename)

if (addr_tag)
{
+ if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
+ return grub_error (GRUB_ERR_BAD_OS, "Slaunch not supported with multiboot addr tag");
+
grub_uint64_t load_addr = (addr_tag->load_addr + 1)
? addr_tag->load_addr : (addr_tag->header_addr
- ((char *) header - (char *) mld.buffer));
@@ -390,6 +397,34 @@ grub_multiboot2_load (grub_file_t file, const char *filename)
err = grub_multiboot2_set_console (GRUB_MULTIBOOT2_CONSOLE_EGA_TEXT,
accepted_consoles,
0, 0, 0, console_required);
+
+ if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
+ {
+ grub_relocator_chunk_t ch;
+ struct grub_slaunch_params *slparams = grub_slaunch_params();
+
+ if (grub_relocator_alloc_chunk_align_safe (grub_multiboot2_relocator, &ch, 0x1000000,
+ UP_TO_TOP32 (GRUB_SLAUNCH_TPM_EVT_LOG_SIZE),
+ GRUB_SLAUNCH_TPM_EVT_LOG_SIZE, GRUB_PAGE_SIZE,
+ GRUB_RELOCATOR_PREFERENCE_HIGH, 1))
+ {
+ grub_free (mld.buffer);
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "Could not allocate TPM event log area");
+ }
+
+ slparams->tpm_evt_log_base = get_physical_target_address (ch);
+ slparams->tpm_evt_log_size = GRUB_SLAUNCH_TPM_EVT_LOG_SIZE;
+
+ grub_txt_init_tpm_event_log(get_virtual_current_address (ch),
+ slparams->tpm_evt_log_size);
+
+ grub_dprintf ("multiboot_loader", "tpm_evt_log_base = %lx, tpm_evt_log_size = %x\n",
+ (unsigned long) slparams->tpm_evt_log_base,
+ (unsigned) slparams->tpm_evt_log_size);
+
+ grub_txt_setup_mle_ptab (slparams);
+ }
+
return err;
}

@@ -1128,3 +1163,64 @@ grub_multiboot2_set_bootdev (void)

bootdev_set = 1;
}
+
+static void
+add_multiboot2_slrt_policy_entries (void)
+{
+ unsigned i;
+ struct module *cur;
+
+ for (i = 0, cur = modules; i < modcnt; i++, cur = cur->next)
+ {
+ grub_slaunch_add_slrt_policy_entry (GRUB_SLAUNCH_CODE_PCR,
+ GRUB_SLR_ET_MULTIBOOT2_MODULE,
+ /*flags=*/0,
+ cur->start,
+ cur->size,
+ "Measured MB2 module");
+ }
+}
+
+grub_err_t
+grub_multiboot2_prepare_slaunch_txt (grub_uint32_t mbi_target,
+ grub_uint32_t mbi_size)
+{
+ grub_err_t err;
+ struct grub_slaunch_params *slparams = grub_slaunch_params ();
+
+ slparams->boot_params_addr = mbi_target;
+
+ slparams->slr_table_base = GRUB_SLAUNCH_STORE_IN_OS2MLE;
+ slparams->slr_table_size = GRUB_PAGE_SIZE;
+
+ slparams->slr_table_mem = grub_zalloc (slparams->slr_table_size);
+ if (slparams->slr_table_mem == NULL)
+ return GRUB_ERR_OUT_OF_MEMORY;
+
+ err = grub_txt_boot_prepare (slparams);
+ if (err != GRUB_ERR_NONE)
+ {
+ grub_printf ("TXT boot preparation failed");
+ return err;
+ }
+
+ grub_slaunch_add_slrt_policy_entry (GRUB_SLAUNCH_DATA_PCR,
+ GRUB_SLR_ET_MULTIBOOT2_INFO,
+ /*flags=*/0,
+ mbi_target,
+ mbi_size,
+ "Measured MB2 information");
+ grub_slaunch_add_slrt_policy_entries ();
+ grub_txt_add_slrt_policy_entries ();
+ add_multiboot2_slrt_policy_entries ();
+ grub_slaunch_finish_slr_table ();
+
+ grub_dprintf ("multiboot_loader", "slr_table_base = %lx, slr_table_size = %x\n",
+ (unsigned long) slparams->slr_table_base,
+ (unsigned) slparams->slr_table_size);
+ grub_memcpy ((void *)(grub_addr_t) slparams->slr_table_base,
+ slparams->slr_table_mem,
+ slparams->slr_table_size);
+
+ return GRUB_ERR_NONE;
+}
diff --git a/include/grub/multiboot2.h b/include/grub/multiboot2.h
index 3417a1447..2e843d24e 100644
--- a/include/grub/multiboot2.h
+++ b/include/grub/multiboot2.h
@@ -43,6 +43,8 @@ void grub_multiboot2_set_bootdev (void);
void
grub_multiboot2_add_elfsyms (grub_size_t num, grub_size_t entsize,
unsigned shndx, void *data);
+grub_err_t grub_multiboot2_prepare_slaunch_txt (grub_uint32_t mbi_target,
+ grub_uint32_t mbi_size);

grub_uint32_t grub_multiboot2_get_mmap_count (void);
grub_err_t grub_multiboot2_set_video_mode (void);
--
2.47.0

Sergii Dmytruk

unread,
Nov 1, 2024, 6:53:41 PM11/1/24
to grub-...@gnu.org, trenchbo...@googlegroups.com
From: Krystian Hebel <krystia...@3mdeb.com>

Extend slaunch command to work on AMD CPUs and validate input binary to
reject obviously incorrect ones.

Signed-off-by: Krystian Hebel <krystia...@3mdeb.com>
Signed-off-by: Sergii Dmytruk <sergii....@3mdeb.com>
---
grub-core/lib/i386/relocator32.S | 6 ++++
grub-core/loader/i386/skinit.c | 58 ++++++++++++++++++++++++++++++++
grub-core/loader/i386/slaunch.c | 33 ++++++++++++++++--
include/grub/i386/skinit.h | 2 ++
include/grub/i386/slaunch.h | 5 +--
5 files changed, 100 insertions(+), 4 deletions(-)

diff --git a/grub-core/lib/i386/relocator32.S b/grub-core/lib/i386/relocator32.S
index a2b377197..2bdc07018 100644
--- a/grub-core/lib/i386/relocator32.S
+++ b/grub-core/lib/i386/relocator32.S
@@ -115,6 +115,9 @@ VARIABLE(grub_relocator32_edx)
cmpl $SLP_INTEL_TXT, %edi
je LOCAL(intel_txt)

+ cmpl $SLP_AMD_SKINIT, %edi
+ je LOCAL(amd_skinit)
+
.byte 0xea
VARIABLE(grub_relocator32_eip)
.long 0
@@ -123,6 +126,9 @@ VARIABLE(grub_relocator32_eip)
LOCAL(intel_txt):
getsec

+LOCAL(amd_skinit):
+ skinit
+
/* GDT. Copied from loader/i386/linux.c. */
.p2align 4
LOCAL(gdt):
diff --git a/grub-core/loader/i386/skinit.c b/grub-core/loader/i386/skinit.c
index d536630a6..0011f3ece 100644
--- a/grub-core/loader/i386/skinit.c
+++ b/grub-core/loader/i386/skinit.c
@@ -35,6 +35,64 @@
/* Offset to area for passing data to SKL. */
#define SLB_PARAM(slb) ((const grub_uint16_t *) (slb))[3]

+int
+grub_skinit_is_slb (const void *slb_base, grub_uint32_t slb_size)
+{
+ const grub_uint8_t skl_uuid[16] = {
+ 0x78, 0xf1, 0x26, 0x8e, 0x04, 0x92, 0x11, 0xe9,
+ 0x83, 0x2a, 0xc8, 0x5b, 0x76, 0xc4, 0xcc, 0x02,
+ };
+ /* We need space after SLB to pass SLRT to it. */
+ const grub_ssize_t max_size = GRUB_SKINIT_SLB_SIZE - SLRT_SIZE;
+
+ const grub_uint8_t *uuid;
+
+ if (slb_size > max_size)
+ {
+ grub_dprintf ("slaunch", "SLB is too large: %d > %zd\n",
+ slb_size, max_size);
+ return 0;
+ }
+
+ if (SLB_MEASURED (slb_base) > slb_size)
+ {
+ grub_dprintf ("slaunch", "SLB measured size is too large: %d > %d\n",
+ SLB_MEASURED (slb_base), slb_size);
+ return 0;
+ }
+
+ if (SLB_ENTRY (slb_base) >= SLB_MEASURED (slb_base))
+ {
+ grub_dprintf ("slaunch", "SLB entry is not measured: %d >= %d\n",
+ SLB_ENTRY (slb_base), SLB_MEASURED (slb_base));
+ return 0;
+ }
+
+ if (SLB_INFO (slb_base) > SLB_MEASURED (slb_base) - sizeof(skl_uuid))
+ {
+ grub_dprintf ("slaunch", "SLB info is not measured: %d > %zd\n",
+ SLB_INFO (slb_base),
+ SLB_MEASURED (slb_base) - sizeof(skl_uuid));
+ return 0;
+ }
+
+ if (SLB_PARAM (slb_base) > max_size)
+ {
+ grub_dprintf ("slaunch", "SLB bootloader data offset is too large: %d > %zd\n",
+ SLB_PARAM (slb_base), max_size);
+ return 0;
+ }
+
+ uuid = (const grub_uint8_t *) slb_base + SLB_INFO (slb_base);
+ if (grub_memcmp (uuid, skl_uuid, sizeof(skl_uuid)) != 0)
+ {
+ grub_dprintf ("slaunch", "SLB has unexpected UUID\n");
+ return 0;
+ }
+
+ return 1;
+}
+
grub_err_t
grub_skinit_boot_prepare (struct grub_relocator *rel,
struct grub_slaunch_params *slparams)
diff --git a/grub-core/loader/i386/slaunch.c b/grub-core/loader/i386/slaunch.c
index 824b5c23b..806dd8c8d 100644
--- a/grub-core/loader/i386/slaunch.c
+++ b/grub-core/loader/i386/slaunch.c
@@ -28,6 +28,7 @@
#include <grub/i386/cpuid.h>
#include <grub/i386/msr.h>
#include <grub/i386/mmio.h>
+#include <grub/i386/skinit.h>
#include <grub/i386/slaunch.h>
#include <grub/i386/tpm.h>
#include <grub/i386/txt.h>
@@ -77,6 +78,8 @@ grub_slaunch_init_slrt_storage (int arch)
/* Setup DCE and DLME information. */
slr_dl_info_staging.hdr.tag = GRUB_SLR_ENTRY_DL_INFO;
slr_dl_info_staging.hdr.size = sizeof(struct grub_slr_entry_dl_info);
+ slr_dl_info_staging.bl_context.bootloader = GRUB_SLR_BOOTLOADER_GRUB;
+ slr_dl_info_staging.bl_context.context = slparams.boot_params_addr;
slr_dl_info_staging.dce_base = slparams.dce_base;
slr_dl_info_staging.dce_size = slparams.dce_size;
slr_dl_info_staging.dlme_base = slparams.mle_start;
@@ -154,7 +157,8 @@ grub_cmd_slaunch (grub_command_t cmd __attribute__ ((unused)),
char *argv[] __attribute__ ((unused)))
{
grub_uint32_t manufacturer[3];
- grub_uint32_t eax;
+ grub_uint32_t eax, ebx, ecx, edx;
+ grub_uint64_t msr_value;
grub_err_t err;

if (!grub_cpu_is_cpuid_supported ())
@@ -176,6 +180,19 @@ grub_cmd_slaunch (grub_command_t cmd __attribute__ ((unused)),

slp = SLP_INTEL_TXT;
}
+ else if (!grub_memcmp (manufacturer, "AuthenticAMD", 12))
+ {
+ grub_cpuid (GRUB_AMD_CPUID_FEATURES, eax, ebx, ecx, edx);
+ if (! (ecx & GRUB_AMD_CPUID_FEATURES_ECX_SVM) )
+ return grub_error (GRUB_ERR_BAD_DEVICE, N_("CPU does not support AMD SVM"));
+
+ /* Check whether SVM feature is disabled in BIOS */
+ msr_value = grub_rdmsr (GRUB_MSR_AMD64_VM_CR);
+ if (msr_value & GRUB_MSR_SVM_VM_CR_SVM_DISABLE)
+ return grub_error (GRUB_ERR_BAD_DEVICE, N_("BIOS has AMD SVM disabled"));
+
+ slp = SLP_AMD_SKINIT;
+ }
else
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("CPU is unsupported"));

@@ -196,7 +213,7 @@ grub_cmd_slaunch_module (grub_command_t cmd __attribute__ ((unused)),
if (slp == SLP_NONE)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("secure launch not enabled"));

- if (slp != SLP_INTEL_TXT)
+ if (slp > SLP_AMD_SKINIT)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
N_("unknown secure launch platform type: %d"), slp);

@@ -242,6 +259,14 @@ grub_cmd_slaunch_module (grub_command_t cmd __attribute__ ((unused)),
goto fail;
}
}
+ else if (slp == SLP_AMD_SKINIT)
+ {
+ if (!grub_skinit_is_slb (new_module, size))
+ {
+ grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("it does not look like SLB"));
+ goto fail;
+ }
+ }

grub_file_close (file);

@@ -273,6 +298,10 @@ grub_cmd_slaunch_state (grub_command_t cmd __attribute__ ((unused)),
grub_printf ("Secure launcher: Intel TXT\n");
grub_txt_state_show ();
}
+ else if (slp == SLP_AMD_SKINIT)
+ {
+ grub_printf ("Secure launcher: AMD SKINIT\n");
+ }
else
return grub_error (GRUB_ERR_BAD_ARGUMENT,
N_("Unknown secure launcher platform type: %d\n"), slp);
diff --git a/include/grub/i386/skinit.h b/include/grub/i386/skinit.h
index e2d5e4fbf..2901dbbb9 100644
--- a/include/grub/i386/skinit.h
+++ b/include/grub/i386/skinit.h
@@ -28,6 +28,8 @@
#include <grub/cpu/relocator.h>
#include <grub/i386/slaunch.h>

+int grub_skinit_is_slb (const void *slb_base, grub_uint32_t slb_size);
+
grub_err_t grub_skinit_boot_prepare (struct grub_relocator *rel,
struct grub_slaunch_params *slparams);

diff --git a/include/grub/i386/slaunch.h b/include/grub/i386/slaunch.h
index 8bf7042b9..82c6134a1 100644
--- a/include/grub/i386/slaunch.h
+++ b/include/grub/i386/slaunch.h
@@ -22,8 +22,9 @@
#define GRUB_I386_SLAUNCH_H 1

/* Secure launch platform types. */
-#define SLP_NONE 0
-#define SLP_INTEL_TXT 1
+#define SLP_NONE 0
+#define SLP_INTEL_TXT 1
+#define SLP_AMD_SKINIT 2

/* PCRs used by Secure launch. */
#define GRUB_SLAUNCH_CODE_PCR 17
--
2.47.0

Sergii Dmytruk

unread,
Nov 1, 2024, 6:53:42 PM11/1/24
to grub-...@gnu.org, trenchbo...@googlegroups.com
From: Krystian Hebel <krystia...@3mdeb.com>

Hook up this platform in all the places which previously were specific
to Intel TXT.

Signed-off-by: Krystian Hebel <krystia...@3mdeb.com>
Signed-off-by: Sergii Dmytruk <sergii....@3mdeb.com>
---
grub-core/loader/multiboot.c | 11 +++++--
grub-core/loader/multiboot_elfxx.c | 22 ++++++-------
grub-core/loader/multiboot_mbi2.c | 52 +++++++++++++++++++-----------
include/grub/multiboot2.h | 4 +--
4 files changed, 55 insertions(+), 34 deletions(-)

diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c
index 561523a2b..1d1d6a2e9 100644
--- a/grub-core/loader/multiboot.c
+++ b/grub-core/loader/multiboot.c
@@ -51,6 +51,7 @@
#include <grub/memory.h>
#include <grub/i18n.h>
#if defined (__i386__) || defined (__x86_64__)
+#include <grub/i386/skinit.h>
#include <grub/i386/slaunch.h>
#include <grub/i386/txt.h>
#endif
@@ -176,6 +177,10 @@ normal_boot (struct grub_relocator *rel, struct grub_relocator32_state state)
state.ecx = slparams->dce_size;
state.edx = 0;
}
+ else if (state.edi == SLP_AMD_SKINIT)
+ {
+ state.eax = slparams->dce_base;
+ }

grub_relocator32_boot (rel, state, 0);
}
@@ -206,10 +211,10 @@ grub_multiboot_boot (void)
return err;

#ifdef GRUB_USE_MULTIBOOT2
- if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
+ if (grub_slaunch_platform_type () != SLP_NONE)
{
- err = grub_multiboot2_prepare_slaunch_txt (state.MULTIBOOT_MBI_REGISTER,
- mbi_size);
+ err = grub_multiboot2_prepare_slaunch (state.MULTIBOOT_MBI_REGISTER,
+ mbi_size);
if (err)
return err;
}
diff --git a/grub-core/loader/multiboot_elfxx.c b/grub-core/loader/multiboot_elfxx.c
index f29fbb411..374b87c52 100644
--- a/grub-core/loader/multiboot_elfxx.c
+++ b/grub-core/loader/multiboot_elfxx.c
@@ -130,13 +130,15 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)

if (mld->relocatable)
{
+#ifndef GRUB_USE_MULTIBOOT2
+ if (grub_slaunch_platform_type () != SLP_NONE)
+ return grub_error (GRUB_ERR_BAD_OS, "Only multiboot2 supported for slaunch");
+#endif
+
load_size = highest_load - mld->link_base_addr;

if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
{
-#ifndef GRUB_USE_MULTIBOOT2
- return grub_error (GRUB_ERR_BAD_OS, "Only multiboot2 supported for slaunch");
-#else
/*
* We allocate the binary together with the page tables to make one
* contiguous block for MLE.
@@ -147,7 +149,6 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
/* Do not go below GRUB_TXT_PMR_ALIGN. */
if (mld->align < GRUB_TXT_PMR_ALIGN)
mld->align = GRUB_TXT_PMR_ALIGN;
-#endif
}
else
{
@@ -179,14 +180,14 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
grub_dprintf ("multiboot_loader", "load_base_addr=0x%lx, source=0x%lx\n",
(long) mld->load_base_addr, (long) source);

- if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
+ if (grub_slaunch_platform_type () != SLP_NONE)
{
-#ifndef GRUB_USE_MULTIBOOT2
- return grub_error (GRUB_ERR_BAD_OS, "Only multiboot2 supported for slaunch");
-#else
slparams->mle_start = mld->load_base_addr;
slparams->mle_mem = source;
+ }

+ if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
+ {
err = grub_relocator_alloc_chunk_align_safe (GRUB_MULTIBOOT (relocator), &ch,
GRUB_MEMORY_MACHINE_UPPER_START,
mld->load_base_addr - slparams->mle_ptab_size,
@@ -203,14 +204,13 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
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;
/* TODO: support non-relocatable */
- if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
+ if (grub_slaunch_platform_type () != SLP_NONE)
return grub_error (GRUB_ERR_BAD_OS, "Non-relocatable ELF not supported with slaunch");
}

@@ -275,7 +275,7 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
}
}

- if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
+ if (grub_slaunch_platform_type () != SLP_NONE)
{
slparams->mle_header_offset = 0xffffffff;

diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c
index a611b5d43..b7e1575bc 100644
--- a/grub-core/loader/multiboot_mbi2.c
+++ b/grub-core/loader/multiboot_mbi2.c
@@ -37,6 +37,7 @@
#include <grub/net.h>
#include <grub/lib/cmdline.h>
#include <grub/i386/memory.h>
+#include <grub/i386/skinit.h>
#include <grub/i386/slaunch.h>
#include <grub/i386/txt.h>
#include <grub/slr_table.h>
@@ -281,7 +282,7 @@ grub_multiboot2_load (grub_file_t file, const char *filename)

if (addr_tag)
{
- if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
+ if (grub_slaunch_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)
@@ -398,7 +399,7 @@ grub_multiboot2_load (grub_file_t file, const char *filename)
accepted_consoles,
0, 0, 0, console_required);

- if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
+ if (grub_slaunch_platform_type () != SLP_NONE)
{
grub_relocator_chunk_t ch;
struct grub_slaunch_params *slparams = grub_slaunch_params();
@@ -415,6 +416,7 @@ grub_multiboot2_load (grub_file_t file, const char *filename)
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. */
grub_txt_init_tpm_event_log(get_virtual_current_address (ch),
slparams->tpm_evt_log_size);

@@ -422,7 +424,8 @@ grub_multiboot2_load (grub_file_t file, const char *filename)
(unsigned long) slparams->tpm_evt_log_base,
(unsigned) slparams->tpm_evt_log_size);

- grub_txt_setup_mle_ptab (slparams);
+ if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
+ grub_txt_setup_mle_ptab (slparams);
}

return err;
@@ -1182,27 +1185,37 @@ add_multiboot2_slrt_policy_entries (void)
}

grub_err_t
-grub_multiboot2_prepare_slaunch_txt (grub_uint32_t mbi_target,
- grub_uint32_t mbi_size)
+grub_multiboot2_prepare_slaunch (grub_uint32_t mbi_target,
+ grub_uint32_t mbi_size)
{
grub_err_t err;
struct grub_slaunch_params *slparams = grub_slaunch_params ();
+ grub_uint32_t slp = grub_slaunch_platform_type ();

slparams->boot_params_addr = mbi_target;

- slparams->slr_table_base = GRUB_SLAUNCH_STORE_IN_OS2MLE;
- slparams->slr_table_size = GRUB_PAGE_SIZE;
+ if (slp == SLP_INTEL_TXT)
+ {
+ slparams->slr_table_base = GRUB_SLAUNCH_STORE_IN_OS2MLE;
+ slparams->slr_table_size = GRUB_PAGE_SIZE;

- slparams->slr_table_mem = grub_zalloc (slparams->slr_table_size);
- if (slparams->slr_table_mem == NULL)
- return GRUB_ERR_OUT_OF_MEMORY;
+ slparams->slr_table_mem = grub_zalloc (slparams->slr_table_size);
+ if (slparams->slr_table_mem == NULL)
+ return GRUB_ERR_OUT_OF_MEMORY;

- err = grub_txt_boot_prepare (slparams);
- if (err != GRUB_ERR_NONE)
+ err = grub_txt_boot_prepare (slparams);
+ if (err != GRUB_ERR_NONE)
+ return grub_error (err, "TXT boot preparation failed");
+ }
+ else if (slp == SLP_AMD_SKINIT)
{
- grub_printf ("TXT boot preparation failed");
- return err;
+ err = grub_skinit_boot_prepare (grub_multiboot2_relocator, slparams);
+ if (err != GRUB_ERR_NONE)
+ return grub_error (err, "SKINIT preparations have failed");
}
+ else
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("Unknown secure launcher platform type: %d\n"), slp);

grub_slaunch_add_slrt_policy_entry (GRUB_SLAUNCH_DATA_PCR,
GRUB_SLR_ET_MULTIBOOT2_INFO,
@@ -1211,16 +1224,19 @@ grub_multiboot2_prepare_slaunch_txt (grub_uint32_t mbi_target,
mbi_size,
"Measured MB2 information");
grub_slaunch_add_slrt_policy_entries ();
- grub_txt_add_slrt_policy_entries ();
+ if (slp == SLP_INTEL_TXT)
+ grub_txt_add_slrt_policy_entries ();
add_multiboot2_slrt_policy_entries ();
grub_slaunch_finish_slr_table ();

grub_dprintf ("multiboot_loader", "slr_table_base = %lx, slr_table_size = %x\n",
(unsigned long) slparams->slr_table_base,
(unsigned) slparams->slr_table_size);
- grub_memcpy ((void *)(grub_addr_t) slparams->slr_table_base,
- slparams->slr_table_mem,
- slparams->slr_table_size);
+
+ if (slp == SLP_INTEL_TXT)
+ grub_memcpy ((void *)(grub_addr_t) slparams->slr_table_base,
+ slparams->slr_table_mem,
+ slparams->slr_table_size);

return GRUB_ERR_NONE;
}
diff --git a/include/grub/multiboot2.h b/include/grub/multiboot2.h
index 2e843d24e..60d104fed 100644
--- a/include/grub/multiboot2.h
+++ b/include/grub/multiboot2.h
@@ -43,8 +43,8 @@ void grub_multiboot2_set_bootdev (void);
void
grub_multiboot2_add_elfsyms (grub_size_t num, grub_size_t entsize,
unsigned shndx, void *data);
-grub_err_t grub_multiboot2_prepare_slaunch_txt (grub_uint32_t mbi_target,
- grub_uint32_t mbi_size);
+grub_err_t grub_multiboot2_prepare_slaunch (grub_uint32_t mbi_target,

Sergii Dmytruk

unread,
Nov 1, 2024, 6:53:43 PM11/1/24
to grub-...@gnu.org, trenchbo...@googlegroups.com
From: Ross Philipson <ross.ph...@oracle.com>

Signed-off-by: Ross Philipson <ross.ph...@oracle.com>
Signed-off-by: Daniel Kiper <daniel...@oracle.com>
Signed-off-by: Sergii Dmytruk <sergii....@3mdeb.com>
---
grub-core/loader/i386/linux.c | 57 ++++++++++++++++++++++++-----------
1 file changed, 40 insertions(+), 17 deletions(-)

diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
index 70d42ec8d..8d766f32c 100644
--- a/grub-core/loader/i386/linux.c
+++ b/grub-core/loader/i386/linux.c
@@ -34,6 +34,7 @@
#include <grub/i386/relocator.h>
#include <grub/i18n.h>
#include <grub/lib/cmdline.h>
+#include <grub/i386/skinit.h>
#include <grub/i386/slaunch.h>
#include <grub/i386/txt.h>
#include <grub/linux.h>
@@ -250,7 +251,7 @@ allocate_pages (grub_size_t prot_size, grub_size_t *align,
prot_mode_mem = get_virtual_current_address (ch);
prot_mode_target = get_physical_target_address (ch);

- if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
+ if (grub_slaunch_platform_type () != SLP_NONE)
{
/* Zero out memory to get stable MLE measurements. */
grub_memset (prot_mode_mem, 0, total_size);
@@ -269,22 +270,29 @@ allocate_pages (grub_size_t prot_size, grub_size_t *align,
slparams->mle_ptab_mem, (unsigned long) slparams->mle_ptab_target,
(unsigned) slparams->mle_ptab_size);

- err = grub_relocator_alloc_chunk_align (relocator, &ch, 0x1000000,
- 0xffffffff - GRUB_PAGE_SIZE,
- GRUB_PAGE_SIZE, GRUB_PAGE_SIZE,
- GRUB_RELOCATOR_PREFERENCE_NONE, 1);
- if (err)
- goto fail;
-
- slparams->slr_table_base = get_physical_target_address (ch);
- slparams->slr_table_size = GRUB_PAGE_SIZE;
- slparams->slr_table_mem = get_virtual_current_address (ch);
-
- grub_memset (slparams->slr_table_mem, 0, slparams->slr_table_size);
-
- grub_dprintf ("linux", "slr_table_base = %lx, slr_table_size = %x\n",
- (unsigned long) slparams->slr_table_base,
- (unsigned) slparams->slr_table_size);
+ /*
+ * For AMD SKINIT, SLRT is part of SLB and it will be initialized by
+ * grub_skinit_boot_prepare().
+ */
+ if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
+ {
+ err = grub_relocator_alloc_chunk_align (relocator, &ch, 0x1000000,
+ 0xffffffff - GRUB_PAGE_SIZE,
+ GRUB_PAGE_SIZE, GRUB_PAGE_SIZE,
+ GRUB_RELOCATOR_PREFERENCE_NONE, 1);
+ if (err)
+ goto fail;
+
+ slparams->slr_table_base = get_physical_target_address (ch);
+ slparams->slr_table_size = GRUB_PAGE_SIZE;
+ slparams->slr_table_mem = get_virtual_current_address (ch);
+
+ grub_memset (slparams->slr_table_mem, 0, slparams->slr_table_size);
+
+ grub_dprintf ("linux", "slr_table_base = %lx, slr_table_size = %x\n",
+ (unsigned long) slparams->slr_table_base,
+ (unsigned) slparams->slr_table_size);
+ }

err = grub_relocator_alloc_chunk_align (relocator, &ch, 0x1000000,
0xffffffff - GRUB_SLAUNCH_TPM_EVT_LOG_SIZE,
@@ -837,6 +845,21 @@ grub_linux_boot (void)
state.ecx = slparams->dce_size;
state.edx = 0;
}
+ else if (state.edi == SLP_AMD_SKINIT)
+ {
+ slparams->boot_params_addr = ctx.real_mode_target;
+
+ err = grub_skinit_boot_prepare (relocator, slparams);
+
+ if (err != GRUB_ERR_NONE)
+ return grub_error (err, "SKINIT preparations have failed");
+
+ grub_slaunch_add_slrt_policy_entries ();
+ grub_linux_setup_slr_table (slparams);
+ grub_slaunch_finish_slr_table ();
+
+ state.eax = slparams->dce_base;
+ }
else
{
/* FIXME. */
--
2.47.0

Reply all
Reply to author
Forward
0 new messages