summaryrefslogtreecommitdiff
path: root/drivers/firmware/efi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firmware/efi')
-rw-r--r--drivers/firmware/efi/arm-runtime.c2
-rw-r--r--drivers/firmware/efi/capsule-loader.c2
-rw-r--r--drivers/firmware/efi/cper.c23
-rw-r--r--drivers/firmware/efi/efi-init.c19
-rw-r--r--drivers/firmware/efi/efi-pstore.c43
-rw-r--r--drivers/firmware/efi/efi.c3
-rw-r--r--drivers/firmware/efi/libstub/Makefile6
-rw-r--r--drivers/firmware/efi/libstub/alignedmem.c1
-rw-r--r--drivers/firmware/efi/libstub/efi-stub-helper.c106
-rw-r--r--drivers/firmware/efi/libstub/efi-stub.c2
-rw-r--r--drivers/firmware/efi/libstub/efistub.h100
-rw-r--r--drivers/firmware/efi/libstub/kaslr.c2
-rw-r--r--drivers/firmware/efi/libstub/randomalloc.c12
-rw-r--r--drivers/firmware/efi/libstub/tpm.c82
-rw-r--r--drivers/firmware/efi/libstub/x86-stub.c45
-rw-r--r--drivers/firmware/efi/libstub/x86-stub.h4
-rw-r--r--drivers/firmware/efi/libstub/zboot.c2
-rw-r--r--drivers/firmware/efi/riscv-runtime.c2
-rw-r--r--drivers/firmware/efi/sysfb_efi.c2
19 files changed, 343 insertions, 115 deletions
diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c
index 83f5bb57fa4c..83092d93f36a 100644
--- a/drivers/firmware/efi/arm-runtime.c
+++ b/drivers/firmware/efi/arm-runtime.c
@@ -107,7 +107,7 @@ static int __init arm_enable_runtime_services(void)
efi_memory_desc_t *md;
for_each_efi_memory_desc(md) {
- int md_size = md->num_pages << EFI_PAGE_SHIFT;
+ u64 md_size = md->num_pages << EFI_PAGE_SHIFT;
struct resource *res;
if (!(md->attribute & EFI_MEMORY_SP))
diff --git a/drivers/firmware/efi/capsule-loader.c b/drivers/firmware/efi/capsule-loader.c
index 3e8d4b51a814..97bafb5f7038 100644
--- a/drivers/firmware/efi/capsule-loader.c
+++ b/drivers/firmware/efi/capsule-loader.c
@@ -292,7 +292,7 @@ static int efi_capsule_open(struct inode *inode, struct file *file)
return -ENOMEM;
}
- cap_info->phys = kzalloc(sizeof(void *), GFP_KERNEL);
+ cap_info->phys = kzalloc(sizeof(phys_addr_t), GFP_KERNEL);
if (!cap_info->phys) {
kfree(cap_info->pages);
kfree(cap_info);
diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
index 35c37f667781..7d2cdd9e2227 100644
--- a/drivers/firmware/efi/cper.c
+++ b/drivers/firmware/efi/cper.c
@@ -445,8 +445,8 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie,
printk("%saer_uncor_severity: 0x%08x\n",
pfx, aer->uncor_severity);
printk("%sTLP Header: %08x %08x %08x %08x\n", pfx,
- aer->header_log.dw0, aer->header_log.dw1,
- aer->header_log.dw2, aer->header_log.dw3);
+ aer->header_log.dw[0], aer->header_log.dw[1],
+ aer->header_log.dw[2], aer->header_log.dw[3]);
}
}
@@ -523,6 +523,17 @@ static void cper_print_tstamp(const char *pfx,
}
}
+struct ignore_section {
+ guid_t guid;
+ const char *name;
+};
+
+static const struct ignore_section ignore_sections[] = {
+ { .guid = CPER_SEC_CXL_GEN_MEDIA_GUID, .name = "CXL General Media Event" },
+ { .guid = CPER_SEC_CXL_DRAM_GUID, .name = "CXL DRAM Event" },
+ { .guid = CPER_SEC_CXL_MEM_MODULE_GUID, .name = "CXL Memory Module Event" },
+};
+
static void
cper_estatus_print_section(const char *pfx, struct acpi_hest_generic_data *gdata,
int sec_no)
@@ -543,6 +554,14 @@ cper_estatus_print_section(const char *pfx, struct acpi_hest_generic_data *gdata
printk("%s""fru_text: %.20s\n", pfx, gdata->fru_text);
snprintf(newpfx, sizeof(newpfx), "%s ", pfx);
+
+ for (int i = 0; i < ARRAY_SIZE(ignore_sections); i++) {
+ if (guid_equal(sec_type, &ignore_sections[i].guid)) {
+ printk("%ssection_type: %s\n", newpfx, ignore_sections[i].name);
+ return;
+ }
+ }
+
if (guid_equal(sec_type, &CPER_SEC_PROC_GENERIC)) {
struct cper_sec_proc_generic *proc_err = acpi_hest_get_payload(gdata);
diff --git a/drivers/firmware/efi/efi-init.c b/drivers/firmware/efi/efi-init.c
index d4987d013080..a00e07b853f2 100644
--- a/drivers/firmware/efi/efi-init.c
+++ b/drivers/firmware/efi/efi-init.c
@@ -144,15 +144,6 @@ static __init int is_usable_memory(efi_memory_desc_t *md)
case EFI_CONVENTIONAL_MEMORY:
case EFI_PERSISTENT_MEMORY:
/*
- * Special purpose memory is 'soft reserved', which means it
- * is set aside initially, but can be hotplugged back in or
- * be assigned to the dax driver after boot.
- */
- if (efi_soft_reserve_enabled() &&
- (md->attribute & EFI_MEMORY_SP))
- return false;
-
- /*
* According to the spec, these regions are no longer reserved
* after calling ExitBootServices(). However, we can only use
* them as System RAM if they can be mapped writeback cacheable.
@@ -196,6 +187,16 @@ static __init void reserve_regions(void)
size = npages << PAGE_SHIFT;
if (is_memory(md)) {
+ /*
+ * Special purpose memory is 'soft reserved', which
+ * means it is set aside initially. Don't add a memblock
+ * for it now so that it can be hotplugged back in or
+ * be assigned to the dax driver after boot.
+ */
+ if (efi_soft_reserve_enabled() &&
+ (md->attribute & EFI_MEMORY_SP))
+ continue;
+
early_init_dt_add_memory_arch(paddr, size);
if (!is_usable_memory(md))
diff --git a/drivers/firmware/efi/efi-pstore.c b/drivers/firmware/efi/efi-pstore.c
index e7b9ec6f8a86..833cbb995dd3 100644
--- a/drivers/firmware/efi/efi-pstore.c
+++ b/drivers/firmware/efi/efi-pstore.c
@@ -14,16 +14,43 @@ static unsigned int record_size = 1024;
module_param(record_size, uint, 0444);
MODULE_PARM_DESC(record_size, "size of each pstore UEFI var (in bytes, min/default=1024)");
-static bool efivars_pstore_disable =
- IS_ENABLED(CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE);
-
-module_param_named(pstore_disable, efivars_pstore_disable, bool, 0644);
-
#define PSTORE_EFI_ATTRIBUTES \
(EFI_VARIABLE_NON_VOLATILE | \
EFI_VARIABLE_BOOTSERVICE_ACCESS | \
EFI_VARIABLE_RUNTIME_ACCESS)
+static bool pstore_disable = IS_ENABLED(CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE);
+
+static int efivars_pstore_init(void);
+static void efivars_pstore_exit(void);
+
+static int efi_pstore_disable_set(const char *val, const struct kernel_param *kp)
+{
+ int err;
+ bool old_pstore_disable = pstore_disable;
+
+ err = param_set_bool(val, kp);
+ if (err)
+ return err;
+
+ if (old_pstore_disable != pstore_disable) {
+ if (pstore_disable)
+ efivars_pstore_exit();
+ else
+ efivars_pstore_init();
+ }
+
+ return 0;
+}
+
+static const struct kernel_param_ops pstore_disable_ops = {
+ .set = efi_pstore_disable_set,
+ .get = param_get_bool,
+};
+
+module_param_cb(pstore_disable, &pstore_disable_ops, &pstore_disable, 0644);
+__MODULE_PARM_TYPE(pstore_disable, "bool");
+
static int efi_pstore_open(struct pstore_info *psi)
{
int err;
@@ -218,12 +245,12 @@ static struct pstore_info efi_pstore_info = {
.erase = efi_pstore_erase,
};
-static __init int efivars_pstore_init(void)
+static int efivars_pstore_init(void)
{
if (!efivar_supports_writes())
return 0;
- if (efivars_pstore_disable)
+ if (pstore_disable)
return 0;
/*
@@ -250,7 +277,7 @@ static __init int efivars_pstore_init(void)
return 0;
}
-static __exit void efivars_pstore_exit(void)
+static void efivars_pstore_exit(void)
{
if (!efi_pstore_info.bufsize)
return;
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 4fcda50acfa4..8859fb0b006d 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -597,7 +597,8 @@ static const efi_config_table_type_t common_tables[] __initconst = {
{EFI_MEMORY_ATTRIBUTES_TABLE_GUID, &efi_mem_attr_table, "MEMATTR" },
{LINUX_EFI_RANDOM_SEED_TABLE_GUID, &efi_rng_seed, "RNG" },
{LINUX_EFI_TPM_EVENT_LOG_GUID, &efi.tpm_log, "TPMEventLog" },
- {LINUX_EFI_TPM_FINAL_LOG_GUID, &efi.tpm_final_log, "TPMFinalLog" },
+ {EFI_TCG2_FINAL_EVENTS_TABLE_GUID, &efi.tpm_final_log, "TPMFinalLog" },
+ {EFI_CC_FINAL_EVENTS_TABLE_GUID, &efi.tpm_final_log, "CCFinalLog" },
{LINUX_EFI_MEMRESERVE_TABLE_GUID, &mem_reserve, "MEMRESERVE" },
{LINUX_EFI_INITRD_MEDIA_GUID, &initrd, "INITRD" },
{EFI_RT_PROPERTIES_TABLE_GUID, &rt_prop, "RTPROP" },
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
index 06964a3c130f..31eb1e287ce1 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -28,7 +28,7 @@ cflags-$(CONFIG_ARM) += -DEFI_HAVE_STRLEN -DEFI_HAVE_STRNLEN \
-DEFI_HAVE_MEMCHR -DEFI_HAVE_STRRCHR \
-DEFI_HAVE_STRCMP -fno-builtin -fpic \
$(call cc-option,-mno-single-pic-base)
-cflags-$(CONFIG_RISCV) += -fpic -DNO_ALTERNATIVE
+cflags-$(CONFIG_RISCV) += -fpic -DNO_ALTERNATIVE -mno-relax
cflags-$(CONFIG_LOONGARCH) += -fpie
cflags-$(CONFIG_EFI_PARAMS_FROM_FDT) += -I$(srctree)/scripts/dtc/libfdt
@@ -105,7 +105,7 @@ lib-y := $(patsubst %.o,%.stub.o,$(lib-y))
# Even when -mbranch-protection=none is set, Clang will generate a
# .note.gnu.property for code-less object files (like lib/ctype.c),
# so work around this by explicitly removing the unwanted section.
-# https://bugs.llvm.org/show_bug.cgi?id=46480
+# https://llvm.org/pr46480
STUBCOPY_FLAGS-y += --remove-section=.note.gnu.property
STUBCOPY_RELOC-$(CONFIG_X86_32) := R_386_32
@@ -143,7 +143,7 @@ STUBCOPY_RELOC-$(CONFIG_ARM64) := R_AARCH64_ABS
# exist.
STUBCOPY_FLAGS-$(CONFIG_RISCV) += --prefix-alloc-sections=.init \
--prefix-symbols=__efistub_
-STUBCOPY_RELOC-$(CONFIG_RISCV) := R_RISCV_HI20
+STUBCOPY_RELOC-$(CONFIG_RISCV) := -E R_RISCV_HI20\|R_RISCV_$(BITS)\|R_RISCV_RELAX
# For LoongArch, keep all the symbols in .init section and make sure that no
# absolute symbols references exist.
diff --git a/drivers/firmware/efi/libstub/alignedmem.c b/drivers/firmware/efi/libstub/alignedmem.c
index 6b83c492c3b8..31928bd87e0f 100644
--- a/drivers/firmware/efi/libstub/alignedmem.c
+++ b/drivers/firmware/efi/libstub/alignedmem.c
@@ -14,6 +14,7 @@
* @max: the address that the last allocated memory page shall not
* exceed
* @align: minimum alignment of the base of the allocation
+ * @memory_type: the type of memory to allocate
*
* Allocate pages as EFI_LOADER_DATA. The allocated pages are aligned according
* to @align, which should be >= EFI_ALLOC_ALIGN. The last allocated page will
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index bfa30625f5d0..de659f6a815f 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -11,6 +11,7 @@
#include <linux/efi.h>
#include <linux/kernel.h>
+#include <linux/overflow.h>
#include <asm/efi.h>
#include <asm/setup.h>
@@ -24,6 +25,8 @@ static bool efi_noinitrd;
static bool efi_nosoftreserve;
static bool efi_disable_pci_dma = IS_ENABLED(CONFIG_EFI_DISABLE_PCI_DMA);
+int efi_mem_encrypt;
+
bool __pure __efi_soft_reserve_enabled(void)
{
return !efi_nosoftreserve;
@@ -75,6 +78,12 @@ efi_status_t efi_parse_options(char const *cmdline)
efi_noinitrd = true;
} else if (IS_ENABLED(CONFIG_X86_64) && !strcmp(param, "no5lvl")) {
efi_no5lvl = true;
+ } else if (IS_ENABLED(CONFIG_ARCH_HAS_MEM_ENCRYPT) &&
+ !strcmp(param, "mem_encrypt") && val) {
+ if (parse_option_str(val, "on"))
+ efi_mem_encrypt = 1;
+ else if (parse_option_str(val, "off"))
+ efi_mem_encrypt = -1;
} else if (!strcmp(param, "efi") && val) {
efi_nochunk = parse_option_str(val, "nochunk");
efi_novamap |= parse_option_str(val, "novamap");
@@ -193,7 +202,7 @@ void efi_apply_loadoptions_quirk(const void **load_options, u32 *load_options_si
*load_options_size = load_option_unpacked.optional_data_size;
}
-enum efistub_event {
+enum efistub_event_type {
EFISTUB_EVT_INITRD,
EFISTUB_EVT_LOAD_OPTIONS,
EFISTUB_EVT_COUNT,
@@ -219,54 +228,95 @@ static const struct {
},
};
+static_assert(sizeof(efi_tcg2_event_t) == sizeof(efi_cc_event_t));
+
+union efistub_event {
+ efi_tcg2_event_t tcg2_data;
+ efi_cc_event_t cc_data;
+};
+
+struct efistub_measured_event {
+ union efistub_event event_data;
+ TCG_PCClientTaggedEvent tagged_event __packed;
+};
+
static efi_status_t efi_measure_tagged_event(unsigned long load_addr,
unsigned long load_size,
- enum efistub_event event)
+ enum efistub_event_type event)
{
+ union {
+ efi_status_t
+ (__efiapi *hash_log_extend_event)(void *, u64, efi_physical_addr_t,
+ u64, const union efistub_event *);
+ struct { u32 hash_log_extend_event; } mixed_mode;
+ } method;
+ struct efistub_measured_event *evt;
+ int size = struct_size(evt, tagged_event.tagged_event_data,
+ events[event].event_data_len);
efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID;
efi_tcg2_protocol_t *tcg2 = NULL;
+ union efistub_event ev;
efi_status_t status;
+ void *protocol;
efi_bs_call(locate_protocol, &tcg2_guid, NULL, (void **)&tcg2);
if (tcg2) {
- struct efi_measured_event {
- efi_tcg2_event_t event_data;
- efi_tcg2_tagged_event_t tagged_event;
- u8 tagged_event_data[];
- } *evt;
- int size = sizeof(*evt) + events[event].event_data_len;
-
- status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, size,
- (void **)&evt);
- if (status != EFI_SUCCESS)
- goto fail;
-
- evt->event_data = (struct efi_tcg2_event){
+ ev.tcg2_data = (struct efi_tcg2_event){
.event_size = size,
- .event_header.header_size = sizeof(evt->event_data.event_header),
+ .event_header.header_size = sizeof(ev.tcg2_data.event_header),
.event_header.header_version = EFI_TCG2_EVENT_HEADER_VERSION,
.event_header.pcr_index = events[event].pcr_index,
.event_header.event_type = EV_EVENT_TAG,
};
+ protocol = tcg2;
+ method.hash_log_extend_event =
+ (void *)efi_table_attr(tcg2, hash_log_extend_event);
+ } else {
+ efi_guid_t cc_guid = EFI_CC_MEASUREMENT_PROTOCOL_GUID;
+ efi_cc_protocol_t *cc = NULL;
- evt->tagged_event = (struct efi_tcg2_tagged_event){
- .tagged_event_id = events[event].event_id,
- .tagged_event_data_size = events[event].event_data_len,
- };
-
- memcpy(evt->tagged_event_data, events[event].event_data,
- events[event].event_data_len);
+ efi_bs_call(locate_protocol, &cc_guid, NULL, (void **)&cc);
+ if (!cc)
+ return EFI_UNSUPPORTED;
- status = efi_call_proto(tcg2, hash_log_extend_event, 0,
- load_addr, load_size, &evt->event_data);
- efi_bs_call(free_pool, evt);
+ ev.cc_data = (struct efi_cc_event){
+ .event_size = size,
+ .event_header.header_size = sizeof(ev.cc_data.event_header),
+ .event_header.header_version = EFI_CC_EVENT_HEADER_VERSION,
+ .event_header.event_type = EV_EVENT_TAG,
+ };
+ status = efi_call_proto(cc, map_pcr_to_mr_index,
+ events[event].pcr_index,
+ &ev.cc_data.event_header.mr_index);
if (status != EFI_SUCCESS)
goto fail;
- return EFI_SUCCESS;
+
+ protocol = cc;
+ method.hash_log_extend_event =
+ (void *)efi_table_attr(cc, hash_log_extend_event);
}
- return EFI_UNSUPPORTED;
+ status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, size, (void **)&evt);
+ if (status != EFI_SUCCESS)
+ goto fail;
+
+ *evt = (struct efistub_measured_event) {
+ .event_data = ev,
+ .tagged_event.tagged_event_id = events[event].event_id,
+ .tagged_event.tagged_event_data_size = events[event].event_data_len,
+ };
+
+ memcpy(evt->tagged_event.tagged_event_data, events[event].event_data,
+ events[event].event_data_len);
+
+ status = efi_fn_call(&method, hash_log_extend_event, protocol, 0,
+ load_addr, load_size, &evt->event_data);
+ efi_bs_call(free_pool, evt);
+
+ if (status == EFI_SUCCESS)
+ return EFI_SUCCESS;
+
fail:
efi_warn("Failed to measure data for event %d: 0x%lx\n", event, status);
return status;
diff --git a/drivers/firmware/efi/libstub/efi-stub.c b/drivers/firmware/efi/libstub/efi-stub.c
index f9c1e8a2bd1d..958a680e0660 100644
--- a/drivers/firmware/efi/libstub/efi-stub.c
+++ b/drivers/firmware/efi/libstub/efi-stub.c
@@ -167,7 +167,7 @@ efi_status_t efi_stub_common(efi_handle_t handle,
si = setup_graphics();
- efi_retrieve_tpm2_eventlog();
+ efi_retrieve_eventlog();
/* Ask the firmware to clear memory on unclean shutdown */
efi_enable_reset_attack_mitigation();
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index 212687c30d79..27abb4ce0291 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -37,8 +37,8 @@ extern bool efi_no5lvl;
extern bool efi_nochunk;
extern bool efi_nokaslr;
extern int efi_loglevel;
+extern int efi_mem_encrypt;
extern bool efi_novamap;
-
extern const efi_system_table_t *efi_system_table;
typedef union efi_dxe_services_table efi_dxe_services_table_t;
@@ -843,14 +843,14 @@ struct efi_tcg2_event {
/* u8[] event follows here */
} __packed;
-struct efi_tcg2_tagged_event {
- u32 tagged_event_id;
- u32 tagged_event_data_size;
- /* u8 tagged event data follows here */
-} __packed;
+/* from TCG PC Client Platform Firmware Profile Specification */
+typedef struct tdTCG_PCClientTaggedEvent {
+ u32 tagged_event_id;
+ u32 tagged_event_data_size;
+ u8 tagged_event_data[];
+} TCG_PCClientTaggedEvent;
typedef struct efi_tcg2_event efi_tcg2_event_t;
-typedef struct efi_tcg2_tagged_event efi_tcg2_tagged_event_t;
typedef union efi_tcg2_protocol efi_tcg2_protocol_t;
union efi_tcg2_protocol {
@@ -882,6 +882,87 @@ union efi_tcg2_protocol {
} mixed_mode;
};
+typedef struct {
+ u8 major;
+ u8 minor;
+} efi_cc_version_t;
+
+typedef struct {
+ u8 type;
+ u8 sub_type;
+} efi_cc_type_t;
+
+/* EFI CC type/subtype defines */
+#define EFI_CC_TYPE_NONE 0
+#define EFI_CC_TYPE_AMD_SEV 1
+#define EFI_CC_TYPE_INTEL_TDX 2
+
+typedef u32 efi_cc_mr_index_t;
+
+struct efi_cc_event {
+ u32 event_size;
+ struct {
+ u32 header_size;
+ u16 header_version;
+ u32 mr_index;
+ u32 event_type;
+ } __packed event_header;
+ /* u8[] event follows here */
+} __packed;
+
+typedef struct efi_cc_event efi_cc_event_t;
+
+typedef u32 efi_cc_event_log_bitmap_t;
+typedef u32 efi_cc_event_log_format_t;
+typedef u32 efi_cc_event_algorithm_bitmap_t;
+
+typedef struct {
+ u8 size;
+ efi_cc_version_t structure_version;
+ efi_cc_version_t protocol_version;
+ efi_cc_event_algorithm_bitmap_t hash_algorithm_bitmap;
+ efi_cc_event_log_bitmap_t supported_event_logs;
+ efi_cc_type_t cc_type;
+} efi_cc_boot_service_cap_t;
+
+#define EFI_CC_EVENT_HEADER_VERSION 1
+
+#define EFI_CC_BOOT_HASH_ALG_SHA384 0x00000004
+
+#define EFI_CC_EVENT_LOG_FORMAT_TCG_2 0x00000002
+
+typedef union efi_cc_protocol efi_cc_protocol_t;
+
+union efi_cc_protocol {
+ struct {
+ efi_status_t
+ (__efiapi *get_capability)(efi_cc_protocol_t *,
+ efi_cc_boot_service_cap_t *);
+
+ efi_status_t
+ (__efiapi *get_event_log)(efi_cc_protocol_t *,
+ efi_cc_event_log_format_t,
+ efi_physical_addr_t *,
+ efi_physical_addr_t *,
+ efi_bool_t *);
+
+ efi_status_t
+ (__efiapi *hash_log_extend_event)(efi_cc_protocol_t *, u64,
+ efi_physical_addr_t, u64,
+ const efi_cc_event_t *);
+
+ efi_status_t
+ (__efiapi *map_pcr_to_mr_index)(efi_cc_protocol_t *, u32,
+ efi_cc_mr_index_t *);
+ };
+ struct {
+ u32 get_capability;
+ u32 get_event_log;
+ u32 hash_log_extend_event;
+ u32 map_pcr_to_mr_index;
+ } mixed_mode;
+};
+
struct riscv_efi_boot_protocol {
u64 revision;
@@ -956,7 +1037,8 @@ efi_status_t efi_get_random_bytes(unsigned long size, u8 *out);
efi_status_t efi_random_alloc(unsigned long size, unsigned long align,
unsigned long *addr, unsigned long random_seed,
- int memory_type, unsigned long alloc_limit);
+ int memory_type, unsigned long alloc_min,
+ unsigned long alloc_max);
efi_status_t efi_random_get_seed(void);
@@ -1060,7 +1142,7 @@ static inline void
efi_enable_reset_attack_mitigation(void) { }
#endif
-void efi_retrieve_tpm2_eventlog(void);
+void efi_retrieve_eventlog(void);
struct screen_info *alloc_screen_info(void);
struct screen_info *__alloc_screen_info(void);
diff --git a/drivers/firmware/efi/libstub/kaslr.c b/drivers/firmware/efi/libstub/kaslr.c
index 62d63f7a2645..1a9808012abd 100644
--- a/drivers/firmware/efi/libstub/kaslr.c
+++ b/drivers/firmware/efi/libstub/kaslr.c
@@ -119,7 +119,7 @@ efi_status_t efi_kaslr_relocate_kernel(unsigned long *image_addr,
*/
status = efi_random_alloc(*reserve_size, min_kimg_align,
reserve_addr, phys_seed,
- EFI_LOADER_CODE, EFI_ALLOC_LIMIT);
+ EFI_LOADER_CODE, 0, EFI_ALLOC_LIMIT);
if (status != EFI_SUCCESS)
efi_warn("efi_random_alloc() failed: 0x%lx\n", status);
} else {
diff --git a/drivers/firmware/efi/libstub/randomalloc.c b/drivers/firmware/efi/libstub/randomalloc.c
index 674a064b8f7a..4e96a855fdf4 100644
--- a/drivers/firmware/efi/libstub/randomalloc.c
+++ b/drivers/firmware/efi/libstub/randomalloc.c
@@ -17,7 +17,7 @@
static unsigned long get_entry_num_slots(efi_memory_desc_t *md,
unsigned long size,
unsigned long align_shift,
- u64 alloc_limit)
+ u64 alloc_min, u64 alloc_max)
{
unsigned long align = 1UL << align_shift;
u64 first_slot, last_slot, region_end;
@@ -30,11 +30,11 @@ static unsigned long get_entry_num_slots(efi_memory_desc_t *md,
return 0;
region_end = min(md->phys_addr + md->num_pages * EFI_PAGE_SIZE - 1,
- alloc_limit);
+ alloc_max);
if (region_end < size)
return 0;
- first_slot = round_up(md->phys_addr, align);
+ first_slot = round_up(max(md->phys_addr, alloc_min), align);
last_slot = round_down(region_end - size + 1, align);
if (first_slot > last_slot)
@@ -56,7 +56,8 @@ efi_status_t efi_random_alloc(unsigned long size,
unsigned long *addr,
unsigned long random_seed,
int memory_type,
- unsigned long alloc_limit)
+ unsigned long alloc_min,
+ unsigned long alloc_max)
{
unsigned long total_slots = 0, target_slot;
unsigned long total_mirrored_slots = 0;
@@ -78,7 +79,8 @@ efi_status_t efi_random_alloc(unsigned long size,
efi_memory_desc_t *md = (void *)map->map + map_offset;
unsigned long slots;
- slots = get_entry_num_slots(md, size, ilog2(align), alloc_limit);
+ slots = get_entry_num_slots(md, size, ilog2(align), alloc_min,
+ alloc_max);
MD_NUM_SLOTS(md) = slots;
total_slots += slots;
if (md->attribute & EFI_MEMORY_MORE_RELIABLE)
diff --git a/drivers/firmware/efi/libstub/tpm.c b/drivers/firmware/efi/libstub/tpm.c
index 7acbac16eae0..df3182f2e63a 100644
--- a/drivers/firmware/efi/libstub/tpm.c
+++ b/drivers/firmware/efi/libstub/tpm.c
@@ -47,39 +47,18 @@ void efi_enable_reset_attack_mitigation(void)
#endif
-void efi_retrieve_tpm2_eventlog(void)
+static void efi_retrieve_tcg2_eventlog(int version, efi_physical_addr_t log_location,
+ efi_physical_addr_t log_last_entry,
+ efi_bool_t truncated,
+ struct efi_tcg2_final_events_table *final_events_table)
{
- efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID;
efi_guid_t linux_eventlog_guid = LINUX_EFI_TPM_EVENT_LOG_GUID;
efi_status_t status;
- efi_physical_addr_t log_location = 0, log_last_entry = 0;
struct linux_efi_tpm_eventlog *log_tbl = NULL;
- struct efi_tcg2_final_events_table *final_events_table = NULL;
unsigned long first_entry_addr, last_entry_addr;
size_t log_size, last_entry_size;
- efi_bool_t truncated;
- int version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
- efi_tcg2_protocol_t *tcg2_protocol = NULL;
int final_events_size = 0;
- status = efi_bs_call(locate_protocol, &tcg2_guid, NULL,
- (void **)&tcg2_protocol);
- if (status != EFI_SUCCESS)
- return;
-
- status = efi_call_proto(tcg2_protocol, get_event_log, version,
- &log_location, &log_last_entry, &truncated);
-
- if (status != EFI_SUCCESS || !log_location) {
- version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
- status = efi_call_proto(tcg2_protocol, get_event_log, version,
- &log_location, &log_last_entry,
- &truncated);
- if (status != EFI_SUCCESS || !log_location)
- return;
-
- }
-
first_entry_addr = (unsigned long) log_location;
/*
@@ -93,8 +72,10 @@ void efi_retrieve_tpm2_eventlog(void)
* get_event_log only returns the address of the last entry.
* We need to calculate its size to deduce the full size of
* the logs.
+ *
+ * CC Event log also uses TCG2 format, handle it same as TPM2.
*/
- if (version == EFI_TCG2_EVENT_LOG_FORMAT_TCG_2) {
+ if (version > EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2) {
/*
* The TCG2 log format has variable length entries,
* and the information to decode the hash algorithms
@@ -127,8 +108,6 @@ void efi_retrieve_tpm2_eventlog(void)
* Figure out whether any events have already been logged to the
* final events structure, and if so how much space they take up
*/
- if (version == EFI_TCG2_EVENT_LOG_FORMAT_TCG_2)
- final_events_table = get_efi_config_table(LINUX_EFI_TPM_FINAL_LOG_GUID);
if (final_events_table && final_events_table->nr_events) {
struct tcg_pcr_event2_head *header;
int offset;
@@ -165,3 +144,50 @@ void efi_retrieve_tpm2_eventlog(void)
err_free:
efi_bs_call(free_pool, log_tbl);
}
+
+void efi_retrieve_eventlog(void)
+{
+ struct efi_tcg2_final_events_table *final_events_table = NULL;
+ efi_physical_addr_t log_location = 0, log_last_entry = 0;
+ efi_guid_t tpm2_guid = EFI_TCG2_PROTOCOL_GUID;
+ int version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
+ efi_tcg2_protocol_t *tpm2 = NULL;
+ efi_bool_t truncated;
+ efi_status_t status;
+
+ status = efi_bs_call(locate_protocol, &tpm2_guid, NULL, (void **)&tpm2);
+ if (status == EFI_SUCCESS) {
+ status = efi_call_proto(tpm2, get_event_log, version, &log_location,
+ &log_last_entry, &truncated);
+
+ if (status != EFI_SUCCESS || !log_location) {
+ version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
+ status = efi_call_proto(tpm2, get_event_log, version,
+ &log_location, &log_last_entry,
+ &truncated);
+ } else {
+ final_events_table =
+ get_efi_config_table(EFI_TCG2_FINAL_EVENTS_TABLE_GUID);
+ }
+ } else {
+ efi_guid_t cc_guid = EFI_CC_MEASUREMENT_PROTOCOL_GUID;
+ efi_cc_protocol_t *cc = NULL;
+
+ status = efi_bs_call(locate_protocol, &cc_guid, NULL, (void **)&cc);
+ if (status != EFI_SUCCESS)
+ return;
+
+ version = EFI_CC_EVENT_LOG_FORMAT_TCG_2;
+ status = efi_call_proto(cc, get_event_log, version, &log_location,
+ &log_last_entry, &truncated);
+
+ final_events_table =
+ get_efi_config_table(EFI_CC_FINAL_EVENTS_TABLE_GUID);
+ }
+
+ if (status != EFI_SUCCESS || !log_location)
+ return;
+
+ efi_retrieve_tcg2_eventlog(version, log_location, log_last_entry,
+ truncated, final_events_table);
+}
diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
index 0d510c9a06a4..57888614e90f 100644
--- a/drivers/firmware/efi/libstub/x86-stub.c
+++ b/drivers/firmware/efi/libstub/x86-stub.c
@@ -21,6 +21,8 @@
#include "efistub.h"
#include "x86-stub.h"
+extern char _bss[], _ebss[];
+
const efi_system_table_t *efi_system_table;
const efi_dxe_services_table_t *efi_dxe_table;
static efi_loaded_image_t *image = NULL;
@@ -223,8 +225,8 @@ static void retrieve_apple_device_properties(struct boot_params *boot_params)
}
}
-void efi_adjust_memory_range_protection(unsigned long start,
- unsigned long size)
+efi_status_t efi_adjust_memory_range_protection(unsigned long start,
+ unsigned long size)
{
efi_status_t status;
efi_gcd_memory_space_desc_t desc;
@@ -236,13 +238,26 @@ void efi_adjust_memory_range_protection(unsigned long start,
rounded_end = roundup(start + size, EFI_PAGE_SIZE);
if (memattr != NULL) {
- efi_call_proto(memattr, clear_memory_attributes, rounded_start,
- rounded_end - rounded_start, EFI_MEMORY_XP);
- return;
+ status = efi_call_proto(memattr, set_memory_attributes,
+ rounded_start,
+ rounded_end - rounded_start,
+ EFI_MEMORY_RO);
+ if (status != EFI_SUCCESS) {
+ efi_warn("Failed to set EFI_MEMORY_RO attribute\n");
+ return status;
+ }
+
+ status = efi_call_proto(memattr, clear_memory_attributes,
+ rounded_start,
+ rounded_end - rounded_start,
+ EFI_MEMORY_XP);
+ if (status != EFI_SUCCESS)
+ efi_warn("Failed to clear EFI_MEMORY_XP attribute\n");
+ return status;
}
if (efi_dxe_table == NULL)
- return;
+ return EFI_SUCCESS;
/*
* Don't modify memory region attributes, they are
@@ -255,7 +270,7 @@ void efi_adjust_memory_range_protection(unsigned long start,
status = efi_dxe_call(get_memory_space_descriptor, start, &desc);
if (status != EFI_SUCCESS)
- return;
+ break;
next = desc.base_address + desc.length;
@@ -280,8 +295,10 @@ void efi_adjust_memory_range_protection(unsigned long start,
unprotect_start,
unprotect_start + unprotect_size,
status);
+ break;
}
}
+ return EFI_SUCCESS;
}
static void setup_unaccepted_memory(void)
@@ -459,6 +476,8 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
efi_status_t status;
char *cmdline_ptr;
+ memset(_bss, 0, _ebss - _bss);
+
efi_system_table = sys_table_arg;
/* Check if we were booted by the EFI firmware */
@@ -793,6 +812,7 @@ static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry)
status = efi_random_alloc(alloc_size, CONFIG_PHYSICAL_ALIGN, &addr,
seed[0], EFI_LOADER_CODE,
+ LOAD_PHYSICAL_ADDR,
EFI_X86_KERNEL_ALLOC_LIMIT);
if (status != EFI_SUCCESS)
return status;
@@ -805,9 +825,7 @@ static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry)
*kernel_entry = addr + entry;
- efi_adjust_memory_range_protection(addr, kernel_total_size);
-
- return EFI_SUCCESS;
+ return efi_adjust_memory_range_protection(addr, kernel_text_size);
}
static void __noreturn enter_kernel(unsigned long kernel_addr,
@@ -879,6 +897,9 @@ void __noreturn efi_stub_entry(efi_handle_t handle,
}
}
+ if (efi_mem_encrypt > 0)
+ hdr->xloadflags |= XLF_MEM_ENCRYPTION;
+
status = efi_decompress_kernel(&kernel_entry);
if (status != EFI_SUCCESS) {
efi_err("Failed to decompress kernel\n");
@@ -918,7 +939,7 @@ void __noreturn efi_stub_entry(efi_handle_t handle,
efi_random_get_seed();
- efi_retrieve_tpm2_eventlog();
+ efi_retrieve_eventlog();
setup_graphics(boot_params);
@@ -953,8 +974,6 @@ fail:
void efi_handover_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg,
struct boot_params *boot_params)
{
- extern char _bss[], _ebss[];
-
memset(_bss, 0, _ebss - _bss);
efi_stub_entry(handle, sys_table_arg, boot_params);
}
diff --git a/drivers/firmware/efi/libstub/x86-stub.h b/drivers/firmware/efi/libstub/x86-stub.h
index 37c5a36b9d8c..1c20e99a6494 100644
--- a/drivers/firmware/efi/libstub/x86-stub.h
+++ b/drivers/firmware/efi/libstub/x86-stub.h
@@ -5,8 +5,8 @@
extern void trampoline_32bit_src(void *, bool);
extern const u16 trampoline_ljmp_imm_offset;
-void efi_adjust_memory_range_protection(unsigned long start,
- unsigned long size);
+efi_status_t efi_adjust_memory_range_protection(unsigned long start,
+ unsigned long size);
#ifdef CONFIG_X86_64
efi_status_t efi_setup_5level_paging(void);
diff --git a/drivers/firmware/efi/libstub/zboot.c b/drivers/firmware/efi/libstub/zboot.c
index bdb17eac0cb4..1ceace956758 100644
--- a/drivers/firmware/efi/libstub/zboot.c
+++ b/drivers/firmware/efi/libstub/zboot.c
@@ -119,7 +119,7 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
}
status = efi_random_alloc(alloc_size, min_kimg_align, &image_base,
- seed, EFI_LOADER_CODE, EFI_ALLOC_LIMIT);
+ seed, EFI_LOADER_CODE, 0, EFI_ALLOC_LIMIT);
if (status != EFI_SUCCESS) {
efi_err("Failed to allocate memory\n");
goto free_cmdline;
diff --git a/drivers/firmware/efi/riscv-runtime.c b/drivers/firmware/efi/riscv-runtime.c
index 09525fb5c240..01f0f90ea418 100644
--- a/drivers/firmware/efi/riscv-runtime.c
+++ b/drivers/firmware/efi/riscv-runtime.c
@@ -85,7 +85,7 @@ static int __init riscv_enable_runtime_services(void)
efi_memory_desc_t *md;
for_each_efi_memory_desc(md) {
- int md_size = md->num_pages << EFI_PAGE_SHIFT;
+ u64 md_size = md->num_pages << EFI_PAGE_SHIFT;
struct resource *res;
if (!(md->attribute & EFI_MEMORY_SP))
diff --git a/drivers/firmware/efi/sysfb_efi.c b/drivers/firmware/efi/sysfb_efi.c
index 456d0e5eaf78..cc807ed35aed 100644
--- a/drivers/firmware/efi/sysfb_efi.c
+++ b/drivers/firmware/efi/sysfb_efi.c
@@ -336,7 +336,7 @@ static int efifb_add_links(struct fwnode_handle *fwnode)
if (!sup_np)
return 0;
- fwnode_link_add(fwnode, of_fwnode_handle(sup_np));
+ fwnode_link_add(fwnode, of_fwnode_handle(sup_np), 0);
of_node_put(sup_np);
return 0;