cbfs: Add "struct" file type and associated helpers

This patch adds functionality to compile a C data structure into a raw
binary file, add it to CBFS and allow coreboot to load it at runtime.
This is useful in all cases where we need to be able to have several
larger data sets available in an image, but will only require a small
subset of them at boot (a classic example would be DRAM parameters) or
only require it in certain boot modes. This allows us to load less data
from flash and increase boot speed compared to solutions that compile
all data sets into a stage.

Each structure has to be defined in a separate .c file which contains no
functions and only a single global variable. The data type must be
serialization safe (composed of only fixed-width types, paying attention
to padding). It must be added to CBFS in a Makefile with the 'struct'
file processor.

Change-Id: Iab65c0b6ebea235089f741eaa8098743e54d6ccc
Signed-off-by: Julius Werner <jwerner@chromium.org>
Reviewed-on: https://review.coreboot.org/16272
Tested-by: build bot (Jenkins)
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
This commit is contained in:
Julius Werner 2016-08-19 15:43:06 -07:00
parent 71885a4960
commit f975e55dcd
6 changed files with 41 additions and 0 deletions

View File

@ -277,6 +277,18 @@ cbfs-files-processor-defconfig= \
rm -f $(2).tmp2 && \ rm -f $(2).tmp2 && \
\mv -f $(2).tmp $(2)) \mv -f $(2).tmp $(2))
#######################################################################
# Compile a C file with a bare struct definition into binary
# arg1: C source file
# arg2: binary file
cbfs-files-processor-struct= \
$(eval $(2): $(1) $(obj)/build.h $(KCONFIG_AUTOHEADER); \
printf " CC+STRIP $(@)\n"; \
$(CC_ramstage) -MMD $(CPPFLAGS_ramstage) $(CFLAGS_ramstage) $(ramstage-c-ccopts) -include $(KCONFIG_AUTOHEADER) -MT $(2) -o $(2).tmp -c $(1) && \
$(OBJCOPY_ramstage) -O binary $(2).tmp $(2); \
rm -f $(2).tmp) \
$(eval DEPENDENCIES += $(2).d)
####################################################################### #######################################################################
# Add handler for arbitrary files in CBFS # Add handler for arbitrary files in CBFS
$(call add-special-class,cbfs-files) $(call add-special-class,cbfs-files)

View File

@ -73,6 +73,7 @@
#define CBFS_TYPE_VSA 0x51 #define CBFS_TYPE_VSA 0x51
#define CBFS_TYPE_MBI 0x52 #define CBFS_TYPE_MBI 0x52
#define CBFS_TYPE_MICROCODE 0x53 #define CBFS_TYPE_MICROCODE 0x53
#define CBFS_TYPE_STRUCT 0x70
#define CBFS_COMPONENT_CMOS_DEFAULT 0xaa #define CBFS_COMPONENT_CMOS_DEFAULT 0xaa
#define CBFS_COMPONENT_CMOS_LAYOUT 0x01aa #define CBFS_COMPONENT_CMOS_LAYOUT 0x01aa

View File

@ -77,6 +77,7 @@
#define CBFS_TYPE_MRC 0x61 #define CBFS_TYPE_MRC 0x61
#define CBFS_TYPE_MMA 0x62 #define CBFS_TYPE_MMA 0x62
#define CBFS_TYPE_EFI 0x63 #define CBFS_TYPE_EFI 0x63
#define CBFS_TYPE_STRUCT 0x70
#define CBFS_COMPONENT_CMOS_DEFAULT 0xaa #define CBFS_COMPONENT_CMOS_DEFAULT 0xaa
#define CBFS_TYPE_SPD 0xab #define CBFS_TYPE_SPD 0xab
#define CBFS_TYPE_MRC_CACHE 0xac #define CBFS_TYPE_MRC_CACHE 0xac

View File

