Revert "util/cbmem: Consolidate CBMEM and coreboot table access"
This reverts commit c24a12db86.
Reason for revert: can't assume uint64_t or uintptr_t is a long. use proper printf modifiers instead.
```
cbmem.c:417:28: error: format specifies type 'unsigned long' but the argument
has type 'uint64_t' (aka 'unsigned long long') [-Werror,-Wformat]
417 | debug("Found at %#lx\n", address + i);
| ~~~~ ^~~~~~~~~~~
| %#llx
cbmem.c:50:40: note: expanded from macro 'debug'
50 | #define debug(x...) if(verbose) printf(x)
| ^
cbmem.c:1321:21: error: format specifies type 'unsigned long' but the argument
has type 'uintptr_t' (aka 'unsigned int') [-Werror,-Wformat]
1321 | printf("%08lx:", start_address + i);
| ~~~~~ ^~~~~~~~~~~~~~~~~
| %08x
2 errors generated.
make: *** [<builtin>: cbmem.o] Error 1
```
Signed-off-by: Jon Murphy <jpmurphy@google.com>
Change-Id: I6e074b0c6c8247f85cd69d64c0e8584c5826e35a
Reviewed-on: https://review.coreboot.org/c/coreboot/+/88016
Reviewed-by: Subrata Banik <subratabanik@google.com>
Reviewed-by: Matt DeVillier <matt.devillier@gmail.com>
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Reviewed-by: Jakub "Kuba" Czapiga <czapiga@google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
parent
30865c2fb1
commit
712dfb3761
1 changed files with 318 additions and 341 deletions
|
|
@ -35,6 +35,9 @@
|
|||
#include <x86intrin.h>
|
||||
#endif
|
||||
|
||||
/* Return < 0 on error, 0 on success. */
|
||||
static int parse_cbtable(uint64_t address, size_t table_size);
|
||||
|
||||
struct mapping {
|
||||
void *virt;
|
||||
size_t offset;
|
||||
|
|
@ -53,6 +56,9 @@ static int verbose = 0;
|
|||
static int mem_fd;
|
||||
static struct mapping lbtable_mapping;
|
||||
|
||||
/* TSC frequency from the LB_TAG_TSC_INFO record. 0 if not present. */
|
||||
static uint32_t tsc_freq_khz = 0;
|
||||
|
||||
static void die(const char *msg)
|
||||
{
|
||||
if (msg)
|
||||
|
|
@ -189,6 +195,57 @@ static void *aligned_memcpy(void *dest, const void *src, size_t n)
|
|||
return dest;
|
||||
}
|
||||
|
||||
/* Find the first cbmem entry filling in the details. */
|
||||
static int find_cbmem_entry(uint32_t id, uint64_t *addr, size_t *size)
|
||||
{
|
||||
const uint8_t *table;
|
||||
size_t offset;
|
||||
int ret = -1;
|
||||
|
||||
table = mapping_virt(&lbtable_mapping);
|
||||
|
||||
if (table == NULL)
|
||||
return -1;
|
||||
|
||||
offset = 0;
|
||||
|
||||
while (offset < mapping_size(&lbtable_mapping)) {
|
||||
const struct lb_record *lbr;
|
||||
struct lb_cbmem_entry lbe;
|
||||
|
||||
lbr = (const void *)(table + offset);
|
||||
offset += lbr->size;
|
||||
|
||||
if (lbr->tag != LB_TAG_CBMEM_ENTRY)
|
||||
continue;
|
||||
|
||||
aligned_memcpy(&lbe, lbr, sizeof(lbe));
|
||||
if (lbe.id != id)
|
||||
continue;
|
||||
|
||||
*addr = lbe.address;
|
||||
*size = lbe.entry_size;
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try finding the timestamp table and coreboot cbmem console starting from the
|
||||
* passed in memory offset. Could be called recursively in case a forwarding
|
||||
* entry is found.
|
||||
*
|
||||
* Returns pointer to a memory buffer containing the timestamp table or zero if
|
||||
* none found.
|
||||
*/
|
||||
|
||||
static struct lb_cbmem_ref timestamps;
|
||||
static struct lb_cbmem_ref console;
|
||||
static struct lb_cbmem_ref tpm_cb_log;
|
||||
static struct lb_memory_range cbmem;
|
||||
|
||||
/* This is a work-around for a nasty problem introduced by initially having
|
||||
* pointer sized entries in the lb_cbmem_ref structures. This caused problems
|
||||
* on 64bit x86 systems because coreboot is 32bit on those systems.
|
||||
|
|
@ -210,168 +267,90 @@ static struct lb_cbmem_ref parse_cbmem_ref(const struct lb_cbmem_ref *cbmem_ref)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t cbmem_id_to_lb_tag(uint32_t tag)
|
||||
static void parse_memory_tags(const struct lb_memory *mem)
|
||||
{
|
||||
/* Minimal subset. Expand based on the CBMEM to coreboot table
|
||||
records mapping in lib/coreboot_table.c */
|
||||
switch (tag) {
|
||||
case CBMEM_ID_TIMESTAMP:
|
||||
return LB_TAG_TIMESTAMPS;
|
||||
case CBMEM_ID_CONSOLE:
|
||||
return LB_TAG_CBMEM_CONSOLE;
|
||||
case CBMEM_ID_TPM_CB_LOG:
|
||||
return LB_TAG_TPM_CB_LOG;
|
||||
int num_entries;
|
||||
int i;
|
||||
|
||||
/* Peel off the header size and calculate the number of entries. */
|
||||
num_entries = (mem->size - sizeof(*mem)) / sizeof(mem->map[0]);
|
||||
|
||||
for (i = 0; i < num_entries; i++) {
|
||||
if (mem->map[i].type != LB_MEM_TABLE)
|
||||
continue;
|
||||
debug(" LB_MEM_TABLE found.\n");
|
||||
/* The last one found is CBMEM */
|
||||
aligned_memcpy(&cbmem, &mem->map[i], sizeof(cbmem));
|
||||
}
|
||||
return LB_TAG_UNUSED;
|
||||
}
|
||||
|
||||
struct cbmem_console {
|
||||
uint32_t size;
|
||||
uint32_t cursor;
|
||||
uint8_t body[];
|
||||
} __packed;
|
||||
|
||||
#define CBMC_CURSOR_MASK ((1 << 28) - 1)
|
||||
#define CBMC_OVERFLOW (1 << 31)
|
||||
|
||||
|
||||
/* Find the first cbmem entry filling in the details. */
|
||||
static int find_cbmem_entry(uint32_t id, uint64_t *addr, size_t *size)
|
||||
/* Return < 0 on error, 0 on success, 1 if forwarding table entry found. */
|
||||
static int parse_cbtable_entries(const struct mapping *table_mapping)
|
||||
{
|
||||
const uint8_t *table;
|
||||
size_t offset = 0;
|
||||
const uint32_t legacy_tag = cbmem_id_to_lb_tag(id);
|
||||
struct lb_cbmem_ref *ref = NULL;
|
||||
size_t i;
|
||||
const struct lb_record *lbr_p;
|
||||
size_t table_size = mapping_size(table_mapping);
|
||||
const void *lbtable = mapping_virt(table_mapping);
|
||||
int forwarding_table_found = 0;
|
||||
|
||||
table = mapping_virt(&lbtable_mapping);
|
||||
|
||||
if (table == NULL)
|
||||
return -1;
|
||||
|
||||
const struct lb_record *lbr = NULL;
|
||||
while (offset < mapping_size(&lbtable_mapping)) {
|
||||
lbr = (const void *)(table + offset);
|
||||
offset += lbr->size;
|
||||
|
||||
/* Store coreboot table entry for later if CBMEM entry does not exist.
|
||||
CBMEM entry stores size including the reserved area, so prefer it,
|
||||
so more potential data and/or space is available. */
|
||||
if (legacy_tag != LB_TAG_UNUSED && lbr->tag == legacy_tag)
|
||||
ref = (struct lb_cbmem_ref *)lbr;
|
||||
|
||||
if (lbr->tag != LB_TAG_CBMEM_ENTRY)
|
||||
for (i = 0; i < table_size; i += lbr_p->size) {
|
||||
lbr_p = lbtable + i;
|
||||
debug(" coreboot table entry 0x%02x\n", lbr_p->tag);
|
||||
switch (lbr_p->tag) {
|
||||
case LB_TAG_MEMORY:
|
||||
debug(" Found memory map.\n");
|
||||
parse_memory_tags(lbtable + i);
|
||||
continue;
|
||||
|
||||
struct lb_cbmem_entry lbe;
|
||||
aligned_memcpy(&lbe, lbr, sizeof(lbe));
|
||||
if (lbe.id != id)
|
||||
case LB_TAG_TIMESTAMPS: {
|
||||
debug(" Found timestamp table.\n");
|
||||
timestamps =
|
||||
parse_cbmem_ref((struct lb_cbmem_ref *)lbr_p);
|
||||
continue;
|
||||
}
|
||||
case LB_TAG_CBMEM_CONSOLE: {
|
||||
debug(" Found cbmem console.\n");
|
||||
console = parse_cbmem_ref((struct lb_cbmem_ref *)lbr_p);
|
||||
continue;
|
||||
}
|
||||
case LB_TAG_TPM_CB_LOG: {
|
||||
debug(" Found TPM CB log table.\n");
|
||||
tpm_cb_log =
|
||||
parse_cbmem_ref((struct lb_cbmem_ref *)lbr_p);
|
||||
continue;
|
||||
}
|
||||
case LB_TAG_TSC_INFO:
|
||||
debug(" Found TSC info.\n");
|
||||
tsc_freq_khz = ((struct lb_tsc_info *)lbr_p)->freq_khz;
|
||||
continue;
|
||||
case LB_TAG_FORWARD: {
|
||||
int ret;
|
||||
/*
|
||||
* This is a forwarding entry - repeat the
|
||||
* search at the new address.
|
||||
*/
|
||||
struct lb_forward lbf_p =
|
||||
*(const struct lb_forward *)lbr_p;
|
||||
debug(" Found forwarding entry.\n");
|
||||
ret = parse_cbtable(lbf_p.forward, 0);
|
||||
|
||||
*addr = lbe.address;
|
||||
*size = lbe.entry_size;
|
||||
return 0;
|
||||
/* Assume the forwarding entry is valid. If this fails
|
||||
* then there's a total failure. */
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
forwarding_table_found = 1;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* No mapping and/or no potential reference means that
|
||||
the requested entry does not exit. */
|
||||
if (legacy_tag == LB_TAG_UNUSED || ref == NULL)
|
||||
return -1;
|
||||
|
||||
debug("Found coreboot table record equivalent of CBMEM entry id: %#x, tag: %#x\n", id,
|
||||
legacy_tag);
|
||||
|
||||
const struct lb_cbmem_ref lbc = parse_cbmem_ref(ref);
|
||||
size_t header_map_size = 0;
|
||||
|
||||
/* Process legacy coreboot table entries */
|
||||
switch (lbc.tag) {
|
||||
case LB_TAG_TIMESTAMPS:
|
||||
header_map_size = sizeof(struct timestamp_table);
|
||||
break;
|
||||
case LB_TAG_CBMEM_CONSOLE:
|
||||
header_map_size = sizeof(struct cbmem_console);
|
||||
break;
|
||||
case LB_TAG_TPM_CB_LOG:
|
||||
header_map_size = sizeof(struct tpm_cb_log_table);
|
||||
break;
|
||||
}
|
||||
|
||||
struct mapping entry_mapping;
|
||||
const void *entry_header = NULL;
|
||||
|
||||
entry_header = map_memory(&entry_mapping, lbc.cbmem_addr, header_map_size);
|
||||
if (!entry_header) {
|
||||
fprintf(stderr, "Unable to map header for coreboot table entry id: %#x\n",
|
||||
legacy_tag);
|
||||
abort();
|
||||
}
|
||||
|
||||
*addr = lbc.cbmem_addr;
|
||||
|
||||
switch (legacy_tag) {
|
||||
case LB_TAG_TIMESTAMPS: {
|
||||
const struct timestamp_table *tst_p = entry_header;
|
||||
*size = sizeof(*tst_p) + tst_p->num_entries * sizeof(tst_p->entries[0]);
|
||||
break;
|
||||
}
|
||||
case LB_TAG_CBMEM_CONSOLE: {
|
||||
const struct cbmem_console *console_p = entry_header;
|
||||
*size = sizeof(*console_p) + console_p->size;
|
||||
break;
|
||||
}
|
||||
case LB_TAG_TPM_CB_LOG: {
|
||||
const struct tpm_cb_log_table *tclt_p = entry_header;
|
||||
*size = sizeof(*tclt_p) + tclt_p->num_entries * sizeof(tclt_p->entries[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unmap_memory(&entry_mapping);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns pointer to allocated buffer and size of the buffer in parameters.
|
||||
* Returns zero on success.
|
||||
* free() buffer after use.
|
||||
*/
|
||||
static int get_cbmem_entry(uint32_t id, uint8_t **buf_out, size_t *size_out)
|
||||
{
|
||||
uint64_t addr;
|
||||
size_t size;
|
||||
struct mapping cbmem_mapping;
|
||||
|
||||
if (find_cbmem_entry(id, &addr, &size)) {
|
||||
debug("CBMEM entry not found. CBMEM id: %#x\n", id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
const uint8_t *buf = map_memory(&cbmem_mapping, addr, size);
|
||||
if (!buf) {
|
||||
fprintf(stderr, "Unable to map CBMEM entry id: %#x, size: %zu\n", id, size);
|
||||
abort();
|
||||
}
|
||||
|
||||
*buf_out = malloc(size);
|
||||
if (!*buf_out) {
|
||||
unmap_memory(&cbmem_mapping);
|
||||
fprintf(stderr,
|
||||
"Unable to allocate memory for CBMEM entry id: %#x, size: %zu\n", id,
|
||||
size);
|
||||
abort();
|
||||
}
|
||||
|
||||
aligned_memcpy(*buf_out, buf, size);
|
||||
unmap_memory(&cbmem_mapping);
|
||||
*size_out = size;
|
||||
return 0;
|
||||
return forwarding_table_found;
|
||||
}
|
||||
|
||||
/* Return < 0 on error, 0 on success. */
|
||||
static int parse_cbtable(uint64_t address, size_t table_size)
|
||||
{
|
||||
const uint8_t *buf;
|
||||
const void *buf;
|
||||
struct mapping header_mapping;
|
||||
size_t req_size;
|
||||
size_t i;
|
||||
|
|
@ -381,7 +360,8 @@ static int parse_cbtable(uint64_t address, size_t table_size)
|
|||
if (req_size == 0)
|
||||
req_size = 4 * 1024;
|
||||
|
||||
debug("Looking for coreboot table at %" PRIx64 " %zd bytes.\n", address, req_size);
|
||||
debug("Looking for coreboot table at %" PRIx64 " %zd bytes.\n",
|
||||
address, req_size);
|
||||
|
||||
buf = map_memory(&header_mapping, address, req_size);
|
||||
|
||||
|
|
@ -390,10 +370,11 @@ static int parse_cbtable(uint64_t address, size_t table_size)
|
|||
|
||||
/* look at every 16 bytes */
|
||||
for (i = 0; i <= req_size - sizeof(struct lb_header); i += 16) {
|
||||
int ret;
|
||||
const struct lb_header *lbh;
|
||||
struct mapping table_mapping;
|
||||
|
||||
lbh = (const struct lb_header *)&buf[i];
|
||||
lbh = buf + i;
|
||||
if (memcmp(lbh->signature, "LBIO", sizeof(lbh->signature)) ||
|
||||
!lbh->header_bytes ||
|
||||
ipchksum(lbh, sizeof(*lbh))) {
|
||||
|
|
@ -414,32 +395,27 @@ static int parse_cbtable(uint64_t address, size_t table_size)
|
|||
continue;
|
||||
}
|
||||
|
||||
debug("Found at %#lx\n", address + i);
|
||||
debug("Found!\n");
|
||||
|
||||
const struct lb_record *lbr_p;
|
||||
const uint8_t *lbtable = mapping_virt(&table_mapping);
|
||||
ret = parse_cbtable_entries(&table_mapping);
|
||||
|
||||
for (size_t offset = 0; offset < lbh->table_bytes; offset += lbr_p->size) {
|
||||
lbr_p = (const struct lb_record *)&lbtable[offset];
|
||||
debug(" coreboot table entry 0x%02x\n", lbr_p->tag);
|
||||
|
||||
if (lbr_p->tag != LB_TAG_FORWARD)
|
||||
continue;
|
||||
|
||||
/* This is a forwarding entry. Repeat the search at the new address. */
|
||||
struct lb_forward lbf_p = *(const struct lb_forward *)lbr_p;
|
||||
debug(" Found forwarding entry.\n");
|
||||
|
||||
const uint64_t next_addr = lbf_p.forward;
|
||||
unmap_memory(&header_mapping);
|
||||
/* Table parsing failed. */
|
||||
if (ret < 0) {
|
||||
unmap_memory(&table_mapping);
|
||||
|
||||
return parse_cbtable(next_addr, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
debug("correct coreboot table found.\n");
|
||||
/* Succeeded in parsing the table. Header not needed anymore. */
|
||||
unmap_memory(&header_mapping);
|
||||
lbtable_mapping = table_mapping;
|
||||
|
||||
/*
|
||||
* Table parsing succeeded. If forwarding table not found update
|
||||
* coreboot table mapping for future use.
|
||||
*/
|
||||
if (ret == 0)
|
||||
lbtable_mapping = table_mapping;
|
||||
else
|
||||
unmap_memory(&table_mapping);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -449,78 +425,6 @@ static int parse_cbtable(uint64_t address, size_t table_size)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static void lb_table_get_entry(uint32_t tag, uint8_t **buf_out, size_t *size_out)
|
||||
{
|
||||
const struct lb_record *lbr_p;
|
||||
const uint8_t *lbtable_raw;
|
||||
size_t table_size;
|
||||
bool tag_found = false;
|
||||
|
||||
if (get_cbmem_entry(CBMEM_ID_CBTABLE, (uint8_t **)&lbtable_raw, &table_size)) {
|
||||
fprintf(stderr, "coreboot table not found.\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
const struct lb_header *lbh = (const struct lb_header *)lbtable_raw;
|
||||
|
||||
for (size_t i = 0; i < lbh->table_bytes; i += lbr_p->size) {
|
||||
lbr_p = (const struct lb_record *)(&lbtable_raw[lbh->header_bytes + i]);
|
||||
if (lbr_p->tag == tag) {
|
||||
tag_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!tag_found) {
|
||||
fprintf(stderr, "coreboot table entry %#x not found.\n", tag);
|
||||
free((void *)lbtable_raw);
|
||||
abort();
|
||||
}
|
||||
|
||||
debug("coreboot table entry %#x found.\n", tag);
|
||||
|
||||
*buf_out = malloc(lbr_p->size);
|
||||
if (!*buf_out) {
|
||||
fprintf(stderr,
|
||||
"Unable to allocate memory for coreboot table entry %#x, size: %d\n",
|
||||
tag, lbr_p->size);
|
||||
free((void *)lbtable_raw);
|
||||
abort();
|
||||
}
|
||||
memcpy(*buf_out, lbr_p, lbr_p->size);
|
||||
*size_out = lbr_p->size;
|
||||
free((void *)lbtable_raw);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns mapping, mapped buffer pointer and its size by parameters.
|
||||
* Returns zero on success.
|
||||
* unmap_mempry() after use.
|
||||
*/
|
||||
static int map_cbmem_entry_rw(uint32_t id, struct mapping *mapping, uint8_t **buf_out,
|
||||
size_t *size_out)
|
||||
{
|
||||
uint64_t addr;
|
||||
size_t size;
|
||||
|
||||
if (find_cbmem_entry(id, &addr, &size)) {
|
||||
debug("CBMEM entry not found. CBMEM id: %#x\n", id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*buf_out = map_memory_with_prot(mapping, addr, size, PROT_READ | PROT_WRITE);
|
||||
if (!*buf_out) {
|
||||
fprintf(stderr,
|
||||
"Unable to map CBMEM entry id: %#x, size: %zu for read-write access.\n",
|
||||
id, size);
|
||||
abort();
|
||||
}
|
||||
|
||||
*size_out = size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(linux) && (defined(__i386__) || defined(__x86_64__))
|
||||
/*
|
||||
* read CPU frequency from a sysfs file, return an frequency in Megahertz as
|
||||
|
|
@ -624,19 +528,11 @@ static uint64_t timestamp_get(uint64_t table_tick_freq_mhz)
|
|||
{
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
uint64_t tsc = __rdtsc();
|
||||
struct lb_tsc_info *tsc_info;
|
||||
size_t size;
|
||||
|
||||
/* No tick frequency specified means raw TSC values. */
|
||||
if (!table_tick_freq_mhz)
|
||||
return tsc;
|
||||
|
||||
lb_table_get_entry(LB_TAG_TSC_INFO, (uint8_t **)&tsc_info, &size);
|
||||
|
||||
const uint32_t tsc_freq_khz = tsc_info->freq_khz;
|
||||
|
||||
free(tsc_info);
|
||||
|
||||
if (tsc_freq_khz)
|
||||
return tsc * table_tick_freq_mhz * 1000 / tsc_freq_khz;
|
||||
#else
|
||||
|
|
@ -783,23 +679,34 @@ static void dump_timestamps(enum timestamps_print_type output_type)
|
|||
size_t size;
|
||||
uint64_t prev_stamp = 0;
|
||||
uint64_t total_time = 0;
|
||||
struct mapping timestamp_mapping;
|
||||
|
||||
if (get_cbmem_entry(CBMEM_ID_TIMESTAMP, (uint8_t **)&tst_p, &size)) {
|
||||
fprintf(stderr, "Timestamps not found.\n");
|
||||
abort();
|
||||
if (timestamps.tag != LB_TAG_TIMESTAMPS) {
|
||||
fprintf(stderr, "No timestamps found in coreboot table.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
size = sizeof(*tst_p);
|
||||
tst_p = map_memory(×tamp_mapping, timestamps.cbmem_addr, size);
|
||||
if (!tst_p)
|
||||
die("Unable to map timestamp header\n");
|
||||
|
||||
timestamp_set_tick_freq(tst_p->tick_freq_mhz);
|
||||
|
||||
if (output_type == TIMESTAMPS_PRINT_NORMAL)
|
||||
printf("%d entries total:\n\n", tst_p->num_entries);
|
||||
size += tst_p->num_entries * sizeof(tst_p->entries[0]);
|
||||
|
||||
unmap_memory(×tamp_mapping);
|
||||
|
||||
tst_p = map_memory(×tamp_mapping, timestamps.cbmem_addr, size);
|
||||
if (!tst_p)
|
||||
die("Unable to map full timestamp table\n");
|
||||
|
||||
sorted_tst_p = malloc(size + sizeof(struct timestamp_entry));
|
||||
if (!sorted_tst_p) {
|
||||
free((void *)tst_p);
|
||||
if (!sorted_tst_p)
|
||||
die("Failed to allocate memory");
|
||||
}
|
||||
memcpy(sorted_tst_p, tst_p, size);
|
||||
aligned_memcpy(sorted_tst_p, tst_p, size);
|
||||
|
||||
/*
|
||||
* Insert a timestamp to represent the base time (start of coreboot),
|
||||
|
|
@ -876,8 +783,8 @@ static void dump_timestamps(enum timestamps_print_type output_type)
|
|||
printf("\n");
|
||||
}
|
||||
|
||||
unmap_memory(×tamp_mapping);
|
||||
free(sorted_tst_p);
|
||||
free((void *)tst_p);
|
||||
}
|
||||
|
||||
/* add a timestamp entry */
|
||||
|
|
@ -885,14 +792,16 @@ static void timestamp_add_now(uint32_t timestamp_id)
|
|||
{
|
||||
struct timestamp_table *tst_p;
|
||||
struct mapping timestamp_mapping;
|
||||
size_t tst_size;
|
||||
|
||||
if (map_cbmem_entry_rw(CBMEM_ID_TIMESTAMP, ×tamp_mapping, (uint8_t **)&tst_p,
|
||||
&tst_size)) {
|
||||
fprintf(stderr, "Unable to find timestamps.\n");
|
||||
abort();
|
||||
if (timestamps.tag != LB_TAG_TIMESTAMPS) {
|
||||
die("No timestamps found in coreboot table.\n");
|
||||
}
|
||||
|
||||
tst_p = map_memory_with_prot(×tamp_mapping, timestamps.cbmem_addr,
|
||||
timestamps.size, PROT_READ | PROT_WRITE);
|
||||
if (!tst_p)
|
||||
die("Unable to map timestamp table\n");
|
||||
|
||||
/*
|
||||
* Note that coreboot sizes the cbmem entry in the table according to
|
||||
* max_entries, so it's OK to just add more entries if there's room.
|
||||
|
|
@ -1086,24 +995,32 @@ static void parse_tpm2_log(const struct tcg_efi_spec_id_event *tpm2_log)
|
|||
}
|
||||
|
||||
/* Dump the TPM log table in format defined by specifications */
|
||||
static void dump_tpm_std_log(void *buf)
|
||||
static void dump_tpm_std_log(uint64_t addr, size_t size)
|
||||
{
|
||||
const void *event_log;
|
||||
const struct tcpa_spec_entry *tspec_entry;
|
||||
const struct tcg_efi_spec_id_event *tcg_spec_entry;
|
||||
struct mapping log_mapping;
|
||||
|
||||
tspec_entry = buf;
|
||||
event_log = map_memory(&log_mapping, addr, size);
|
||||
if (!event_log)
|
||||
die("Unable to map TPM eventlog\n");
|
||||
|
||||
tspec_entry = event_log;
|
||||
if (!strcmp((const char *)tspec_entry->signature, TCPA_SPEC_ID_EVENT_SIGNATURE)) {
|
||||
if (tspec_entry->spec_version_major == 1 &&
|
||||
tspec_entry->spec_version_minor == 2 && tspec_entry->spec_errata >= 1 &&
|
||||
tspec_entry->spec_version_minor == 2 &&
|
||||
tspec_entry->spec_errata >= 1 &&
|
||||
le32toh(tspec_entry->entry.event_type) == EV_NO_ACTION) {
|
||||
parse_tpm12_log(tspec_entry);
|
||||
} else {
|
||||
fprintf(stderr, "Unknown TPM1.2 log specification\n");
|
||||
}
|
||||
unmap_memory(&log_mapping);
|
||||
return;
|
||||
}
|
||||
|
||||
tcg_spec_entry = buf;
|
||||
tcg_spec_entry = event_log;
|
||||
if (!strcmp((const char *)tcg_spec_entry->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE)) {
|
||||
if (tcg_spec_entry->spec_version_major == 2 &&
|
||||
tcg_spec_entry->spec_version_minor == 0 &&
|
||||
|
|
@ -1112,25 +1029,42 @@ static void dump_tpm_std_log(void *buf)
|
|||
} else {
|
||||
fprintf(stderr, "Unknown TPM2 log specification.\n");
|
||||
}
|
||||
unmap_memory(&log_mapping);
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Unknown TPM log specification: %.*s\n",
|
||||
(int)sizeof(tcg_spec_entry->signature),
|
||||
(const char *)tcg_spec_entry->signature);
|
||||
|
||||
unmap_memory(&log_mapping);
|
||||
}
|
||||
|
||||
/* dump the TPM CB log table */
|
||||
static void dump_tpm_cb_log(void)
|
||||
{
|
||||
const struct tpm_cb_log_table *tclt_p;
|
||||
size_t tclt_size;
|
||||
size_t size;
|
||||
struct mapping log_mapping;
|
||||
|
||||
if (get_cbmem_entry(CBMEM_ID_TPM_CB_LOG, (uint8_t **)&tclt_p, &tclt_size)) {
|
||||
fprintf(stderr, "coreboot TPM log not found.\n");
|
||||
abort();
|
||||
if (tpm_cb_log.tag != LB_TAG_TPM_CB_LOG) {
|
||||
fprintf(stderr, "No TPM log found in coreboot table.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
size = sizeof(*tclt_p);
|
||||
tclt_p = map_memory(&log_mapping, tpm_cb_log.cbmem_addr, size);
|
||||
if (!tclt_p)
|
||||
die("Unable to map TPM log header\n");
|
||||
|
||||
size += tclt_p->num_entries * sizeof(tclt_p->entries[0]);
|
||||
|
||||
unmap_memory(&log_mapping);
|
||||
|
||||
tclt_p = map_memory(&log_mapping, tpm_cb_log.cbmem_addr, size);
|
||||
if (!tclt_p)
|
||||
die("Unable to map full TPM log table\n");
|
||||
|
||||
printf("coreboot TPM log:\n\n");
|
||||
|
||||
for (uint16_t i = 0; i < tclt_p->num_entries; i++) {
|
||||
|
|
@ -1141,22 +1075,30 @@ static void dump_tpm_cb_log(void)
|
|||
printf(" %s [%s]\n", tce->digest_type, tce->name);
|
||||
}
|
||||
|
||||
free((void *)tclt_p);
|
||||
unmap_memory(&log_mapping);
|
||||
}
|
||||
|
||||
static void dump_tpm_log(void)
|
||||
{
|
||||
uint8_t *buf;
|
||||
uint64_t start;
|
||||
size_t size;
|
||||
|
||||
if (!get_cbmem_entry(CBMEM_ID_TCPA_TCG_LOG, &buf, &size) ||
|
||||
!get_cbmem_entry(CBMEM_ID_TPM2_TCG_LOG, &buf, &size)) {
|
||||
dump_tpm_std_log(buf);
|
||||
free(buf);
|
||||
} else
|
||||
if (!find_cbmem_entry(CBMEM_ID_TCPA_TCG_LOG, &start, &size) ||
|
||||
!find_cbmem_entry(CBMEM_ID_TPM2_TCG_LOG, &start, &size))
|
||||
dump_tpm_std_log(start, size);
|
||||
else
|
||||
dump_tpm_cb_log();
|
||||
}
|
||||
|
||||
struct cbmem_console {
|
||||
uint32_t size;
|
||||
uint32_t cursor;
|
||||
uint8_t body[];
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
#define CBMC_CURSOR_MASK ((1 << 28) - 1)
|
||||
#define CBMC_OVERFLOW (1 << 31)
|
||||
|
||||
enum console_print_type {
|
||||
CONSOLE_PRINT_FULL = 0,
|
||||
CONSOLE_PRINT_LAST,
|
||||
|
|
@ -1192,37 +1134,50 @@ static void dump_console(enum console_print_type type, int max_loglevel, int pri
|
|||
const struct cbmem_console *console_p;
|
||||
char *console_c;
|
||||
size_t size, cursor, previous;
|
||||
size_t console_buf_size;
|
||||
struct mapping console_mapping;
|
||||
|
||||
if (get_cbmem_entry(CBMEM_ID_CONSOLE, (uint8_t **)&console_p, &console_buf_size)) {
|
||||
fprintf(stderr, "CBMEM console not found.\n");
|
||||
abort();
|
||||
if (console.tag != LB_TAG_CBMEM_CONSOLE) {
|
||||
fprintf(stderr, "No console found in coreboot table.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
size = sizeof(*console_p);
|
||||
console_p = map_memory(&console_mapping, console.cbmem_addr, size);
|
||||
if (!console_p)
|
||||
die("Unable to map console object.\n");
|
||||
|
||||
cursor = console_p->cursor & CBMC_CURSOR_MASK;
|
||||
if (!(console_p->cursor & CBMC_OVERFLOW) && cursor < console_p->size)
|
||||
size = cursor;
|
||||
else
|
||||
size = console_p->size;
|
||||
unmap_memory(&console_mapping);
|
||||
|
||||
console_c = malloc(size + 1);
|
||||
if (!console_c) {
|
||||
fprintf(stderr, "Not enough memory for console.\n");
|
||||
free((void *)console_p);
|
||||
abort();
|
||||
exit(1);
|
||||
}
|
||||
console_c[size] = '\0';
|
||||
|
||||
console_p = map_memory(&console_mapping, console.cbmem_addr,
|
||||
size + sizeof(*console_p));
|
||||
|
||||
if (!console_p)
|
||||
die("Unable to map full console object.\n");
|
||||
|
||||
if (console_p->cursor & CBMC_OVERFLOW) {
|
||||
if (cursor >= size) {
|
||||
printf("cbmem: ERROR: CBMEM console struct is illegal, "
|
||||
"output may be corrupt or out of order!\n\n");
|
||||
cursor = 0;
|
||||
}
|
||||
memcpy(console_c, console_p->body + cursor, size - cursor);
|
||||
memcpy(console_c + size - cursor, console_p->body, cursor);
|
||||
aligned_memcpy(console_c, console_p->body + cursor,
|
||||
size - cursor);
|
||||
aligned_memcpy(console_c + size - cursor,
|
||||
console_p->body, cursor);
|
||||
} else {
|
||||
memcpy(console_c, console_p->body, size);
|
||||
aligned_memcpy(console_c, console_p->body, size);
|
||||
}
|
||||
|
||||
/* Slight memory corruption may occur between reboots and give us a few
|
||||
|
|
@ -1297,88 +1252,109 @@ static void dump_console(enum console_print_type type, int max_loglevel, int pri
|
|||
printf(BIOS_LOG_ESCAPE_RESET);
|
||||
|
||||
free(console_c);
|
||||
free((void *)console_p);
|
||||
unmap_memory(&console_mapping);
|
||||
}
|
||||
|
||||
/* Hexdump provided buffer using start_address as an offset in the output. */
|
||||
static void hexdump(const uintptr_t start_address, const uint8_t *buf, const int length)
|
||||
static void hexdump(unsigned long memory, int length)
|
||||
{
|
||||
int i;
|
||||
const uint8_t *m;
|
||||
int all_zero = 0;
|
||||
struct mapping hexdump_mapping;
|
||||
|
||||
m = map_memory(&hexdump_mapping, memory, length);
|
||||
if (!m)
|
||||
die("Unable to map hexdump memory.\n");
|
||||
|
||||
for (i = 0; i < length; i += 16) {
|
||||
int j;
|
||||
|
||||
all_zero++;
|
||||
for (j = 0; j < 16; j++) {
|
||||
if (buf[i + j] != 0) {
|
||||
if(m[i+j] != 0) {
|
||||
all_zero = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (all_zero < 2) {
|
||||
printf("%08lx:", start_address + i);
|
||||
printf("%08lx:", memory + i);
|
||||
for (j = 0; j < 16; j++)
|
||||
printf(" %02x", buf[i + j]);
|
||||
printf(" %02x", m[i+j]);
|
||||
printf(" ");
|
||||
for (j = 0; j < 16; j++)
|
||||
printf("%c", isprint(buf[i + j]) ? buf[i + j] : '.');
|
||||
printf("%c", isprint(m[i+j]) ? m[i+j] : '.');
|
||||
printf("\n");
|
||||
} else if (all_zero == 2) {
|
||||
printf("...\n");
|
||||
}
|
||||
}
|
||||
|
||||
unmap_memory(&hexdump_mapping);
|
||||
}
|
||||
|
||||
static void dump_cbmem_hex(void)
|
||||
{
|
||||
struct mapping cbmem_mapping;
|
||||
struct lb_memory *memory;
|
||||
const uint8_t *buf = NULL;
|
||||
size_t size = 0;
|
||||
|
||||
lb_table_get_entry(LB_TAG_MEMORY, (uint8_t **)&memory, &size);
|
||||
|
||||
if (!memory)
|
||||
die("No memory entries available.\n");
|
||||
|
||||
const int entries = (memory->size - sizeof(*memory)) / sizeof(memory->map[0]);
|
||||
/* First from the end is CBMEM */
|
||||
for (int i = entries - 1; i >= 0; --i) {
|
||||
if (memory->map[i].type != LB_MEM_TABLE)
|
||||
continue;
|
||||
|
||||
buf = map_memory(&cbmem_mapping, memory->map[i].start, memory->map[i].size);
|
||||
if (!buf)
|
||||
die("Unable to map CBMEM area memory.\n");
|
||||
|
||||
size = memory->map[i].size;
|
||||
break;
|
||||
if (cbmem.type != LB_MEM_TABLE) {
|
||||
fprintf(stderr, "No coreboot CBMEM area found!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!buf)
|
||||
die("Unable to find CBMEM area memory entry.\n");
|
||||
hexdump(cbmem.start, cbmem.size);
|
||||
}
|
||||
|
||||
hexdump(cbmem_mapping.phys, buf, size);
|
||||
static void rawdump(uint64_t base, uint64_t size)
|
||||
{
|
||||
const uint8_t *m;
|
||||
struct mapping dump_mapping;
|
||||
|
||||
unmap_memory(&cbmem_mapping);
|
||||
free(memory);
|
||||
m = map_memory(&dump_mapping, base, size);
|
||||
if (!m)
|
||||
die("Unable to map rawdump memory\n");
|
||||
|
||||
for (uint64_t i = 0 ; i < size; i++)
|
||||
printf("%c", m[i]);
|
||||
|
||||
unmap_memory(&dump_mapping);
|
||||
}
|
||||
|
||||
static void dump_cbmem_raw(unsigned int id)
|
||||
{
|
||||
uint8_t *buf;
|
||||
size_t size;
|
||||
const uint8_t *table;
|
||||
size_t offset;
|
||||
uint64_t base = 0;
|
||||
uint64_t size = 0;
|
||||
|
||||
if (get_cbmem_entry(id, &buf, &size)) {
|
||||
fprintf(stderr, "cbmem entry id: %#x not found.\n", id);
|
||||
abort();
|
||||
table = mapping_virt(&lbtable_mapping);
|
||||
|
||||
if (table == NULL)
|
||||
return;
|
||||
|
||||
offset = 0;
|
||||
|
||||
while (offset < mapping_size(&lbtable_mapping)) {
|
||||
const struct lb_record *lbr;
|
||||
struct lb_cbmem_entry lbe;
|
||||
|
||||
lbr = (const void *)(table + offset);
|
||||
offset += lbr->size;
|
||||
|
||||
if (lbr->tag != LB_TAG_CBMEM_ENTRY)
|
||||
continue;
|
||||
|
||||
aligned_memcpy(&lbe, lbr, sizeof(lbe));
|
||||
if (lbe.id == id) {
|
||||
debug("found id for raw dump %0x", lbe.id);
|
||||
base = lbe.address;
|
||||
size = lbe.entry_size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fwrite(buf, 1, size, stdout);
|
||||
|
||||
free(buf);
|
||||
if (!base)
|
||||
fprintf(stderr, "id %0x not found in cbtable\n", id);
|
||||
else
|
||||
rawdump(base, size);
|
||||
}
|
||||
|
||||
struct cbmem_id_to_name {
|
||||
|
|
@ -1423,31 +1399,34 @@ static void cbmem_print_entry(int n, uint32_t id, uint64_t base, uint64_t size)
|
|||
|
||||
static void dump_cbmem_toc(void)
|
||||
{
|
||||
int i = 0;
|
||||
const uint8_t *table = NULL;
|
||||
size_t table_size = 0;
|
||||
int i;
|
||||
const uint8_t *table;
|
||||
size_t offset;
|
||||
|
||||
if (get_cbmem_entry(CBMEM_ID_CBTABLE, (uint8_t **)&table, &table_size)) {
|
||||
fprintf(stderr, "coreboot table not found.\n");
|
||||
abort();
|
||||
}
|
||||
table = mapping_virt(&lbtable_mapping);
|
||||
|
||||
const struct lb_header *lbh = (const struct lb_header *)table;
|
||||
if (table == NULL)
|
||||
return;
|
||||
|
||||
printf("CBMEM table of contents:\n");
|
||||
printf(" %-20s %-8s %-8s %-8s\n", "NAME", "ID", "START", "LENGTH");
|
||||
printf(" %-20s %-8s %-8s %-8s\n", "NAME", "ID", "START",
|
||||
"LENGTH");
|
||||
|
||||
const struct lb_record *lbr = NULL;
|
||||
for (size_t offset = lbh->header_bytes;
|
||||
offset < lbh->table_bytes + lbh->header_bytes - sizeof(struct lb_cbmem_entry);
|
||||
offset += lbr->size) {
|
||||
lbr = (const struct lb_record *)&table[offset];
|
||||
i = 0;
|
||||
offset = 0;
|
||||
|
||||
while (offset < mapping_size(&lbtable_mapping)) {
|
||||
const struct lb_record *lbr;
|
||||
struct lb_cbmem_entry lbe;
|
||||
|
||||
lbr = (const void *)(table + offset);
|
||||
offset += lbr->size;
|
||||
|
||||
if (lbr->tag != LB_TAG_CBMEM_ENTRY)
|
||||
continue;
|
||||
|
||||
const struct lb_cbmem_entry *lbe = (const struct lb_cbmem_entry *)lbr;
|
||||
cbmem_print_entry(i, lbe->id, lbe->address, lbe->entry_size);
|
||||
aligned_memcpy(&lbe, lbr, sizeof(lbe));
|
||||
cbmem_print_entry(i, lbe.id, lbe.address, lbe.entry_size);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
|
@ -1482,23 +1461,21 @@ static int mkpath(char *path, mode_t mode)
|
|||
static void dump_coverage(void)
|
||||
{
|
||||
uint64_t start;
|
||||
uint8_t *coverage;
|
||||
size_t size;
|
||||
const void *coverage;
|
||||
struct mapping coverage_mapping;
|
||||
unsigned long phys_offset;
|
||||
#define phys_to_virt(x) ((void *)(unsigned long)(x) + phys_offset)
|
||||
|
||||
if (get_cbmem_entry(CBMEM_ID_COVERAGE, &coverage, &size)) {
|
||||
fprintf(stderr, "No coverage information found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Physical address is needed for pointer translation
|
||||
if (find_cbmem_entry(CBMEM_ID_COVERAGE, &start, &size)) {
|
||||
fprintf(stderr, "No coverage information found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Map coverage area */
|
||||
coverage = map_memory(&coverage_mapping, start, size);
|
||||
if (!coverage)
|
||||
die("Unable to map coverage area.\n");
|
||||
phys_offset = (unsigned long)coverage - (unsigned long)start;
|
||||
|
||||
printf("Dumping coverage data...\n");
|
||||
|
|
@ -1535,7 +1512,7 @@ static void dump_coverage(void)
|
|||
else
|
||||
file = NULL;
|
||||
}
|
||||
free(coverage);
|
||||
unmap_memory(&coverage_mapping);
|
||||
}
|
||||
|
||||
static void print_version(void)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue