Merge changes from topic "paulliu-imx8m-eventlog" into integration

* changes:
  docs(imx8m): update for measured boot for imx8mm
  feat(plat/imx/imx8m/imx8mm): add support for measured boot
This commit is contained in:
Madhukar Pappireddy 2022-02-21 16:41:38 +01:00 committed by TrustedFirmware Code Review
commit 1776d4091b
6 changed files with 329 additions and 1 deletions

View file

@ -60,3 +60,11 @@ BL2 will be in the FIT image and SPL will verify it.
All of the BL3x will be put in the FIP image. BL2 will verify them. All of the BL3x will be put in the FIP image. BL2 will verify them.
In U-boot we turn on the UEFI secure boot features so it can verify In U-boot we turn on the UEFI secure boot features so it can verify
grub. And we use grub to verify linux kernel. grub. And we use grub to verify linux kernel.
Measured Boot
-------------
When setting MEASURED_BOOT=1 on imx8mm we can let TF-A generate event logs
with a DTB overlay. The overlay will be put at PLAT_IMX8M_DTO_BASE with
maximum size PLAT_IMX8M_DTO_MAX_SIZE. Then in U-boot we can apply the DTB
overlay and let U-boot to parse the event log and update the PCRs.

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_HANDLES 3U
#define MAX_IO_DEVICES 2U #define MAX_IO_DEVICES 2U
#define MAX_IO_BLOCK_DEVICES 1U #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/include \
-Iplat/imx/imx8m/imx8mm/include \ -Iplat/imx/imx8m/imx8mm/include \
-Idrivers/imx/usdhc \ -Idrivers/imx/usdhc \
-Iinclude/common/tbbr -Iinclude/common/tbbr \
-Iinclude/lib/libfdt
# Include GICv3 driver files # Include GICv3 driver files
include drivers/arm/gic/v3/gicv3.mk include drivers/arm/gic/v3/gicv3.mk
include lib/libfdt/libfdt.mk
IMX_GIC_SOURCES := ${GICV3_SOURCES} \ IMX_GIC_SOURCES := ${GICV3_SOURCES} \
plat/common/plat_gicv3.c \ plat/common/plat_gicv3.c \
plat/common/plat_psci_common.c \ plat/common/plat_psci_common.c \
@ -43,6 +46,7 @@ BL31_SOURCES += plat/imx/common/imx8_helpers.S \
ifeq (${NEED_BL2},yes) ifeq (${NEED_BL2},yes)
BL2_SOURCES += common/desc_image_load.c \ BL2_SOURCES += common/desc_image_load.c \
common/fdt_wrappers.c \
plat/imx/common/imx8_helpers.S \ plat/imx/common/imx8_helpers.S \
plat/imx/common/imx_uart_console.S \ plat/imx/common/imx_uart_console.S \
plat/imx/imx8m/imx8mm/imx8mm_bl2_el3_setup.c \ 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 EL3_EXCEPTION_HANDLING := 1
SDEI_SUPPORT := 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 */