Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make cbmem work and print TCPA log #197

Merged
6 changes: 6 additions & 0 deletions src/commonlib/include/commonlib/cbmem_id.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@
#define CBMEM_ID_STORAGE_DATA 0x53746f72
#define CBMEM_ID_TCPA_LOG 0x54435041
#define CBMEM_ID_TCPA_SPEC_LOG 0x54534C47
/*
* This is memory range for TCPA log according to specification without
* internal data. The range lies within CBMEM_ID_TCPA_SPEC_LOG entry.
*/
#define CBMEM_ID_TCPA_LOG_REF 0x544C5246
#define CBMEM_ID_TCPA_TCG_LOG 0x54445041
#define CBMEM_ID_TIMESTAMP 0x54494d45
#define CBMEM_ID_TPM2_TCG_LOG 0x54504d32
Expand Down Expand Up @@ -127,6 +132,7 @@
{ CBMEM_ID_STORAGE_DATA, "SD/MMC/eMMC" }, \
{ CBMEM_ID_TCPA_LOG, "TCPA LOG " }, \
{ CBMEM_ID_TCPA_SPEC_LOG, "TCPASPECLOG" }, \
{ CBMEM_ID_TCPA_LOG_REF, "TCPA LOGREF" }, \
{ CBMEM_ID_TCPA_TCG_LOG, "TCPA TCGLOG" }, \
{ CBMEM_ID_TIMESTAMP, "TIME STAMP " }, \
{ CBMEM_ID_TPM2_TCG_LOG, "TPM2 TCGLOG" }, \
Expand Down
24 changes: 23 additions & 1 deletion src/lib/coreboot_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <inttypes.h>
#include <spi_flash.h>
#include <smmstore.h>
#include <security/tpm/tspi.h>

#if CONFIG(USE_OPTION_TABLE)
#include <option_table.h>
Expand Down Expand Up @@ -249,7 +250,6 @@ static void add_cbmem_pointers(struct lb_header *header)
{CBMEM_ID_VPD, LB_TAG_VPD},
{CBMEM_ID_WIFI_CALIBRATION, LB_TAG_WIFI_CALIBRATION},
{CBMEM_ID_TCPA_LOG, LB_TAG_TCPA_LOG},
{CBMEM_ID_TCPA_SPEC_LOG, LB_TAG_TCPA_SPEC_LOG},
{CBMEM_ID_FMAP, LB_TAG_FMAP},
{CBMEM_ID_VBOOT_WORKBUF, LB_TAG_VBOOT_WORKBUF},
};
Expand All @@ -274,6 +274,25 @@ static void add_cbmem_pointers(struct lb_header *header)
}
}

static void lb_tpm_tcpa_log(struct lb_header *header)
{
struct lb_range *lb_range;
const struct tcpa_log_ref *range = cbmem_find(CBMEM_ID_TCPA_LOG_REF);

if (range == NULL)
return; /* The section is not present */

lb_range = (struct lb_range *)lb_new_record(header);
if (lb_range == NULL) {
printk(BIOS_ERR, "No more room in coreboot table!\n");
return;
}
lb_range->tag = LB_TAG_TCPA_SPEC_LOG;
lb_range->size = sizeof(*lb_range);
lb_range->range_start = range->start;
lb_range->range_size = range->size;
}