@ -34,6 +34,10 @@ int cbfs_boot_locate(struct cbfsf *fh, const char *name, uint32_t *type);
* leaking mappings are a no-op. Returns NULL on error, else returns * leaking mappings are a no-op. Returns NULL on error, else returns
* the mapping and sets the size of the file. */ * the mapping and sets the size of the file. */
void *cbfs_boot_map_with_leak(const char *name, uint32_t type, size_t *size); void *cbfs_boot_map_with_leak(const char *name, uint32_t type, size_t *size);
/* Load a struct file from CBFS into a buffer. Returns amount of loaded
* bytes on success or 0 on error. File will get decompressed as necessary.
* Same decompression requirements as cbfs_load_and_decompress(). */
size_t cbfs_boot_load_struct(const char *name, void *buf, size_t buf_size);
/* Load |in_size| bytes from |rdev| at |offset| to the |buffer_size| bytes /* Load |in_size| bytes from |rdev| at |offset| to the |buffer_size| bytes
* large |buffer|, decompressing it according to |compression| in the process. * large |buffer|, decompressing it according to |compression| in the process.

View File

@ -79,6 +79,8 @@ size_t cbfs_load_and_decompress(const struct region_device *rdev, size_t offset,
switch (compression) { switch (compression) {
case CBFS_COMPRESS_NONE: case CBFS_COMPRESS_NONE:
if (buffer_size < in_size)
return 0;
if (rdev_readat(rdev, buffer, offset, in_size) != in_size) if (rdev_readat(rdev, buffer, offset, in_size) != in_size)
return 0; return 0;
return in_size; return in_size;
@ -166,6 +168,25 @@ void *cbfs_boot_load_stage_by_name(const char *name)
return prog_entry(&stage); return prog_entry(&stage);
} }
size_t cbfs_boot_load_struct(const char *name, void *buf, size_t buf_size)
{
struct cbfsf fh;
uint32_t compression_algo;
size_t decompressed_size;
uint32_t type = CBFS_TYPE_STRUCT;
if (cbfs_boot_locate(&fh, name, &type) < 0)
return 0;
if (cbfsf_decompression_info(&fh, &compression_algo,
&decompressed_size) < 0
|| decompressed_size > buf_size)
return 0;
return cbfs_load_and_decompress(&fh.data, 0, region_device_sz(&fh.data),
buf, buf_size, compression_algo);
}
int cbfs_prog_stage_load(struct prog *pstage) int cbfs_prog_stage_load(struct prog *pstage)
{ {
struct cbfs_stage stage; struct cbfs_stage stage;

View File

@ -186,6 +186,7 @@ struct cbfs_payload {
#define CBFS_COMPONENT_MRC 0x61 #define CBFS_COMPONENT_MRC 0x61
#define CBFS_COMPONENT_MMA 0x62 #define CBFS_COMPONENT_MMA 0x62
#define CBFS_COMPONENT_EFI 0x63 #define CBFS_COMPONENT_EFI 0x63
#define CBFS_COMPONENT_STRUCT 0x70
#define CBFS_COMPONENT_CMOS_DEFAULT 0xaa #define CBFS_COMPONENT_CMOS_DEFAULT 0xaa
#define CBFS_COMPONENT_SPD 0xab #define CBFS_COMPONENT_SPD 0xab
#define CBFS_COMPONENT_MRC_CACHE 0xac #define CBFS_COMPONENT_MRC_CACHE 0xac
@ -227,6 +228,7 @@ static struct typedesc_t filetypes[] unused = {
{CBFS_COMPONENT_MRC_CACHE, "mrc_cache"}, {CBFS_COMPONENT_MRC_CACHE, "mrc_cache"},
{CBFS_COMPONENT_MMA, "mma"}, {CBFS_COMPONENT_MMA, "mma"},
{CBFS_COMPONENT_EFI, "efi"}, {CBFS_COMPONENT_EFI, "efi"},
{CBFS_COMPONENT_STRUCT, "struct"},
{CBFS_COMPONENT_DELETED, "deleted"}, {CBFS_COMPONENT_DELETED, "deleted"},
{CBFS_COMPONENT_NULL, "null"} {CBFS_COMPONENT_NULL, "null"}
}; };