feat(plat/imx/imx8m/imx8mm): add support for measured boot

Add helper functions to generate event log for imx8mm
when MEASURED_BOOT=1.

Signed-off-by: Ying-Chun Liu (PaulLiu) <paulliu@debian.org>
Change-Id: Ifc947d749055787fbda0b39170aa2eb8865b7802
This commit is contained in:
Ying-Chun Liu (PaulLiu) 2021-10-06 09:27:00 +08:00
parent b22f18e365
commit cb2c4f93c1
5 changed files with 321 additions and 1 deletions

View File

@ -0,0 +1,200 @@
/*
* Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2022, Linaro.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <arch_helpers.h>
#if MEASURED_BOOT
#include <common/desc_image_load.h>
#endif
#include <common/fdt_wrappers.h>
#include <libfdt.h>
#define DTB_PROP_HW_LOG_ADDR "tpm_event_log_addr"
#define DTB_PROP_HW_LOG_SIZE "tpm_event_log_size"
#if MEASURED_BOOT
static int imx8m_event_log_fdt_init_overlay(uintptr_t dt_base, int dt_size)
{
int ret;
int offset;
void *dtb = (void *)dt_base;
ret = fdt_create_empty_tree(dtb, dt_size);
if (ret < 0) {
ERROR("cannot create empty dtb tree: %s\n",
fdt_strerror(ret));
return ret;
}
offset = fdt_path_offset(dtb, "/");
if (offset < 0) {
ERROR("cannot find root of the tree: %s\n",
fdt_strerror(offset));
return offset;
}
offset = fdt_add_subnode(dtb, offset, "fragment@0");
if (offset < 0) {
ERROR("cannot add fragment node: %s\n",
fdt_strerror(offset));
return offset;
}
ret = fdt_setprop_string(dtb, offset, "target-path", "/");
if (ret < 0) {
ERROR("cannot set target-path property: %s\n",
fdt_strerror(ret));
return ret;
}
offset = fdt_add_subnode(dtb, offset, "__overlay__");
if (offset < 0) {
ERROR("cannot add __overlay__ node: %s\n",
fdt_strerror(offset));
return ret;
}
offset = fdt_add_subnode(dtb, offset, "tpm_event_log");
if (offset < 0) {
ERROR("cannot add tpm_event_log node: %s\n",
fdt_strerror(offset));
return offset;
}
ret = fdt_setprop_string(dtb, offset, "compatible",
"arm,tpm_event_log");
if (ret < 0) {
ERROR("cannot set compatible property: %s\n",
fdt_strerror(ret));
return ret;
}
ret = fdt_setprop_u64(dtb, offset, "tpm_event_log_addr", 0);
if (ret < 0) {
ERROR("cannot set tpm_event_log_addr property: %s\n",
fdt_strerror(ret));
return ret;
}
ret = fdt_setprop_u32(dtb, offset, "tpm_event_log_size", 0);
if (ret < 0) {
ERROR("cannot set tpm_event_log_size property: %s\n",
fdt_strerror(ret));
return ret;
}
return ret;
}
/*
* Write the Event Log address and its size in the DTB.
*
* This function is supposed to be called only by BL2.
*
* Returns:
* 0 = success
* < 0 = error
*/
static int imx8m_set_event_log_info(uintptr_t config_base,
uintptr_t log_addr, size_t log_size)
{
/* As libfdt uses void *, we can't avoid this cast */
void *dtb = (void *)config_base;
const char *compatible_tpm = "arm,tpm_event_log";
uint64_t base = cpu_to_fdt64(log_addr);
uint32_t sz = cpu_to_fdt32(log_size);
int err, node;
err = fdt_open_into(dtb, dtb, PLAT_IMX8M_DTO_MAX_SIZE);
if (err < 0) {
ERROR("Invalid Device Tree at %p: error %d\n", dtb, err);
return err;
}
/*
* Verify that the DTB is valid, before attempting to write to it,
* and get the DTB root node.
*/
/* Check if the pointer to DT is correct */
err = fdt_check_header(dtb);
if (err < 0) {
WARN("Invalid DTB file passed\n");
return err;
}
/*
* Find the TPM node in device tree.
*/
node = fdt_node_offset_by_compatible(dtb, -1, compatible_tpm);
if (node < 0) {
ERROR("The compatible property '%s' not%s", compatible_tpm,
" found in the config\n");
return node;
}
err = fdt_setprop(dtb, node, DTB_PROP_HW_LOG_ADDR, &base, 8);
if (err < 0) {
ERROR("Failed to add log addr err %d\n", err);
return err;
}
err = fdt_setprop(dtb, node, DTB_PROP_HW_LOG_SIZE, &sz, 4);
if (err < 0) {
ERROR("Failed to add log addr err %d\n", err);
return err;
}
err = fdt_pack(dtb);
if (err < 0) {
ERROR("Failed to pack Device Tree at %p: error %d\n", dtb, err);
return err;
}
/*
* Ensure that the info written to the DTB is visible
* to other images.
*/
flush_dcache_range(config_base, fdt_totalsize(dtb));
return err;
}
/*
* This function writes the Event Log address and its size
* in the QEMU DTB.
*
* This function is supposed to be called only by BL2.
*
* Returns:
* 0 = success
* < 0 = error
*/
int imx8m_set_nt_fw_info(size_t log_size, uintptr_t *ns_log_addr)
{
uintptr_t ns_addr;
int err;
assert(ns_log_addr != NULL);
ns_addr = PLAT_IMX8M_DTO_BASE + PLAT_IMX8M_DTO_MAX_SIZE;
imx8m_event_log_fdt_init_overlay(PLAT_IMX8M_DTO_BASE,
PLAT_IMX8M_DTO_MAX_SIZE);
/* Write the Event Log address and its size in the DTB */
err = imx8m_set_event_log_info(PLAT_IMX8M_DTO_BASE,
ns_addr, log_size);
/* Return Event Log address in Non-secure memory */
*ns_log_addr = (err < 0) ? 0UL : ns_addr;
return err;
}
#endif /* MEASURED_BOOT */

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2022, Arm Limited. All rights reserved.
* Copyright (c) 2022, Linaro.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <string.h>
#include "./include/imx8m_measured_boot.h"
#include <drivers/measured_boot/event_log/event_log.h>
#include <plat/arm/common/plat_arm.h>
/* Event Log data */
static uint8_t event_log[PLAT_IMX_EVENT_LOG_MAX_SIZE];
/* FVP table with platform specific image IDs, names and PCRs */
static const event_log_metadata_t imx8m_event_log_metadata[] = {
{ BL31_IMAGE_ID, EVLOG_BL31_STRING, PCR_0 },
{ BL32_IMAGE_ID, EVLOG_BL32_STRING, PCR_0 },
{ BL32_EXTRA1_IMAGE_ID, EVLOG_BL32_EXTRA1_STRING, PCR_0 },
{ BL32_EXTRA2_IMAGE_ID, EVLOG_BL32_EXTRA2_STRING, PCR_0 },
{ BL33_IMAGE_ID, EVLOG_BL33_STRING, PCR_0 },
{ EVLOG_INVALID_ID, NULL, (unsigned int)(-1) } /* Terminator */
};
const event_log_metadata_t *plat_event_log_get_metadata(void)
{
return imx8m_event_log_metadata;
}
int plat_mboot_measure_image(unsigned int image_id, image_info_t *image_data)
{
/* Calculate image hash and record data in Event Log */
int err = event_log_measure_and_record(image_data->image_base,
image_data->image_size,
image_id);
if (err != 0) {
ERROR("%s%s image id %u (%i)\n",
"Failed to ", "record", image_id, err);
return err;
}
return 0;
}
void bl2_plat_mboot_init(void)
{
event_log_init(event_log, event_log + sizeof(event_log));
event_log_write_header();
}
void bl2_plat_mboot_finish(void)
{
int rc = 0;
/* Event Log address in Non-Secure memory */
uintptr_t ns_log_addr;
/* Event Log filled size */
size_t event_log_cur_size;
event_log_cur_size = event_log_get_cur_size(event_log);
rc = imx8m_set_nt_fw_info(event_log_cur_size, &ns_log_addr);
if (rc != 0) {
ERROR("%s(): Unable to update %s_FW_CONFIG\n",
__func__, "NT");
/*
* It is a fatal error because on i.MX U-boot assumes that
* a valid event log exists and will use it to record the
* measurements into the fTPM.
*/
panic();
}
/* Copy Event Log to Non-secure memory */
(void)memcpy((void *)ns_log_addr, (const void *)event_log,
event_log_cur_size);
/* Ensure that the Event Log is visible in Non-secure memory */
flush_dcache_range(ns_log_addr, event_log_cur_size);
dump_event_log((uint8_t *)event_log, event_log_cur_size);
}

