diff --git a/src/commonlib/include/commonlib/coreboot_tables.h b/src/commonlib/include/commonlib/coreboot_tables.h index 2ed4d7f277..5e0c87c99d 100644 --- a/src/commonlib/include/commonlib/coreboot_tables.h +++ b/src/commonlib/include/commonlib/coreboot_tables.h @@ -308,6 +308,19 @@ struct lb_boot_media_params { uint64_t boot_media_size; }; +/* + * There can be more than one of these records as there is one per cbmem entry. + */ +#define LB_TAG_CBMEM_ENTRY 0x0031 +struct lb_cbmem_entry { + uint32_t tag; + uint32_t size; + + uint64_t address; + uint32_t entry_size; + uint32_t id; +}; + #define LB_TAG_SERIALNO 0x002a #define MAX_SERIALNO_LENGTH 32 diff --git a/src/include/cbmem.h b/src/include/cbmem.h index 0825f2936f..efaa44f9c9 100644 --- a/src/include/cbmem.h +++ b/src/include/cbmem.h @@ -37,6 +37,7 @@ #ifndef __ASSEMBLER__ #include #include +#include struct cbmem_entry; @@ -114,12 +115,11 @@ typedef void (* const cbmem_init_hook_t)(int is_recovery); void cbmem_run_init_hooks(int is_recovery); void cbmem_fail_resume(void); -#ifndef __PRE_RAM__ /* Ramstage only functions. */ /* Add the cbmem memory used to the memory map at boot. */ void cbmem_add_bootmem(void); void cbmem_list(void); -#endif /* __PRE_RAM__ */ +void cbmem_add_records_to_cbtable(struct lb_header *header); #if ENV_RAMSTAGE #define ROMSTAGE_CBMEM_INIT_HOOK(init_fn_) static cbmem_init_hook_t \ diff --git a/src/include/imd.h b/src/include/imd.h index 90a0dd5a90..6575312f3d 100644 --- a/src/include/imd.h +++ b/src/include/imd.h @@ -120,6 +120,9 @@ size_t imd_entry_size(const struct imd *imd, const struct imd_entry *entry); /* Returns pointer to region described by entry or NULL on failure. */ void *imd_entry_at(const struct imd *imd, const struct imd_entry *entry); +/* Returns id for the imd entry. */ +uint32_t imd_entry_id(const struct imd *imd, const struct imd_entry *entry); + /* Attempt to remove entry from imd. */ int imd_entry_remove(const struct imd *imd, const struct imd_entry *entry); @@ -132,6 +135,13 @@ struct imd_lookup { int imd_print_entries(const struct imd *imd, const struct imd_lookup *lookup, size_t size); +struct imd_cursor; +/* Initialize an imd_cursor object to walk the IMD entries. */ +int imd_cursor_init(const struct imd *imd, struct imd_cursor *cursor); + +/* Retrieve the next imd entry the cursor is referencing. Returns NULL when + * no more entries exist. */ +const struct imd_entry *imd_cursor_next(struct imd_cursor *cursor); /* * The struct imd is a handle for working with an in-memory directory. @@ -148,4 +158,10 @@ struct imd { struct imdr sm; }; +struct imd_cursor { + size_t current_imdr; + size_t current_entry; + const struct imdr *imdr[2]; +}; + #endif /* _IMD_H_ */ diff --git a/src/lib/coreboot_table.c b/src/lib/coreboot_table.c index 8ffc69836c..258a4a53b7 100644 --- a/src/lib/coreboot_table.c +++ b/src/lib/coreboot_table.c @@ -538,6 +538,9 @@ unsigned long write_coreboot_table( lb_boot_media_params(head); + /* Add all cbmem entries into the coreboot tables. */ + cbmem_add_records_to_cbtable(head); + /* Remember where my valid memory ranges are */ return lb_table_fini(head); } diff --git a/src/lib/imd.c b/src/lib/imd.c index bbfbced9c8..2ad9cd8934 100644 --- a/src/lib/imd.c +++ b/src/lib/imd.c @@ -623,6 +623,11 @@ void *imd_entry_at(const struct imd *imd, const struct imd_entry *entry) return imdr_entry_at(imdr, entry); } +uint32_t imd_entry_id(const struct imd *imd, const struct imd_entry *entry) +{ + return entry->id; +} + int imd_entry_remove(const struct imd *imd, const struct imd_entry *entry) { struct imd_root *r; @@ -698,3 +703,42 @@ int imd_print_entries(const struct imd *imd, const struct imd_lookup *lookup, return 0; } + +int imd_cursor_init(const struct imd *imd, struct imd_cursor *cursor) +{ + if (imd == NULL || cursor == NULL) + return -1; + + memset(cursor, 0, sizeof(*cursor)); + + cursor->imdr[0] = &imd->lg; + cursor->imdr[1] = &imd->sm; + + return 0; +} + +const struct imd_entry *imd_cursor_next(struct imd_cursor *cursor) +{ + struct imd_root *r; + const struct imd_entry *e; + + if (cursor->current_imdr >= ARRAY_SIZE(cursor->imdr)) + return NULL; + + r = imdr_root(cursor->imdr[cursor->current_imdr]); + + if (r == NULL) + return NULL; + + if (cursor->current_entry >= r->num_entries) { + /* Try next imdr. */ + cursor->current_imdr++; + cursor->current_entry = 0; + return imd_cursor_next(cursor); + } + + e = &r->entries[cursor->current_entry]; + cursor->current_entry++; + + return e; +} diff --git a/src/lib/imd_cbmem.c b/src/lib/imd_cbmem.c index 7cc34f5878..49faad97b4 100644 --- a/src/lib/imd_cbmem.c +++ b/src/lib/imd_cbmem.c @@ -263,7 +263,6 @@ void *cbmem_entry_start(const struct cbmem_entry *entry) return imd_entry_at(imd, cbmem_to_imd(entry)); } -#if ENV_RAMSTAGE void cbmem_add_bootmem(void) { void *base = NULL; @@ -273,10 +272,50 @@ void cbmem_add_bootmem(void) bootmem_add_range((uintptr_t)base, size, LB_MEM_TABLE); } +#if ENV_RAMSTAGE +/* + * -fdata-sections doesn't work so well on read only strings. They all + * get put in the same section even though those strings may never be + * referenced in the final binary. + */ void cbmem_list(void) { static const struct imd_lookup lookup[] = { CBMEM_ID_TO_NAME_TABLE }; imd_print_entries(cbmem_get_imd(), lookup, ARRAY_SIZE(lookup)); } -#endif /* __PRE_RAM__ */ +#endif + +void cbmem_add_records_to_cbtable(struct lb_header *header) +{ + struct imd_cursor cursor; + struct imd *imd; + + imd = cbmem_get_imd(); + + if (imd_cursor_init(imd, &cursor)) + return; + + while (1) { + const struct imd_entry *e; + struct lb_cbmem_entry *lbe; + uint32_t id; + + e = imd_cursor_next(&cursor); + + if (e == NULL) + break; + + id = imd_entry_id(imd, e); + /* Don't add these metadata entries. */ + if (id == CBMEM_ID_IMD_ROOT || id == CBMEM_ID_IMD_SMALL) + continue; + + lbe = (struct lb_cbmem_entry *)lb_new_record(header); + lbe->tag = LB_TAG_CBMEM_ENTRY; + lbe->size = sizeof(*lbe); + lbe->address = (uintptr_t)imd_entry_at(imd, e); + lbe->entry_size = imd_entry_size(imd, e); + lbe->id = id; + } +}