static struct lb_mainboard *lb_mainboard(struct lb_header *header)
{
struct lb_record *rec;
Expand Down Expand Up @@ -463,6 +482,9 @@ static uintptr_t write_coreboot_table(uintptr_t rom_table_end)
/* Serialize resource map into mem table types (LB_MEM_*) */
bootmem_write_memory_table(lb_memory(head));

/* Record reference to TCPA log composed according to specification */
lb_tpm_tcpa_log(head);

/* Record our motherboard */
lb_mainboard(head);

Expand Down
5 changes: 5 additions & 0 deletions src/security/tpm/tspi.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@
#define TPM_PCR_MAX_LEN 64
#define HASH_DATA_CHUNK_SIZE 1024

struct tcpa_log_ref {
uint64_t start;
uint32_t size;
};

/**
* Get the pointer to the single instance of global
* tcpa log data, and initialize it when necessary
Expand Down
7 changes: 7 additions & 0 deletions src/security/tpm/tspi/log-tpm.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ static struct tcpa_table *tcpa_cbmem_init(void)
MAX_TCPA_LOG_ENTRIES * sizeof(struct tcpa_entry);
tclt = cbmem_add(CBMEM_ID_TCPA_SPEC_LOG, tcpa_log_len);
if (tclt) {
struct tcpa_log_ref *tcpa_ref;

tclt->max_entries = MAX_TCPA_LOG_ENTRIES;
tclt->num_entries = 0;

Expand All @@ -52,6 +54,11 @@ static struct tcpa_table *tcpa_cbmem_init(void)
hdr->digest_sizes[0].digest_size = SHA1_DIGEST_SIZE;
hdr->digest_sizes[1].alg_id = TPM2_ALG_SHA256;
hdr->digest_sizes[1].digest_size = SHA256_DIGEST_SIZE;

tcpa_ref = cbmem_add(CBMEM_ID_TCPA_LOG_REF, sizeof(*tcpa_ref));
tcpa_ref->start = (uintptr_t)&tclt->header;
tcpa_ref->size = tcpa_log_len
- offsetof(struct tcpa_table, header);
}
}
}
Expand Down
119 changes: 76 additions & 43 deletions src/soc/ibm/power9/chip.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@
*/
#define CHIP_ID(chip) ((chip) << 3)

struct mem_map {
struct memranges mem;
struct memranges reserved;
};

/* Copy of data put together by the romstage */
mcbist_data_t mem_data[MAX_CHIPS];

Expand Down Expand Up @@ -275,14 +280,15 @@ static void fill_cpu_node(struct device_tree *tree,
dt_add_u32_prop(node, "tlb-sets", 4);
}

static void add_memory_node(struct device_tree *tree, uint8_t chip, uint64_t reg)
static void add_memory_node(struct device_tree *tree, uint8_t chip, uint64_t start,
uint64_t len)
{
struct device_tree_node *node;
/* /memory@0123456789abcdef - 24 characters + null byte */
char path[26] = {};

union {uint32_t u32[2]; uint64_t u64;} addr = { .u64 = base_k(reg) * KiB };
union {uint32_t u32[2]; uint64_t u64;} size = { .u64 = size_k(reg) * KiB };
union {uint32_t u32[2]; uint64_t u64;} addr = { .u64 = start };
union {uint32_t u32[2]; uint64_t u64;} size = { .u64 = len };

snprintf(path, sizeof(path), "/memory@%llx", addr.u64);
node = dt_find_node_by_path(tree, path, NULL, NULL, 1);
Expand All @@ -295,54 +301,83 @@ static void add_memory_node(struct device_tree *tree, uint8_t chip, uint64_t reg
dt_add_u32_prop(node, "ibm,chip-id", chip << 3);
}

static bool add_mem_reserve_node(const struct range_entry *r, void *arg)
static bool build_memory_map(const struct range_entry *r, void *arg)
{
struct device_tree *tree = arg;
struct mem_map *map = arg;

if (range_entry_tag(r) != BM_MEM_RAM) {
struct device_tree_reserve_map_entry *entry = xzalloc(sizeof(*entry));
entry->start = range_entry_base(r);
entry->size = range_entry_size(r);
/*
* Kernel likes its available memory areas at least 1MB
* aligned, let's trim the regions such that unaligned padding
* is added to reserved memory.
*/
if (range_entry_tag(r) == BM_MEM_RAM) {
uint64_t new_start = ALIGN_UP(range_entry_base(r), 1 * MiB);
uint64_t new_end = ALIGN_DOWN(range_entry_end(r), 1 * MiB);

list_insert_after(&entry->list_node, &tree->reserve_map);
if (new_start != range_entry_base(r))
memranges_insert(&map->reserved, range_entry_base(r),
new_start - range_entry_base(r), BM_MEM_RESERVED);

if (new_start != new_end)
memranges_insert(&map->mem, new_start, new_end - new_start, BM_MEM_RAM);

if (new_end != range_entry_end(r))
memranges_insert(&map->reserved, new_end, range_entry_end(r) - new_end,
BM_MEM_RESERVED);
} else {
memranges_insert(&map->reserved, range_entry_base(r), range_entry_size(r),
BM_MEM_RESERVED);
}

return true;
}

static void add_reserved_memory_node(struct device_tree *tree, uint64_t start, uint64_t size)
{
struct device_tree_node *node;
char path[45];

snprintf(path, sizeof(path), "/reserved-memory/coreboot@%llx", start);
node = dt_find_node_by_path(tree, path, NULL, NULL, 1);
/* Use 2 cells each for address and size */
dt_add_reg_prop(node, &start, &size, 1, 2, 2);
}

static void add_memory_nodes(struct device_tree *tree)
{
uint8_t chip;
uint8_t chips = fsi_get_present_chips();
struct mem_map map;
const struct range_entry *r;

/*
* Not using bootmem_walk_os_mem() to be consistent with Hostboot,
* whose "memory" nodes include reserved regions.
*/
for (chip = 0; chip < MAX_CHIPS; chip++) {
int mcs_i;
memranges_init_empty(&map.mem, NULL, 0);
memranges_init_empty(&map.reserved, NULL, 0);

if (!(chips & (1 << chip)))
continue;
bootmem_walk_os_mem(build_memory_map, &map);

for (mcs_i = 0; mcs_i < MCS_PER_PROC; mcs_i++) {
uint64_t reg;
chiplet_id_t nest = mcs_to_nest[mcs_ids[mcs_i]];
memranges_each_entry(r, &map.mem) {
/*
* This is for ATTR_PROC_FABRIC_PUMP_MODE == PUMP_MODE_CHIP_IS_GROUP,
* when chip ID is actually a group ID and "chip ID" field is zero.
*/
uint8_t chip = (range_entry_base(r) >> 45) & 0xF;

/* These registers are undocumented, see istep 14.5. */
/* MCS_MCFGP */
reg = read_scom_for_chiplet(chip, nest, 0x0501080A);
if (reg & PPC_BIT(0))
add_memory_node(tree, chip, reg);
add_memory_node(tree, chip, range_entry_base(r), range_entry_size(r));
}

/* MCS_MCFGPM */
reg = read_scom_for_chiplet(chip, nest, 0x0501080C);
if (reg & PPC_BIT(0))
add_memory_node(tree, chip, reg);
}
/* Createe properly initialized /reserved-memory/ node */
(void)dt_init_reserved_memory_node(tree);

memranges_each_entry(r, &map.reserved) {
struct device_tree_reserve_map_entry *entry = xzalloc(sizeof(*entry));
entry->start = range_entry_base(r);
entry->size = range_entry_size(r);

add_reserved_memory_node(tree, entry->start, entry->size);

list_insert_after(&entry->list_node, &tree->reserve_map);
}

bootmem_walk_os_mem(add_mem_reserve_node, tree);
memranges_teardown(&map.mem);
memranges_teardown(&map.reserved);
}

/* Finds first root complex for a given chip that's present in DT else returns NULL */
Expand Down Expand Up @@ -502,7 +537,11 @@ static void add_tpm_node(struct device_tree *tree)
char path[64];
char compatible[24];

struct tcpa_table *tcpa_table;
const struct tcpa_log_ref *tcpa_ref;

tcpa_ref = cbmem_find(CBMEM_ID_TCPA_LOG_REF);
if (tcpa_ref == NULL)
die("TPM event log (TCPA) is missing from CBMEM!");

/* TODO: is the XSCOM address always the same? */
snprintf(path, sizeof(path), "/xscom@603fc00000000/i2cm@%x/i2c-bus@%x/tpm@%x",
Expand All @@ -515,14 +554,8 @@ static void add_tpm_node(struct device_tree *tree)
dt_add_string_prop(tpm, "compatible", strdup(compatible));
dt_add_u32_prop(tpm, "reg", addr);

tcpa_table = cbmem_find(CBMEM_ID_TCPA_SPEC_LOG);
if (tcpa_table == NULL)
die("TPM events (TCPA) log is missing from CBMEM!");

dt_add_u64_prop(tpm, "linux,sml-base", (uintptr_t)&tcpa_table->header);
dt_add_u32_prop(tpm, "linux,sml-size",
sizeof(tcg_efi_spec_id_event) +
tcpa_table->max_entries * sizeof(struct tcpa_entry));
dt_add_u64_prop(tpm, "ibm,sml-base", tcpa_ref->start);
dt_add_u32_prop(tpm, "ibm,sml-size", tcpa_ref->size);

/* Not hard-coding into DTS-file in case will need to store key hash here */
sb = dt_find_node_by_path(tree, "/ibm,secureboot", NULL, NULL, 1);
Expand Down
Loading