View File

@ -152,3 +152,7 @@
#define MAX_IO_HANDLES 3U
#define MAX_IO_DEVICES 2U
#define MAX_IO_BLOCK_DEVICES 1U
#define PLAT_IMX8M_DTO_BASE 0x53000000
#define PLAT_IMX8M_DTO_MAX_SIZE 0x1000
#define PLAT_IMX_EVENT_LOG_MAX_SIZE UL(0x400)

View File

@ -8,11 +8,14 @@ PLAT_INCLUDES := -Iplat/imx/common/include \
-Iplat/imx/imx8m/include \
-Iplat/imx/imx8m/imx8mm/include \
-Idrivers/imx/usdhc \
-Iinclude/common/tbbr
-Iinclude/common/tbbr \
-Iinclude/lib/libfdt
# Include GICv3 driver files
include drivers/arm/gic/v3/gicv3.mk
include lib/libfdt/libfdt.mk
IMX_GIC_SOURCES := ${GICV3_SOURCES} \
plat/common/plat_gicv3.c \
plat/common/plat_psci_common.c \
@ -43,6 +46,7 @@ BL31_SOURCES += plat/imx/common/imx8_helpers.S \
ifeq (${NEED_BL2},yes)
BL2_SOURCES += common/desc_image_load.c \
common/fdt_wrappers.c \
plat/imx/common/imx8_helpers.S \
plat/imx/common/imx_uart_console.S \
plat/imx/imx8m/imx8mm/imx8mm_bl2_el3_setup.c \
@ -148,3 +152,14 @@ $(eval $(call add_define,IMX_BOOT_UART_BASE))
EL3_EXCEPTION_HANDLING := 1
SDEI_SUPPORT := 1
ifeq (${MEASURED_BOOT},1)
MEASURED_BOOT_MK := drivers/measured_boot/event_log/event_log.mk
$(info Including ${MEASURED_BOOT_MK})
include ${MEASURED_BOOT_MK}
BL2_SOURCES += plat/imx/imx8m/imx8m_measured_boot.c \
plat/imx/imx8m/imx8m_dyn_cfg_helpers.c \
${EVENT_LOG_SOURCES}
endif

View File

@ -0,0 +1,16 @@
/*
* Copyright (c) 2022, Linaro
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef IMX8M_MEASURED_BOOT_H
#define IMX8M_MEASURED_BOOT_H
#include <stdint.h>
#include <arch_helpers.h>
int imx8m_set_nt_fw_info(size_t log_size, uintptr_t *ns_log_addr);
#endif /* IMX8M_MEASURED_BOOT_H */