Attention is currently required from: Jérémy Compostella.
Simon Glass has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/79317?usp=email )
Change subject: Introduce a coreboot Control Block (CCB) ......................................................................
Introduce a coreboot Control Block (CCB)
It is annoying to have to create and maintain two completely different builds of coreboot just make minor changes, such as to enable or disable the console.
It would be much more convenient to have a 'silent' flag in the image, which can be updated as needed, without needing to rebuild coreboot.
Introduce the 'coreboot Control Block' (CCB) which can hold such settings. It is designed to be available very early in bootblock, before CBFS is ready. It is able to control the output of the very first bootblock banner.
The CCB is then passed through the cache and placed in cbmem so it is available to other stages.
Provide options in cbfstool to get and set settings in the CCB. This makes it easy to use this feature.
BUG=b:172341184, b:262546009, b:249105972 BRANCH=none TEST=see next CL
Change-Id: I1f6a7a3e136067859e4e8c2043cf39f2a1771c0f Signed-off-by: Simon Glass sjg@chromium.org --- A Documentation/technotes/ccb.md M Documentation/technotes/index.md A Documentation/util/cbfstool/ccb.md M Documentation/util/cbfstool/index.md M src/arch/x86/car.ld M src/arch/x86/postcar.c M src/arch/x86/romstage.c M src/commonlib/bsd/include/commonlib/bsd/cbmem_id.h A src/commonlib/include/commonlib/ccb.h A src/commonlib/include/commonlib/ccb_api.h M src/console/Kconfig M src/include/memlayout.h M src/include/rules.h M src/include/symbols.h M src/lib/Kconfig M src/lib/Makefile.inc M src/lib/bootblock.c A src/lib/ccb.c M src/lib/hardwaremain.c M util/cbfstool/cbfstool.c 20 files changed, 484 insertions(+), 8 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/17/79317/1
diff --git a/Documentation/technotes/ccb.md b/Documentation/technotes/ccb.md new file mode 100644 index 0000000..51b8295 --- /dev/null +++ b/Documentation/technotes/ccb.md @@ -0,0 +1,88 @@ +# coreboot Control Block (CCB) + +The `coreboot Control Block` (CCB) is a small area of the bootblock which holds +settings for coreboot, such as whether to silence the console or not. These can +be changed without rebuilding coreboot, thus avoiding the need for multiple +images for minor differences. + +The CCB is really just a C struct with a magic number at the start, so it can +be easily found in the bootblock binary. It is compiled into the bootblock +just like any other data. + +When bootblock starts up it calls `ccb_init()` to find the CCB. The settings are +made available through a simple API defined in ccb_api.h + +Bootblock then adds the CCB to cbmem so that it will be available to any future +coreboot stages which are present, including romstage, postcar and ramstage. +Each stage calls `ccb_init()` and uses the same API to access the settings. + +## Changing settings + +Settings are changed using a special cbfstool subcommand. + +```eval_rst +See +:doc:`../util/cbfstool/ccb` +for more information. +``` + +## Available settings + +So far, apart from the magic number, the CCB consists only of a set of flags, +32 bits in length. The default flags value is 0 if the CCB is not present. + +## Searching for the CCB + +The CCB magic number is chosen so that it is very unlikey to appear in normal +bootblock code. The CCB_MAGIC is never used in the code itself, only in +cbfstool. + +## Extending CCB + +New flags can be added to `enum ccb_flags` as needed. Flags bits which are not +yet defined default to zero and that the default value should maximise +compatibility. In other words, be careful not to introduce flags which requires +a non-zero value for normal operation. + +New fields can be added to the CCB by extending `struct ccb`. Examples might +include controlling the log level. + +Any new settings should be implemented to cbfstool as well so that the values +can be read and written. + +## Backwards compatibility + +The CCB is not intended to be stored or generated outside the coreboot build, +so versioning is not included. In fact, while backwards compatibility should be +maintained where possible, it is not stictly necessary, since the CCB struct +does not have any meaning outside coreboot and all of the coreboot stages are +assumed to be built from the same version of the source code. + +Strictly speaking, changing the settings should be done with a cbfstool built +from the same source, although since the CCB will likely change infrequently, +this may not be always be necessary in practice. + +## Implementation notes + +Like the timestamp records, the CCB must be available from the start of the +first coreboot stage, right through to ramstage. The technique used by CCB is +largely the same as with timestamps. In bootblock, the CCB is simply a struct +in the data section, which can be updated by cbfstool. Bootblock copies this +struct into a cache defined by the linker script, so that the following pre-RAM +stages can access it. When romstage runs, it copies the CCB out of the cache +and into CBMEM. Thus it can be used by the following stages which don't have +access to the cache. + + +## Future extensions + +Some boards used a signed bootblock which cannot easily be modified after +building, since it requires resigning parts of the image. To address this, the +CCB could be stored in the romstage instead. This means it is unable to affect +the operation of bootblock, of course. This could be controlled by a new +ROMSTAGE_CCB option. + +The CMOS option feature (in `include/option.h`) could be expanded to provide an +API for CCB. Using strings for options might be too inefficient for bootblock, +so an enum could be introduced for common option types, with a lookup table used +to convert between strings and integers. diff --git a/Documentation/technotes/index.md b/Documentation/technotes/index.md index da5b864..97980d8 100644 --- a/Documentation/technotes/index.md +++ b/Documentation/technotes/index.md @@ -6,3 +6,4 @@ * [Unit Test Code Coverage](2021-05-code-coverage.md) * [Address Sanitizer](asan.md) * [coreboot Consoles](console.md) +* [coreboot Control Block (CCB)](ccb.md) diff --git a/Documentation/util/cbfstool/ccb.md b/Documentation/util/cbfstool/ccb.md new file mode 100644 index 0000000..e4df804 --- /dev/null +++ b/Documentation/util/cbfstool/ccb.md @@ -0,0 +1,18 @@ +# Managing the Coreboot Control Block + +The coreboot Control Block (CCB) is a small area of the bootblock which holds +settings for coreboot, such as whether to silence the console or not. These can +be changed without rebuilding coreboot, thus avoiding the need for multiple +images for minor differences. + +You can use 'cbfstool configure' to change these settings. + +Use `-n` to specify the setting to change and `-V` to specify its new value. + +To check the setting, use 'cbfstool configure-get'. + +```eval_rst +See +:doc:`../../technotes/ccb` +for more information. +``` diff --git a/Documentation/util/cbfstool/index.md b/Documentation/util/cbfstool/index.md index f99b612..ff021f2 100644 --- a/Documentation/util/cbfstool/index.md +++ b/Documentation/util/cbfstool/index.md @@ -3,3 +3,4 @@ Contents:
* [Handling memory mapped boot media](mmap_windows.md) +* [Managing the Coreboot Control Block](ccb.md) diff --git a/src/arch/x86/car.ld b/src/arch/x86/car.ld index eb75981..bd192dd 100644 --- a/src/arch/x86/car.ld +++ b/src/arch/x86/car.ld @@ -42,6 +42,7 @@ REGION(pdpt, ., 32, 32) #endif
+ CCB(., 0x10) TIMESTAMP(., 0x200)
#if !CONFIG(NO_CBFS_MCACHE) diff --git a/src/arch/x86/postcar.c b/src/arch/x86/postcar.c index b07b512..02462a4 100644 --- a/src/arch/x86/postcar.c +++ b/src/arch/x86/postcar.c @@ -2,6 +2,7 @@
#include <arch/romstage.h> #include <cbmem.h> +#include <commonlib/ccb_api.h> #include <console/console.h> #include <cpu/x86/mtrr.h> #include <main_decl.h> @@ -18,8 +19,6 @@ { late_car_teardown();
- console_init(); - /* * CBMEM needs to be recovered because timestamps rely on * the cbmem infrastructure being around. Explicitly recover it. @@ -30,6 +29,9 @@ if (!cbmem_online()) cbmem_initialize();
+ ccb_init(); + console_init(); + timestamp_add_now(TS_POSTCAR_START);
display_mtrrs(); diff --git a/src/arch/x86/romstage.c b/src/arch/x86/romstage.c index a7ee4d9..6ed4148 100644 --- a/src/arch/x86/romstage.c +++ b/src/arch/x86/romstage.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */
#include <arch/cpu.h> +#include <commonlib/ccb_api.h> #include <console/console.h> #include <timestamp.h> #include <romstage_common.h> @@ -9,6 +10,8 @@ { timestamp_add_now(TS_ROMSTAGE_START);
+ ccb_init(); + /* Assumes the hardware was set up during the bootblock */ console_init();
diff --git a/src/commonlib/bsd/include/commonlib/bsd/cbmem_id.h b/src/commonlib/bsd/include/commonlib/bsd/cbmem_id.h index 3536c46..67431c9 100644 --- a/src/commonlib/bsd/include/commonlib/bsd/cbmem_id.h +++ b/src/commonlib/bsd/include/commonlib/bsd/cbmem_id.h @@ -17,6 +17,7 @@ #define CBMEM_ID_CBTABLE 0x43425442 #define CBMEM_ID_CBTABLE_FWD 0x43425443 #define CBMEM_ID_CB_EARLY_DRAM 0x4544524D +#define CBMEM_ID_CCB 0x4343424B #define CBMEM_ID_CONSOLE 0x434f4e53 #define CBMEM_ID_CPU_CRASHLOG 0x4350555f #define CBMEM_ID_COVERAGE 0x47434f56 @@ -105,6 +106,7 @@ { CBMEM_ID_CBTABLE, "COREBOOT " }, \ { CBMEM_ID_CBTABLE_FWD, "COREBOOTFWD" }, \ { CBMEM_ID_CB_EARLY_DRAM, "EARLY DRAM USAGE" }, \ + { CBMEM_ID_CCB, "CCB " }, \ { CBMEM_ID_CONSOLE, "CONSOLE " }, \ { CBMEM_ID_COVERAGE, "COVERAGE " }, \ { CBMEM_ID_CPU_CRASHLOG, "CPU CRASHLOG"}, \ diff --git a/src/commonlib/include/commonlib/ccb.h b/src/commonlib/include/commonlib/ccb.h new file mode 100644 index 0000000..9bb4367 --- /dev/null +++ b/src/commonlib/include/commonlib/ccb.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* + * CCB - Coreboot Control Block - simple post-build settings for coreboot + * + * This is a small block of settings, typically loaded as part of bootblock. + * It can be updated using cbfstool without rebuilding coreboot. It is intended + * to control simple things like the serial console and logging. + * + * See Documentation/technotes/ccb.md for details + */ + +#ifndef CCB_H +#define CCB_H + +#include <stdint.h> + +/** + * enum ccb_flags - flags for use in the CCB + */ +enum ccb_flags { + DUMMY /* none yet */ +}; + +/* Magic number at the top of the CCB and used to detect it in the bootblock */ +#define CCB_MAGIC 0xc043b001 + +/** + * struct ccb - Data in the CCB + * + * @magic: Magic number, must be CCB_MAGIC + * @flags: Flag values - see enum ccb_flags + */ +struct ccb { + uint32_t magic; + uint32_t flags; +}; + +#endif diff --git a/src/commonlib/include/commonlib/ccb_api.h b/src/commonlib/include/commonlib/ccb_api.h new file mode 100644 index 0000000..58d34b5 --- /dev/null +++ b/src/commonlib/include/commonlib/ccb_api.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef CCB_API_H +#define CCB_API_H + +#include <commonlib/ccb.h> + +#if CONFIG(CCB) + +/** + * ccb_get() - Get a pointer to the coreboot control block + * + * Return: pointer to CCB or NULL if there is none + */ +const struct ccb *ccb_get(void); + +/** + * ccb_get_flags() - Get the CCB flags + * + * The default value of the flags is zero. + * + * Return: value of CCB flags or 0 if none + */ +int ccb_get_flags(void); + +/** + * ccb_init() - Set up the CCB for use + * + * This locates the CCB, either built into the stage (typically for bootblock), + * in the CCB cache (for romstage) or in cbmem (for later stages). + * + * After calling this, other API functions can be used + */ +void ccb_init(void); + +#else + +static inline struct ccb *ccb_get(void) { return NULL; } +static inline int ccb_get_flags(void) { return 0; } +static inline void ccb_init(void) {} + +#endif /* CCB_API_H */ + +#endif diff --git a/src/console/Kconfig b/src/console/Kconfig index 84eb9f9..4f2e53b 100644 --- a/src/console/Kconfig +++ b/src/console/Kconfig @@ -428,6 +428,29 @@
endchoice
+config CONSOLE_SILENT + bool "Support silencing the console" + default y + help + Typically when coreboot is built with the console enabled (e.g. + CONFIG_CONSOLE_SERIAL) the output is always produced. Enable this to + allow control of output at runtime. + + Note that this only affects the interactive console. Output to + 'stored' consoles (e.g. CBMEM) still goes ahead. + + This is controlled by calling console_set_silent(). + +config CONSOLE_SILENT_IN_CCB + bool "Flag for silencing console is in coreboot control block" + depends on BOOTBLOCK_CCB + default y + help + This enables using the coreboot control block (CCB) to obtain the + console silence flag in the bootblock. This is set to 0 by default, + meaning that the console is active (if enabled) but can be set to 1 + by an external tool operating on the image. + config DEFAULT_CONSOLE_LOGLEVEL int default 0 if DEFAULT_CONSOLE_LOGLEVEL_0 diff --git a/src/include/memlayout.h b/src/include/memlayout.h index 6280b20..82aefe4 100644 --- a/src/include/memlayout.h +++ b/src/include/memlayout.h @@ -65,6 +65,10 @@ REGION(timestamp, addr, size, 8) \ _ = ASSERT(size >= 212, "Timestamp region must fit timestamp_cache!");
+#define CCB(addr, size) \ + REGION(ccb, addr, size, 8) \ + _ = ASSERT(size >= 0x10, "CCB region must fit CCB space!"); + #define PRERAM_CBMEM_CONSOLE(addr, size) \ REGION(preram_cbmem_console, addr, size, 4)
diff --git a/src/include/rules.h b/src/include/rules.h index 7d32c77..8293fb8 100644 --- a/src/include/rules.h +++ b/src/include/rules.h @@ -303,6 +303,8 @@ #define ENV_HAS_CBMEM (ENV_CREATES_CBMEM || ENV_POSTCAR || ENV_RAMSTAGE) #define ENV_RAMINIT (ENV_SEPARATE_ROMSTAGE || (ENV_BOOTBLOCK && !CONFIG(SEPARATE_ROMSTAGE)))
+#define ENV_HOLDS_CCB (ENV_BOOTBLOCK && CONFIG(BOOTBLOCK_CCB)) + #if ENV_X86 #define ENV_HAS_SPINLOCKS !ENV_ROMSTAGE_OR_BEFORE #elif ENV_RISCV diff --git a/src/include/symbols.h b/src/include/symbols.h index b1e44e11..d69795c 100644 --- a/src/include/symbols.h +++ b/src/include/symbols.h @@ -29,6 +29,7 @@
DECLARE_REGION(sram) DECLARE_OPTIONAL_REGION(timestamp) +DECLARE_OPTIONAL_REGION(ccb) DECLARE_REGION(preram_cbmem_console) DECLARE_REGION(cbmem_init_hooks) DECLARE_REGION(stack) diff --git a/src/lib/Kconfig b/src/lib/Kconfig index 2364794..2acc8c4 100644 --- a/src/lib/Kconfig +++ b/src/lib/Kconfig @@ -74,6 +74,30 @@ help Name of the FMAP region created in the default FMAP to cache SPD data.
+config CCB + bool "Enable coreboot control block" + default y + help + This enables using the coreboot control block (CCB) to set features + at runtime. + + The CCB is useful for tweaking the operation of coreboot without + rebuilding it, such as enabling / disabling the serial console. + +config BOOTBLOCK_CCB + bool "Enable coreboot control block in bootblock" + depends on CCB + default y + help + Enable this to set up the CCB (coreboot control block) in bootblock. + Look for the CCB in the bootblock stage. The CCB is then passed to + the following stages using the cbmem structure. + + The CCB provides a few simple settings for coreboot which can be + changed using the 'cbfstool set-ccb' command. + + See Documentation/util/cbfstool/ccb.md for more information. + if RAMSTAGE_LIBHWBASE && !ROMSTAGE_LIBHWBASE
config HWBASE_DYNAMIC_MMIO diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc index 0f46008..a415599 100644 --- a/src/lib/Makefile.inc +++ b/src/lib/Makefile.inc @@ -197,6 +197,11 @@ verstage-y += hexdump.c smm-y += hexdump.c
+bootblock-$(CONFIG_CCB) += ccb.c +romstage-$(CONFIG_CCB) += ccb.c +postcar-$(CONFIG_CCB) += ccb.c +ramstage-$(CONFIG_CCB) += ccb.c + bootblock-$(CONFIG_FW_CONFIG) += fw_config.c verstage-$(CONFIG_FW_CONFIG) += fw_config.c romstage-$(CONFIG_FW_CONFIG) += fw_config.c diff --git a/src/lib/bootblock.c b/src/lib/bootblock.c index 5c202ba..f2b877b 100644 --- a/src/lib/bootblock.c +++ b/src/lib/bootblock.c @@ -3,6 +3,8 @@ #include <acpi/acpi.h> #include <arch/exception.h> #include <bootblock_common.h> +#include <cbmem.h> +#include <commonlib/ccb_api.h> #include <console/console.h> #include <delay.h> #include <metadata_hash.h> @@ -50,6 +52,8 @@ if (CONFIG(CMOS_POST)) cmos_post_init();
+ ccb_init(); + if (CONFIG(BOOTBLOCK_CONSOLE)) { console_init(); exception_init(); diff --git a/src/lib/ccb.c b/src/lib/ccb.c new file mode 100644 index 0000000..baf53e0 --- /dev/null +++ b/src/lib/ccb.c @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <assert.h> +#include <cbmem.h> +#include <commonlib/ccb_api.h> +#include <console/console.h> +#include <string.h> +#include <symbols.h> + +#if ENV_HOLDS_CCB +struct ccb ccb_static __attribute__((__section__(".init"))) = { + CCB_MAGIC, + /* flags must always be zero during the build */ +}; +#endif + +const struct ccb *ccb; + +const struct ccb *ccb_get(void) +{ + return ccb; +} + +int ccb_get_flags(void) +{ + return ccb ? ccb->flags : 0; +} + +static void add_ccb_to_cbmem(int is_recovery) +{ + struct ccb *ptr; + + ccb = ccb_get(); + if (ccb) { + ptr = cbmem_add(CBMEM_ID_CCB, sizeof(*ccb)); + if (ptr) { + printk(BIOS_DEBUG, "CCB: Adding to CBMEM\n"); + *ptr = *ccb; + } + } +} + +CBMEM_READY_HOOK(add_ccb_to_cbmem); + +void ccb_init(void) +{ + /* This function handles three main situations: + * + * 1. (bootblock) The CCB is in a variable. It must be copied into the + * cache so it is accessible through the pre-RAM stages, just like + * the timestamp cache + * 2. (romstage) The CCB is in the cache. It must be copied into a CBMEM + * entry so it is accessible through the post-RAM stages + * 3. (ramstage) The CCB is in CBMEM. It can be accessed directly. + */ +#if ENV_HOLDS_CCB + ccb = &ccb_static; + if (REGION_SIZE(ccb) < sizeof(*ccb)) { + BUG(); + } else { + /* Copy the CCB into the cache for use by romstage. */ + memcpy((void *)_ccb, ccb, sizeof(*ccb)); + } +#else + if (ENV_CREATES_CBMEM) { + if (!ENV_ROMSTAGE_OR_BEFORE) + return; + + /* Point to the cached CCB. This will be added to CBMEM. */ + ccb = (void *)_ccb; + } else { + ccb = cbmem_find(CBMEM_ID_CCB); + } +#endif +} diff --git a/src/lib/hardwaremain.c b/src/lib/hardwaremain.c index cee48ab..3f1612c 100644 --- a/src/lib/hardwaremain.c +++ b/src/lib/hardwaremain.c @@ -12,6 +12,7 @@ #include <boot/tables.h> #include <bootstate.h> #include <cbmem.h> +#include <commonlib/ccb_api.h> #include <commonlib/console/post_codes.h> #include <commonlib/helpers.h> #include <console/console.h> @@ -441,6 +442,13 @@ if (ENV_X86) init_timer();
+ /* + * CBMEM needs to be recovered because timestamps, ACPI, etc rely on + * the cbmem infrastructure being around. Explicitly recover it. + */ + cbmem_initialize(); + ccb_init(); + /* console_init() MUST PRECEDE ALL printk()! Additionally, ensure * it is the very first thing done in ramstage.*/ console_init(); @@ -448,12 +456,6 @@
exception_init();
- /* - * CBMEM needs to be recovered because timestamps, ACPI, etc rely on - * the cbmem infrastructure being around. Explicitly recover it. - */ - cbmem_initialize(); - timestamp_add_now(TS_RAMSTAGE_START); post_code(POSTCODE_ENTRY_HARDWAREMAIN);
diff --git a/util/cbfstool/cbfstool.c b/util/cbfstool/cbfstool.c index e11cfbc..9ecf379 100644 --- a/util/cbfstool/cbfstool.c +++ b/util/cbfstool/cbfstool.c @@ -18,6 +18,7 @@ #include <commonlib/bsd/cbfs_private.h> #include <commonlib/bsd/compression.h> #include <commonlib/bsd/metadata_hash.h> +#include <commonlib/ccb.h> #include <commonlib/fsp.h> #include <commonlib/endian.h> #include <commonlib/helpers.h> @@ -108,6 +109,7 @@ */ uint32_t ext_win_base; uint32_t ext_win_size; + const char *value; } param = { /* All variables not listed are initialized as zero. */ .arch = CBFS_ARCHITECTURE_UNKNOWN, @@ -674,6 +676,107 @@ return ret; }
+/** + * locate_ccb() - Locate the Coreboot Control Block in the CBFS image + * + * This is located in the bootblock and has a special signature + * + * @ccbp: Returns a pointer to the CCB + * Return: 0 if OK, 1 on error + */ +static int locate_ccb(struct buffer *buffer, struct ccb **ccbp) +{ + const struct fmap *fmap = partitioned_file_get_fmap(param.image_file); + uint32_t *ptr, *end; + char *data; + size_t size; + + if (!fmap) + goto no_bootblock; + + if (fmap_find_area(fmap, SECTION_NAME_BOOTBLOCK)) { + if (!partitioned_file_read_region(buffer, param.image_file, + SECTION_NAME_BOOTBLOCK)) + goto no_bootblock; + } else { + if (!partitioned_file_read_region(buffer, param.image_file, + SECTION_NAME_PRIMARY_CBFS)) + goto no_bootblock; + } + + data = buffer_get(buffer); + size = buffer_size(buffer); + + for (ptr = (uint32_t *)data, end = (uint32_t *)(data + size); ptr < end; + ptr++) { + if (*ptr == CCB_MAGIC) { + *ccbp = (struct ccb *)ptr; + return 0; + } + } + + ERROR("CCB not in bootblock\n"); + + return 1; + +no_bootblock: + ERROR("Bootblock not in ROM image?!?\n"); + return 1; +} + +/** + * cbfs_ccb_set_value() - Set the value of an item in the Coreboot Control Block + * + * @name: Name of item to set + * @value: Value to set it to + * Return: 0 if OK, non-zero on error + */ +static int cbfs_ccb_set_value(unused const char *name, unused const char *value) +{ + struct buffer buffer; + struct ccb *ccb; + uint val; + + if (locate_ccb(&buffer, &ccb)) + return 1; + + /* For now this code is very simple as we have no settings. */ + if (1) { + ERROR("Unknown CCB setting '%s'\n", name); + return 1; + } + val = 0; + printf("%s=%s\n", name, value); + ccb->flags = val; + + return 0; +} + +/** + * cbfs_ccb_get_value() - Get the value of an item in the Coreboot Control Block + * + * This displays the value for the given setting name + * + * @name: Name of item to get + * Return: 0 if OK, non-zero on error + */ +static int cbfs_ccb_get_value(unused const char *name) +{ + struct buffer buffer; + struct ccb *ccb; + + if (locate_ccb(&buffer, &ccb)) + return 1; + /* For now this code just shows an error as there are no settings. */ + if (1) { + ERROR("Unknown CCB setting '%s'\n", name); + return 1; + } + + + return 0; +} + static int is_valid_topswap(void) { switch (param.topswap_size) { @@ -1366,6 +1469,30 @@ param.headeroffset); }
+static int cbfs_ccb_set(void) +{ + if (!param.name) { + ERROR("You need to specify -n/--name.\n"); + return 1; + } + if (!param.value) { + ERROR("You need to specify a value to write.\n"); + return 1; + } + + return cbfs_ccb_set_value(param.name, param.value); +} + +static int cbfs_ccb_get(void) +{ + if (!param.name) { + ERROR("You need to specify -n/--name.\n"); + return 1; + } + + return cbfs_ccb_get_value(param.name); +} + static int cbfs_remove(void) { if (!param.name) { @@ -1796,6 +1923,8 @@ {"add-master-header", "H:r:vh?j:", cbfs_add_master_header, true, true}, {"compact", "r:h?", cbfs_compact, true, true}, {"copy", "r:R:h?", cbfs_copy, true, true}, + {"configure", "n:V:v?", cbfs_ccb_set, true, true}, + {"configure-get", "n:v?", cbfs_ccb_get, true, true}, {"create", "M:r:s:B:b:H:o:m:vh?", cbfs_create, true, true}, {"extract", "H:r:m:n:f:Uvh?", cbfs_extract, true, false}, {"layout", "wvh?", cbfs_layout, false, false}, @@ -1847,6 +1976,7 @@ {"size", required_argument, 0, 's' }, {"type", required_argument, 0, 't' }, {"verbose", no_argument, 0, 'v' }, + {"value", required_argument, 0, 'V' }, {"with-readonly", no_argument, 0, 'w' }, {"xip", no_argument, 0, 'y' }, {"gen-attribute", no_argument, 0, 'g' }, @@ -1991,6 +2121,10 @@ "Add a legacy CBFS master header\n" " remove [-r image,regions] -n NAME " "Remove a component\n" + " configure-get -n var " + "Get a value from the Coreboot Control Block\n" + " configure -n var -V value " + "Set a value in the Coreboot Control Block\n" " compact -r image,regions " "Defragment CBFS image.\n" " copy -r image,regions -R source-region " @@ -2299,6 +2433,9 @@ if (decode_mmap_arg(optarg)) return 1; break; + case 'V': + param.value = optarg; + break; case 'h': case '?': usage(argv[0]);