From 06c3b8bc3be6ec960aa9cfa7b6e69d5df981b4bb Mon Sep 17 00:00:00 2001 From: Lean Sheng Tan Date: Thu, 26 Dec 2024 21:46:08 +0100 Subject: [PATCH 01/11] Fix up CFR's open issues Fix some typos and also update the naming convention of `CFR_OPTFLAG_GRAYOUT` to `CFR_OPTFLAG_INACTIVE` as per reviews. Signed-off-by: Lean Sheng Tan Change-Id: Id66808382b93e32c58024462c18b20c2a89d6d23 Reviewed-on: https://review.coreboot.org/c/coreboot/+/85780 Tested-by: build bot (Jenkins) Reviewed-by: Angel Pons Reviewed-by: Christian Walter --- Documentation/drivers/cfr.md | 6 +++--- src/commonlib/include/commonlib/cfr.h | 4 ++-- src/drivers/option/cfr.c | 11 ++++------- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/Documentation/drivers/cfr.md b/Documentation/drivers/cfr.md index ade6d2b14a3..0405f5c58c7 100644 --- a/Documentation/drivers/cfr.md +++ b/Documentation/drivers/cfr.md @@ -26,7 +26,7 @@ visible name, a help text, a default value and status flags. All strings are in ASCII. The boot options are grouped into forms, where each form hold -one ore more options. Boot options that are not used in the current +one or more options. Boot options that are not used in the current boot flow, and are never reachable should be marked as hidden. Dependecies between options can be defined in the code and should be evaluated by the CFR parser/UI. @@ -66,7 +66,7 @@ The public API can be found in ## Implementation design ### Tags Tags identify the structure defined in `src/commonlib/include/commonlib/cfr.h`. -Every struct might be immideatly followed by additional structs (so called +Every struct might be immediately followed by additional structs (so called sub nodes), having their own tag and size field. The sum of all sub nodes size fields plus the size of the struct itself equals the size field. @@ -208,7 +208,7 @@ effect on the non-volatile variable. Prevents writes to the variable. -* `CFR_OPTFLAG_GRAYOUT` +* `CFR_OPTFLAG_INACTIVE` Implies `READONLY`. The option is visible, but cannot be modified because one of the dependencies are not given. However there's a diff --git a/src/commonlib/include/commonlib/cfr.h b/src/commonlib/include/commonlib/cfr.h index 22058e96f91..cc8431a2db5 100644 --- a/src/commonlib/include/commonlib/cfr.h +++ b/src/commonlib/include/commonlib/cfr.h @@ -68,7 +68,7 @@ enum cfr_tags { * effect on the non-volatile variable. * CFR_OPTFLAG_READONLY: * Prevents writes to the variable. - * CFR_OPTFLAG_GRAYOUT: + * CFR_OPTFLAG_INACTIVE: * Implies READONLY. The option is visible, but cannot be modified * because one of the dependencies are not given. However there's a * possibility to enable the option by changing runtime configuration. @@ -93,7 +93,7 @@ enum cfr_tags { */ enum cfr_option_flags { CFR_OPTFLAG_READONLY = 1 << 0, - CFR_OPTFLAG_GRAYOUT = 1 << 1, + CFR_OPTFLAG_INACTIVE = 1 << 1, CFR_OPTFLAG_SUPPRESS = 1 << 2, CFR_OPTFLAG_VOLATILE = 1 << 3, CFR_OPTFLAG_RUNTIME = 1 << 4, diff --git a/src/drivers/option/cfr.c b/src/drivers/option/cfr.c index b323b4318a7..e833d7bdba0 100644 --- a/src/drivers/option/cfr.c +++ b/src/drivers/option/cfr.c @@ -29,9 +29,6 @@ static uint32_t cfr_record_size(const char *startp, const char *endp) static uint32_t write_cfr_varchar(char *current, const char *string, uint32_t tag) { - uint8_t *data; - size_t padding; - ASSERT(string); if (!string) return 0; @@ -98,7 +95,7 @@ static uint32_t write_numeric_option(char *current, uint32_t tag, const uint64_t option->object_id = object_id; option->dependency_id = dep_id; option->flags = flags; - if (option->flags & (CFR_OPTFLAG_GRAYOUT | CFR_OPTFLAG_VOLATILE)) + if (option->flags & (CFR_OPTFLAG_INACTIVE | CFR_OPTFLAG_VOLATILE)) option->flags |= CFR_OPTFLAG_READONLY; option->default_value = default_value; option->size = sizeof(*option); @@ -163,7 +160,7 @@ static uint32_t sm_write_opt_varchar(char *current, const struct sm_obj_varchar option->object_id = object_id; option->dependency_id = dep_id; option->flags = sm_varchar->flags; - if (option->flags & (CFR_OPTFLAG_GRAYOUT | CFR_OPTFLAG_VOLATILE)) + if (option->flags & (CFR_OPTFLAG_INACTIVE | CFR_OPTFLAG_VOLATILE)) option->flags |= CFR_OPTFLAG_READONLY; option->size = sizeof(*option); @@ -193,7 +190,7 @@ static uint32_t sm_write_opt_comment(char *current, const struct sm_obj_comment comment->object_id = object_id; comment->dependency_id = dep_id; comment->flags = sm_comment->flags; - if (comment->flags & (CFR_OPTFLAG_GRAYOUT | CFR_OPTFLAG_VOLATILE)) + if (comment->flags & (CFR_OPTFLAG_INACTIVE | CFR_OPTFLAG_VOLATILE)) comment->flags |= CFR_OPTFLAG_READONLY; comment->size = sizeof(*comment); @@ -228,7 +225,7 @@ static uint32_t sm_write_form(char *current, struct sm_obj_form *sm_form, form->object_id = object_id; form->dependency_id = dep_id; form->flags = sm_form->flags; - if (form->flags & (CFR_OPTFLAG_GRAYOUT | CFR_OPTFLAG_VOLATILE)) + if (form->flags & (CFR_OPTFLAG_INACTIVE | CFR_OPTFLAG_VOLATILE)) form->flags |= CFR_OPTFLAG_READONLY; form->size = sizeof(*form); From 7a6e0e47c50760a2613e1a54f7c70236eb31ed49 Mon Sep 17 00:00:00 2001 From: Filip Brozovic Date: Tue, 21 Jan 2025 11:59:11 +0100 Subject: [PATCH 02/11] CFR: Add version field to root struct Add a version field to the CFR root struct so parsers can check compatibility when parsing structs. Change-Id: Ifcb950f1bdedc0ab925f3841befb7e7001c0f7f4 Signed-off-by: Filip Brozovic Reviewed-on: https://review.coreboot.org/c/coreboot/+/86080 Tested-by: build bot (Jenkins) Reviewed-by: Matt DeVillier Reviewed-by: Angel Pons --- src/commonlib/include/commonlib/cfr.h | 2 ++ src/commonlib/include/commonlib/coreboot_tables.h | 1 + src/drivers/option/cfr.c | 1 + 3 files changed, 4 insertions(+) diff --git a/src/commonlib/include/commonlib/cfr.h b/src/commonlib/include/commonlib/cfr.h index cc8431a2db5..5d8b37bf56b 100644 --- a/src/commonlib/include/commonlib/cfr.h +++ b/src/commonlib/include/commonlib/cfr.h @@ -49,6 +49,8 @@ * */ +#define CFR_VERSION 0x00000000 + enum cfr_tags { CFR_TAG_OPTION_FORM = 1, CFR_TAG_ENUM_VALUE = 2, diff --git a/src/commonlib/include/commonlib/coreboot_tables.h b/src/commonlib/include/commonlib/coreboot_tables.h index 6740781603d..0d42b50783d 100644 --- a/src/commonlib/include/commonlib/coreboot_tables.h +++ b/src/commonlib/include/commonlib/coreboot_tables.h @@ -603,6 +603,7 @@ struct lb_efi_fw_info { struct lb_cfr { uint32_t tag; uint32_t size; + uint32_t version; uint32_t checksum; /* Checksum of the variable payload. */ /* struct lb_cfr_option_form forms[] */ }; diff --git a/src/drivers/option/cfr.c b/src/drivers/option/cfr.c index e833d7bdba0..15c4fd9b4ed 100644 --- a/src/drivers/option/cfr.c +++ b/src/drivers/option/cfr.c @@ -307,6 +307,7 @@ void cfr_write_setup_menu(struct lb_cfr *cfr_root, struct sm_obj_form *sm_root[] cfr_root->tag = LB_TAG_CFR_ROOT; cfr_root->size = sizeof(*cfr_root); + cfr_root->version = CFR_VERSION; current += cfr_root->size; while (sm_root && sm_root[i]) From 721963bd0cef97275ecdfd47884f96c9c4805a7e Mon Sep 17 00:00:00 2001 From: Filip Brozovic Date: Tue, 14 Jan 2025 22:42:41 +0100 Subject: [PATCH 03/11] CFR: add dependencies based on specific option values Implements a way for CFR options to depend on another option being set to one or more specific values. This is achieved by writing a list of values as a varbinary struct. Change-Id: Iaf7965551490969052eb27c207fa524470d4dd6a Signed-off-by: Filip Brozovic Reviewed-on: https://review.coreboot.org/c/coreboot/+/85987 Reviewed-by: Angel Pons Reviewed-by: Matt DeVillier Reviewed-by: Sean Rhodes Tested-by: build bot (Jenkins) --- Documentation/drivers/cfr_internal.md | 36 ++++++++++++- src/commonlib/include/commonlib/cfr.h | 8 ++- src/drivers/option/cfr.c | 78 ++++++++++++++++++++------- src/drivers/option/cfr_frontend.h | 24 ++++++--- 4 files changed, 117 insertions(+), 29 deletions(-) diff --git a/Documentation/drivers/cfr_internal.md b/Documentation/drivers/cfr_internal.md index 95fef66eee5..b2355d7b62b 100644 --- a/Documentation/drivers/cfr_internal.md +++ b/Documentation/drivers/cfr_internal.md @@ -50,8 +50,9 @@ static const struct sm_object serial_number = SM_DECLARE_VARCHAR({ The CFR options can have a dependency that must be evaluated at runtime by the OS/payload that parses the CFR record and displays the UI. -By using the `WITH_DEP()` macro you can specify another numberic option that -is checked to hide the current option. +By using the `WITH_DEP()` macro you can specify another numeric option that +is checked to hide the current option. The `WITH_DEP_VALUES()` macro allows +specifying one or more values that cause the dependent option to be displayed. **Example:** Declares a dependency from `sata_disable_port0` to `sata_enable`. The option `sata_disable_port0` will be hidden as long as "sata_enable" is 0. @@ -76,6 +77,37 @@ static struct sm_object sata_disable_port0 = SM_DECLARE_BOOL({ }, WITH_DEP(&sata_enable)); ``` +**Example:** Declares a dependency from `com1_termination` to `com1_mode`. +The option `com1_termination` will only be shown if `com1_mode` is set to RS-485. + +``` +#define COM_MODE_DISABLED 3 +#define COM_MODE_RS232 0 +#define COM_MODE_RS485 1 + +static struct sm_object com1_mode = SM_DECLARE_ENUM({ + .flags = CFR_OPTFLAG_RUNTIME, + .opt_name = "com1_mode", + .ui_name = "COM1 Mode", + .ui_helptext = NULL, + .default_value = 1, + .values = (const struct sm_enum_value[]) { + { "Disabled", COM_MODE_DISABLED }, + { "RS-232", COM_MODE_RS232 }, + { "RS-485", COM_MODE_RS485 }, + SM_ENUM_VALUE_END }, +}); + +static struct sm_object com1_termination = SM_DECLARE_BOOL({ + .flags = CFR_OPTFLAG_RUNTIME, + .opt_name = "com1_termination", + .ui_name = "Enable COM1 termination resistors", + .ui_helptext = NULL, + .default_value = false, +}, WITH_DEP_VALUES(&com1_mode, COM_MODE_RS485)); + +``` + ### Providing mainboard custom options A mainboard that uses CFR can provide a list of custom options diff --git a/src/commonlib/include/commonlib/cfr.h b/src/commonlib/include/commonlib/cfr.h index 5d8b37bf56b..570ce3c2d18 100644 --- a/src/commonlib/include/commonlib/cfr.h +++ b/src/commonlib/include/commonlib/cfr.h @@ -63,6 +63,7 @@ enum cfr_tags { CFR_TAG_VARCHAR_UI_HELPTEXT = 9, CFR_TAG_VARCHAR_DEF_VALUE = 10, CFR_TAG_OPTION_COMMENT = 11, + CFR_TAG_DEP_VALUES = 12, }; /* @@ -104,7 +105,8 @@ enum cfr_option_flags { struct __packed lb_cfr_varbinary { uint32_t tag; /* * CFR_TAG_VARCHAR_OPT_NAME, CFR_TAG_VARCHAR_UI_NAME, - * CFR_TAG_VARCHAR_UI_HELPTEXT or CFR_TAG_VARCHAR_DEF_VALUE + * CFR_TAG_VARCHAR_UI_HELPTEXT, CFR_TAG_VARCHAR_DEF_VALUE + * or CFR_TAG_DEP_VALUES */ uint32_t size; /* Length of the entire structure */ uint32_t data_length; /* Length of data, including NULL terminator for strings */ @@ -136,6 +138,7 @@ struct __packed lb_cfr_numeric_option { * struct lb_cfr_varbinary opt_name * struct lb_cfr_varbinary ui_name * struct lb_cfr_varbinary ui_helptext (Optional) + * struct lb_cfr_varbinary dependency_values (Optional) * struct lb_cfr_enum_value enum_values[] */ }; @@ -153,6 +156,7 @@ struct __packed lb_cfr_varchar_option { * struct lb_cfr_varbinary opt_name * struct lb_cfr_varbinary ui_name * struct lb_cfr_varbinary ui_helptext (Optional) + * struct lb_cfr_varbinary dependency_values (Optional) */ }; @@ -172,6 +176,7 @@ struct __packed lb_cfr_option_comment { /* * struct lb_cfr_varbinary ui_name * struct lb_cfr_varbinary ui_helptext (Optional) + * struct lb_cfr_varbinary dependency_values (Optional) */ }; @@ -186,6 +191,7 @@ struct __packed lb_cfr_option_form { uint32_t flags; /* enum cfr_option_flags */ /* * struct lb_cfr_varbinary ui_name + * struct lb_cfr_varbinary dependency_values (Optional) * struct lb_cfr_varchar_option options[] */ }; diff --git a/src/drivers/option/cfr.c b/src/drivers/option/cfr.c index 15c4fd9b4ed..c439ed9546a 100644 --- a/src/drivers/option/cfr.c +++ b/src/drivers/option/cfr.c @@ -69,6 +69,25 @@ static uint32_t sm_write_ui_helptext(char *current, const char *string) return write_cfr_varchar(current, string, CFR_TAG_VARCHAR_UI_HELPTEXT); } +static uint32_t sm_write_dep_values(char *current, + const uint32_t *dep_values, const uint32_t num_dep_values) +{ + /* Dependency values are optional */ + if (!dep_values || !num_dep_values) + return 0; + + struct lb_cfr_varbinary *cfr_values = (struct lb_cfr_varbinary *)current; + cfr_values->tag = CFR_TAG_DEP_VALUES; + cfr_values->data_length = sizeof(*dep_values) * num_dep_values; + char *data = current + sizeof(*cfr_values); + memcpy(data, dep_values, cfr_values->data_length); + + /* Make sure that every TAG/SIZE field is always aligned to LB_ENTRY_ALIGN */ + cfr_values->size = ALIGN_UP(sizeof(*cfr_values) + cfr_values->data_length, LB_ENTRY_ALIGN); + + return cfr_values->size; +} + static uint32_t sm_write_enum_value(char *current, const struct sm_enum_value *e) { struct lb_cfr_enum_value *enum_val = (struct lb_cfr_enum_value *)current; @@ -86,7 +105,7 @@ static uint32_t sm_write_enum_value(char *current, const struct sm_enum_value *e static uint32_t write_numeric_option(char *current, uint32_t tag, const uint64_t object_id, const char *opt_name, const char *ui_name, const char *ui_helptext, uint32_t flags, uint32_t default_value, const struct sm_enum_value *values, - const uint64_t dep_id) + const uint64_t dep_id, const uint32_t *dep_values, const uint32_t num_dep_values) { struct lb_cfr_numeric_option *option = (struct lb_cfr_numeric_option *)current; size_t len; @@ -110,6 +129,7 @@ static uint32_t write_numeric_option(char *current, uint32_t tag, const uint64_t return 0; current += len; current += sm_write_ui_helptext(current, ui_helptext); + current += sm_write_dep_values(current, dep_values, num_dep_values); if (option->tag == CFR_TAG_OPTION_ENUM && values) { for (const struct sm_enum_value *e = values; e->ui_name; e++) { @@ -122,35 +142,41 @@ static uint32_t write_numeric_option(char *current, uint32_t tag, const uint64_t } static uint32_t sm_write_opt_enum(char *current, const struct sm_obj_enum *sm_enum, - const uint64_t object_id, const uint64_t dep_id) + const uint64_t object_id, const uint64_t dep_id, + const uint32_t *dep_values, const uint32_t num_dep_values) { return write_numeric_option(current, CFR_TAG_OPTION_ENUM, object_id, sm_enum->opt_name, sm_enum->ui_name, sm_enum->ui_helptext, sm_enum->flags, sm_enum->default_value, sm_enum->values, - dep_id); + dep_id, dep_values, num_dep_values); } static uint32_t sm_write_opt_number(char *current, const struct sm_obj_number *sm_number, - const uint64_t object_id, const uint64_t dep_id) + const uint64_t object_id, const uint64_t dep_id, + const uint32_t *dep_values, const uint32_t num_dep_values) { return write_numeric_option(current, CFR_TAG_OPTION_NUMBER, object_id, sm_number->opt_name, sm_number->ui_name, sm_number->ui_helptext, - sm_number->flags, sm_number->default_value, NULL, dep_id); + sm_number->flags, sm_number->default_value, NULL, dep_id, + dep_values, num_dep_values); } static uint32_t sm_write_opt_bool(char *current, const struct sm_obj_bool *sm_bool, - const uint64_t object_id, const uint64_t dep_id) + const uint64_t object_id, const uint64_t dep_id, + const uint32_t *dep_values, const uint32_t num_dep_values) { return write_numeric_option(current, CFR_TAG_OPTION_BOOL, object_id, sm_bool->opt_name, sm_bool->ui_name, sm_bool->ui_helptext, - sm_bool->flags, sm_bool->default_value, NULL, dep_id); + sm_bool->flags, sm_bool->default_value, NULL, dep_id, + dep_values, num_dep_values); } static uint32_t sm_write_opt_varchar(char *current, const struct sm_obj_varchar *sm_varchar, - const uint64_t object_id, const uint64_t dep_id) + const uint64_t object_id, const uint64_t dep_id, + const uint32_t *dep_values, const uint32_t num_dep_values) { struct lb_cfr_varchar_option *option = (struct lb_cfr_varchar_option *)current; @@ -175,13 +201,15 @@ static uint32_t sm_write_opt_varchar(char *current, const struct sm_obj_varchar return 0; current += len; current += sm_write_ui_helptext(current, sm_varchar->ui_helptext); + current += sm_write_dep_values(current, dep_values, num_dep_values); option->size = cfr_record_size((char *)option, current); return option->size; } static uint32_t sm_write_opt_comment(char *current, const struct sm_obj_comment *sm_comment, - const uint32_t object_id, const uint32_t dep_id) + const uint32_t object_id, const uint32_t dep_id, + const uint32_t *dep_values, const uint32_t num_dep_values) { struct lb_cfr_option_comment *comment = (struct lb_cfr_option_comment *)current; size_t len; @@ -200,6 +228,7 @@ static uint32_t sm_write_opt_comment(char *current, const struct sm_obj_comment return 0; current += len; current += sm_write_ui_helptext(current, sm_comment->ui_helptext); + current += sm_write_dep_values(current, dep_values, num_dep_values); comment->size = cfr_record_size((char *)comment, current); return comment->size; @@ -215,7 +244,8 @@ static uint64_t sm_gen_obj_id(void *ptr) static uint32_t sm_write_object(char *current, const struct sm_object *sm_obj); static uint32_t sm_write_form(char *current, struct sm_obj_form *sm_form, - const uint64_t object_id, const uint64_t dep_id) + const uint64_t object_id, const uint64_t dep_id, + const uint32_t *dep_values, const uint32_t num_dep_values) { struct lb_cfr_option_form *form = (struct lb_cfr_option_form *)current; size_t len; @@ -234,6 +264,7 @@ static uint32_t sm_write_form(char *current, struct sm_obj_form *sm_form, if (!len) return 0; current += len; + current += sm_write_dep_values(current, dep_values, num_dep_values); while (sm_form->obj_list[i]) current += sm_write_object(current, sm_form->obj_list[i++]); @@ -245,6 +276,8 @@ static uint32_t sm_write_form(char *current, struct sm_obj_form *sm_form, static uint32_t sm_write_object(char *current, const struct sm_object *sm_obj) { uint64_t dep_id, obj_id; + const uint32_t *dep_values; + uint32_t num_dep_values; struct sm_object sm_obj_copy; assert(sm_obj); @@ -253,10 +286,14 @@ static uint32_t sm_write_object(char *current, const struct sm_object *sm_obj) /* Set dependency ID */ dep_id = 0; + dep_values = NULL; + num_dep_values = 0; if (sm_obj->dep) { - assert(sm_obj->dep->kind == SM_OBJ_BOOL); - if (sm_obj->dep->kind == SM_OBJ_BOOL) + if (sm_obj->dep->kind == SM_OBJ_BOOL || sm_obj->dep->kind == SM_OBJ_ENUM) { dep_id = sm_gen_obj_id((void *)sm_obj->dep); + dep_values = sm_obj->dep_values; + num_dep_values = sm_obj->num_dep_values; + } } /* Invoke callback to update fields */ @@ -273,21 +310,22 @@ static uint32_t sm_write_object(char *current, const struct sm_object *sm_obj) return 0; case SM_OBJ_ENUM: return sm_write_opt_enum(current, &sm_obj->sm_enum, obj_id, - dep_id); + dep_id, dep_values, num_dep_values); case SM_OBJ_NUMBER: return sm_write_opt_number(current, &sm_obj->sm_number, obj_id, - dep_id); + dep_id, dep_values, num_dep_values); case SM_OBJ_BOOL: return sm_write_opt_bool(current, &sm_obj->sm_bool, obj_id, - dep_id); + dep_id, dep_values, num_dep_values); case SM_OBJ_VARCHAR: return sm_write_opt_varchar(current, &sm_obj->sm_varchar, obj_id, - dep_id); + dep_id, dep_values, num_dep_values); case SM_OBJ_COMMENT: return sm_write_opt_comment(current, &sm_obj->sm_comment, obj_id, - dep_id); + dep_id, dep_values, num_dep_values); case SM_OBJ_FORM: - return sm_write_form(current, (struct sm_obj_form *)&sm_obj->sm_form, obj_id, dep_id); + return sm_write_form(current, (struct sm_obj_form *)&sm_obj->sm_form, obj_id, + dep_id, dep_values, num_dep_values); default: BUG(); printk(BIOS_ERR, "Unknown setup menu object kind %u, ignoring\n", sm_obj->kind); @@ -311,13 +349,13 @@ void cfr_write_setup_menu(struct lb_cfr *cfr_root, struct sm_obj_form *sm_root[] current += cfr_root->size; while (sm_root && sm_root[i]) - current += sm_write_form(current, sm_root[i++], 0, 0); + current += sm_write_form(current, sm_root[i++], 0, 0, NULL, 0); /* * Add generic forms. */ for (obj = &_cfr_forms[0]; obj != &_ecfr_forms[0]; obj++) - current += sm_write_form(current, obj, 0, 0); + current += sm_write_form(current, obj, 0, 0, NULL, 0); cfr_root->size = cfr_record_size((char *)cfr_root, current); diff --git a/src/drivers/option/cfr_frontend.h b/src/drivers/option/cfr_frontend.h index 2161853f010..21c18e779ff 100644 --- a/src/drivers/option/cfr_frontend.h +++ b/src/drivers/option/cfr_frontend.h @@ -75,6 +75,8 @@ enum sm_object_kind { struct sm_object { enum sm_object_kind kind; const struct sm_object *dep; + const uint32_t *dep_values; + const uint32_t num_dep_values; void (*ctor)(const struct sm_object *obj, struct sm_object *new); /* Called on object creation */ union { struct sm_obj_enum sm_enum; @@ -87,21 +89,31 @@ struct sm_object { }; /* sm_object helpers with type checking */ -#define SM_DECLARE_ENUM(...) { .kind = SM_OBJ_ENUM, .dep = NULL, \ +#define SM_DECLARE_ENUM(...) { .kind = SM_OBJ_ENUM, .dep = NULL, \ + .dep_values = NULL, .num_dep_values = 0, \ .ctor = NULL, .sm_enum = __VA_ARGS__ } -#define SM_DECLARE_NUMBER(...) { .kind = SM_OBJ_NUMBER, .dep = NULL, \ +#define SM_DECLARE_NUMBER(...) { .kind = SM_OBJ_NUMBER, .dep = NULL, \ + .dep_values = NULL, .num_dep_values = 0, \ .ctor = NULL, .sm_number = __VA_ARGS__ } -#define SM_DECLARE_BOOL(...) { .kind = SM_OBJ_BOOL, .dep = NULL, \ +#define SM_DECLARE_BOOL(...) { .kind = SM_OBJ_BOOL, .dep = NULL, \ + .dep_values = NULL, .num_dep_values = 0, \ .ctor = NULL, .sm_bool = __VA_ARGS__ } -#define SM_DECLARE_VARCHAR(...) { .kind = SM_OBJ_VARCHAR, .dep = NULL, \ +#define SM_DECLARE_VARCHAR(...) { .kind = SM_OBJ_VARCHAR, .dep = NULL, \ + .dep_values = NULL, .num_dep_values = 0, \ .ctor = NULL, .sm_varchar = __VA_ARGS__ } -#define SM_DECLARE_COMMENT(...) { .kind = SM_OBJ_COMMENT, .dep = NULL, \ +#define SM_DECLARE_COMMENT(...) { .kind = SM_OBJ_COMMENT, .dep = NULL, \ + .dep_values = NULL, .num_dep_values = 0, \ .ctor = NULL, .sm_comment = __VA_ARGS__ } -#define SM_DECLARE_FORM(...) { .kind = SM_OBJ_FORM, .dep = NULL, \ +#define SM_DECLARE_FORM(...) { .kind = SM_OBJ_FORM, .dep = NULL, \ + .dep_values = NULL, .num_dep_values = 0, \ .ctor = NULL, .sm_form = __VA_ARGS__ } #define WITH_CALLBACK(c) .ctor = (c) #define WITH_DEP(d) .dep = (d) +#define WITH_DEP_VALUES(d, ...) \ + .dep = (d), \ + .dep_values = ((const uint32_t[]) { __VA_ARGS__ }), \ + .num_dep_values = sizeof((uint32_t[]) { __VA_ARGS__ }) / sizeof(uint32_t) void cfr_write_setup_menu(struct lb_cfr *cfr_root, struct sm_obj_form *sm_root[]); From 32d9e9c9e32f1a229f8bcbe8b513e64ad46b3144 Mon Sep 17 00:00:00 2001 From: Filip Brozovic Date: Tue, 21 Jan 2025 12:02:10 +0100 Subject: [PATCH 04/11] CFR: Add min/max/step values and hex display flag for number options This commit adds support for minimum/maximum limit values as well as step sizes for CFR number options. Additionally, add a new flag that specifies the option should be displayed in hexadecimal notation instead of decimal. Change-Id: I2e70f1430fb1911f1ad974832f8abfe76f928ac3 Signed-off-by: Filip Brozovic Reviewed-on: https://review.coreboot.org/c/coreboot/+/86039 Tested-by: build bot (Jenkins) Reviewed-by: Angel Pons --- src/commonlib/include/commonlib/cfr.h | 14 ++++++++++++++ src/drivers/option/cfr.c | 18 ++++++++++++------ src/drivers/option/cfr_frontend.h | 4 ++++ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/commonlib/include/commonlib/cfr.h b/src/commonlib/include/commonlib/cfr.h index 570ce3c2d18..af68269e297 100644 --- a/src/commonlib/include/commonlib/cfr.h +++ b/src/commonlib/include/commonlib/cfr.h @@ -121,6 +121,15 @@ struct __packed lb_cfr_enum_value { */ }; +/* + * The optional flags describe how a numeric option is to be displayed. + * CFR_NUM_OPT_DISPFLAG_HEX: + * Displays a NUMBER option in hexadecimal instead of decimal notation. + */ +enum cfr_numeric_option_display_flags { + CFR_NUM_OPT_DISPFLAG_HEX = 1 << 0, +}; + /* Supports multiple option types: ENUM, NUMBER, BOOL */ struct __packed lb_cfr_numeric_option { uint32_t tag; /* @@ -134,6 +143,11 @@ struct __packed lb_cfr_numeric_option { */ uint32_t flags; /* enum cfr_option_flags */ uint32_t default_value; + uint32_t min; + uint32_t max; + uint32_t step; + uint32_t display_flags; /* enum cfr_numeric_option_display_flags */ + /* * struct lb_cfr_varbinary opt_name * struct lb_cfr_varbinary ui_name diff --git a/src/drivers/option/cfr.c b/src/drivers/option/cfr.c index c439ed9546a..26bdd55f4d2 100644 --- a/src/drivers/option/cfr.c +++ b/src/drivers/option/cfr.c @@ -104,8 +104,9 @@ static uint32_t sm_write_enum_value(char *current, const struct sm_enum_value *e static uint32_t write_numeric_option(char *current, uint32_t tag, const uint64_t object_id, const char *opt_name, const char *ui_name, const char *ui_helptext, - uint32_t flags, uint32_t default_value, const struct sm_enum_value *values, - const uint64_t dep_id, const uint32_t *dep_values, const uint32_t num_dep_values) + uint32_t flags, uint32_t default_value, uint32_t min, uint32_t max, uint32_t step, + uint32_t display_flags, const struct sm_enum_value *values, const uint64_t dep_id, + const uint32_t *dep_values, const uint32_t num_dep_values) { struct lb_cfr_numeric_option *option = (struct lb_cfr_numeric_option *)current; size_t len; @@ -117,6 +118,10 @@ static uint32_t write_numeric_option(char *current, uint32_t tag, const uint64_t if (option->flags & (CFR_OPTFLAG_INACTIVE | CFR_OPTFLAG_VOLATILE)) option->flags |= CFR_OPTFLAG_READONLY; option->default_value = default_value; + option->min = (min <= max) ? min : 0; + option->max = (min == 0 && max == 0) ? UINT32_MAX : max; + option->step = step; + option->display_flags = display_flags; option->size = sizeof(*option); current += option->size; @@ -148,7 +153,7 @@ static uint32_t sm_write_opt_enum(char *current, const struct sm_obj_enum *sm_en { return write_numeric_option(current, CFR_TAG_OPTION_ENUM, object_id, sm_enum->opt_name, sm_enum->ui_name, sm_enum->ui_helptext, - sm_enum->flags, sm_enum->default_value, sm_enum->values, + sm_enum->flags, sm_enum->default_value, 0, 0, 0, 0, sm_enum->values, dep_id, dep_values, num_dep_values); } @@ -159,8 +164,9 @@ static uint32_t sm_write_opt_number(char *current, const struct sm_obj_number *s { return write_numeric_option(current, CFR_TAG_OPTION_NUMBER, object_id, sm_number->opt_name, sm_number->ui_name, sm_number->ui_helptext, - sm_number->flags, sm_number->default_value, NULL, dep_id, - dep_values, num_dep_values); + sm_number->flags, sm_number->default_value, sm_number->min, sm_number->max, + sm_number->step, sm_number->display_flags, NULL, dep_id, dep_values, + num_dep_values); } static uint32_t sm_write_opt_bool(char *current, const struct sm_obj_bool *sm_bool, @@ -170,7 +176,7 @@ static uint32_t sm_write_opt_bool(char *current, const struct sm_obj_bool *sm_bo { return write_numeric_option(current, CFR_TAG_OPTION_BOOL, object_id, sm_bool->opt_name, sm_bool->ui_name, sm_bool->ui_helptext, - sm_bool->flags, sm_bool->default_value, NULL, dep_id, + sm_bool->flags, sm_bool->default_value, 0, 0, 0, 0, NULL, dep_id, dep_values, num_dep_values); } diff --git a/src/drivers/option/cfr_frontend.h b/src/drivers/option/cfr_frontend.h index 21c18e779ff..17332bdca44 100644 --- a/src/drivers/option/cfr_frontend.h +++ b/src/drivers/option/cfr_frontend.h @@ -30,6 +30,10 @@ struct sm_obj_number { const char *ui_name; const char *ui_helptext; uint32_t default_value; + uint32_t min; + uint32_t max; + uint32_t step; + uint32_t display_flags; /* enum cfr_numeric_option_display_flags */ }; struct sm_obj_bool { From ab4b37b69650f37e88704954b6983ed610674056 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= Date: Sun, 23 Mar 2025 13:58:46 +0100 Subject: [PATCH 05/11] configs/config.lenovo_m900_tiny: add CFR testbed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I749ecf2eb041dfbe2f6f93b5e3a7b2af3c78bb1d Signed-off-by: Michał Kopeć --- configs/config.lenovo_m900_tiny | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 configs/config.lenovo_m900_tiny diff --git a/configs/config.lenovo_m900_tiny b/configs/config.lenovo_m900_tiny new file mode 100644 index 00000000000..62fd6ddc480 --- /dev/null +++ b/configs/config.lenovo_m900_tiny @@ -0,0 +1,31 @@ +CONFIG_VENDOR_LENOVO=y +CONFIG_CBFS_SIZE=0x600000 +CONFIG_BOARD_LENOVO_THINKCENTRE_M900_TINY=y +CONFIG_TPM_MEASURED_BOOT=y +CONFIG_INTEL_ME_DISABLED_HECI=y +CONFIG_DRIVERS_EFI_VARIABLE_STORE=y +CONFIG_DRIVERS_OPTION_CFR=y +CONFIG_TPM2=y +CONFIG_PAYLOAD_EDK2=y +CONFIG_EDK2_REPOSITORY="https://github.com/Dasharo/edk2.git" +CONFIG_EDK2_TAG_OR_REV="origin/cfr_ng" +CONFIG_EDK2_USE_EDK2_PLATFORMS=y +CONFIG_EDK2_PLATFORMS_REPOSITORY="https://github.com/Dasharo/edk2-platforms" +CONFIG_EDK2_PLATFORMS_TAG_OR_REV="3323ed481d35096fb6a7eae7b49f35eff00f86cf" +CONFIG_EDK2_CBMEM_LOGGING=y +CONFIG_EDK2_FOLLOW_BGRT_SPEC=y +CONFIG_EDK2_SERIAL_SUPPORT=y +CONFIG_PXE=y +CONFIG_BUILD_IPXE=y +# CONFIG_IPXE_SERIAL_CONSOLE is not set +CONFIG_EDK2_DASHARO_SYSTEM_FEATURES=y +CONFIG_EDK2_DASHARO_SECURITY_OPTIONS=y +CONFIG_EDK2_DASHARO_USB_CONFIG=y +CONFIG_EDK2_DASHARO_NETWORK_CONFIG=y +CONFIG_EDK2_DASHARO_NETWORK_BOOT_DEFAULT_ENABLE=y +CONFIG_EDK2_DASHARO_SERIAL_REDIRECTION_DEFAULT_ENABLE=y +CONFIG_EDK2_DASHARO_CPU_CONFIG=y +CONFIG_EDK2_HYPERTHREADING_OPTION=y +CONFIG_EDK2_DISABLE_OPTION_ROMS=y +CONFIG_EDK2_ENABLE_FAST_BOOT_FEATURE=y +CONFIG_EDK2_ENABLE_QUIET_BOOT_FEATURE=y From 7c8c89515d6af4d25dd55bdea75dc753fae88e9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= Date: Sun, 23 Mar 2025 13:27:31 +0100 Subject: [PATCH 06/11] [WIP] vc/dasharo: CFR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I123561aa82ac87e105c1a9592e05e1787963e72d Signed-off-by: Michał Kopeć --- src/vendorcode/dasharo/include/dasharo/cfr.h | 105 +++++++++++++++++++ src/vendorcode/dasharo/options.c | 27 +++-- 2 files changed, 126 insertions(+), 6 deletions(-) create mode 100644 src/vendorcode/dasharo/include/dasharo/cfr.h diff --git a/src/vendorcode/dasharo/include/dasharo/cfr.h b/src/vendorcode/dasharo/include/dasharo/cfr.h new file mode 100644 index 00000000000..41e1ba45f35 --- /dev/null +++ b/src/vendorcode/dasharo/include/dasharo/cfr.h @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef DASHARO_CFR_H +#define DASHARO_CFR_H + +#include +#include +#include "options.h" + +struct sm_object lock_bios = SM_DECLARE_BOOL({ + .flags = CFR_OPTFLAG_RUNTIME, + .opt_name = "lock_bios", + .ui_name = "Lock the BIOS boot medium", + .ui_helptext = "This option locks down the BIOS flash", + .default_value = true, +}); + +static void smm_bwp_callback(const struct sm_object *obj, struct sm_object *new) +{ + if (!CONFIG(BOOTMEDIA_SMM_BWP)) + new->sm_bool.flags |= CFR_OPTFLAG_SUPPRESS; +} + +struct sm_object smm_bwp = SM_DECLARE_BOOL({ + .flags = CFR_OPTFLAG_RUNTIME, + .opt_name = "smm_bwp", + .ui_name = "SMM BIOS Write Protection", + .ui_helptext = "This option prevents flash writes outside of SMM", + .default_value = false, +}, WITH_CALLBACK(&smm_bwp_callback)); + +struct sm_object watchdog_enable = SM_DECLARE_BOOL({ + .flags = CFR_OPTFLAG_RUNTIME, + .opt_name = "watchdog_enable", + .ui_name = "Enable watchdog timer", + .ui_helptext = "The watchdog will reset the platform once the timer expires", + .default_value = CONFIG(SOC_INTEL_COMMON_OC_WDT_ENABLE), +}); + +struct sm_object watchdog_timeout = SM_DECLARE_NUMBER({ + .flags = CFR_OPTFLAG_RUNTIME, + .opt_name = "watchdog_timeout", + .ui_name = "Watchdog timeout", + .ui_helptext = "After this timeout expires, the platform will be re-set", + .default_value = CONFIG_SOC_INTEL_COMMON_OC_WDT_TIMEOUT_SECONDS, +}, WITH_DEP(&watchdog_enable)); + +struct sm_object me_mode = SM_DECLARE_ENUM({ + .flags = CFR_OPTFLAG_RUNTIME, + .opt_name = "me_mode", + .ui_name = "Intel ME mode", + .ui_helptext = "Operational mode of Intel Management Engine", + .default_value = CONFIG_INTEL_ME_DEFAULT_STATE, + .values = (const struct sm_enum_value[]) { + { "Enabled", ME_MODE_ENABLE }, + { "Disabled (Soft)", ME_MODE_DISABLE_HECI }, +#if CONFIG(HAVE_INTEL_ME_HAP) + { "Disabled (HAP)", ME_MODE_DISABLE_HAP }, +#endif + SM_ENUM_VALUE_END }, +}); + +static void ps2_enable_callback(const struct sm_object *obj, struct sm_object *new) +{ + if (!CONFIG(EDK2_PS2_SUPPORT)) + new->sm_bool.flags |= CFR_OPTFLAG_SUPPRESS; +} + +struct sm_object ps2_enable = SM_DECLARE_BOOL({ + .flags = CFR_OPTFLAG_RUNTIME, + .opt_name = "ps2_enable", + .ui_name = "Enable PS/2 controller", + .ui_helptext = "Enable or disable the PS/2 controller. Enabling PS/2 slightly increases boot time.", + .default_value = true, +}, WITH_CALLBACK(&ps2_enable_callback)); + +struct sm_object hyper_threading = SM_DECLARE_BOOL({ + .flags = CFR_OPTFLAG_RUNTIME, + .opt_name = "hyper_threading", + .ui_name = "Enable Hyper-Threading", + .ui_helptext = "Enable or disable Hyper-Threading", + .default_value = true, +}); + +struct sm_object throttle_offset = SM_DECLARE_NUMBER({ + .flags = CFR_OPTFLAG_RUNTIME, + .opt_name = "throttle_offset", + .ui_name = "Thermal throttling offset", + .ui_helptext = "Adjust the temperature at which the processor will thermal throttle. " \ + "Lower offset means higher temperature, and vice versa.", + .default_value = CONFIG_EDK2_CPU_THROTTLING_THRESHOLD_DEFAULT, +}); + +static void update_throttling_temp(const struct sm_object *obj, struct sm_object *new) +{ + new->sm_number.default_value = CONFIG_CPU_MAX_TEMPERATURE - get_uint_option("throttle_offset", CONFIG_EDK2_CPU_THROTTLING_THRESHOLD_DEFAULT); +} + +struct sm_object throttle_temp = SM_DECLARE_NUMBER({ + .flags = CFR_OPTFLAG_READONLY | CFR_OPTFLAG_VOLATILE, + .opt_name = "throttle_temp", + .ui_name = "Current thermal throttling temperature", +}, WITH_CALLBACK(update_throttling_temp)); + +#endif // DASHARO_CFG_H diff --git a/src/vendorcode/dasharo/options.c b/src/vendorcode/dasharo/options.c index a4583b574fb..48aa642568a 100644 --- a/src/vendorcode/dasharo/options.c +++ b/src/vendorcode/dasharo/options.c @@ -189,7 +189,9 @@ bool is_vboot_locking_permitted(void) if (CONFIG(DASHARO_FIRMWARE_UPDATE_MODE) && fum) return false; - if (CONFIG(DRIVERS_EFI_VARIABLE_STORE)) + if (CONFIG(DRIVERS_OPTION_CFR)) + lock = get_uint_option("lock_bios", false); + else if (CONFIG(DRIVERS_EFI_VARIABLE_STORE)) read_bool_var("LockBios", &lock); return lock; @@ -265,7 +267,9 @@ uint8_t cse_get_me_disable_mode(void) uint8_t var = CONFIG_INTEL_ME_DEFAULT_STATE; bool fum = false; - if (CONFIG(DRIVERS_EFI_VARIABLE_STORE)) { + if (CONFIG(DRIVERS_OPTION_CFR)) { + var = get_uint_option("me_mode", CONFIG_INTEL_ME_DEFAULT_STATE); + } else if (CONFIG(DRIVERS_EFI_VARIABLE_STORE)) { read_bool_var("FirmwareUpdateMode", &fum); read_u8_var("MeMode", &var); } @@ -320,7 +324,9 @@ bool is_smm_bwp_permitted(void) if (CONFIG(DASHARO_FIRMWARE_UPDATE_MODE) && fum) return false; - if (CONFIG(DRIVERS_EFI_VARIABLE_STORE)) + if (CONFIG(DRIVERS_OPTION_CFR)) + smm_bwp = get_uint_option("smm_bwp", false); + else if (CONFIG(DRIVERS_EFI_VARIABLE_STORE)) read_bool_var("SmmBwp", &smm_bwp); else return CONFIG(BOOTMEDIA_SMM_BWP); @@ -341,9 +347,14 @@ void get_watchdog_config(struct watchdog_config *wdt_cfg) return; size = sizeof(*wdt_cfg); - if (CONFIG(DRIVERS_EFI_VARIABLE_STORE)) + if (CONFIG(DRIVERS_OPTION_CFR)) { + wdt_cfg->wdt_enable = get_uint_option("watchdog_enable", CONFIG(SOC_INTEL_COMMON_OC_WDT_ENABLE)); + wdt_cfg->wdt_timeout = get_uint_option("watchdog_timeout", CONFIG_SOC_INTEL_COMMON_OC_WDT_TIMEOUT_SECONDS); + ret = CB_SUCCESS; + } else if (CONFIG(DRIVERS_EFI_VARIABLE_STORE)) { ret = efi_fv_get_option(&rdev, &dasharo_system_features_guid, "WatchdogConfig", wdt_cfg, &size); + } if (ret != CB_SUCCESS || size != sizeof(*wdt_cfg)) { wdt_cfg->wdt_enable = CONFIG(SOC_INTEL_COMMON_OC_WDT_ENABLE); @@ -355,7 +366,9 @@ bool get_ps2_option(void) { bool ps2_en = true; - if (CONFIG(DRIVERS_EFI_VARIABLE_STORE)) + if (CONFIG(DRIVERS_OPTION_CFR)) + ps2_en = get_uint_option("ps2_enable", true); + else if (CONFIG(DRIVERS_EFI_VARIABLE_STORE)) read_bool_var("Ps2Controller", &ps2_en); return ps2_en; @@ -530,7 +543,9 @@ uint8_t get_cpu_throttling_offset(uint8_t tcc_offset) { uint8_t offset = tcc_offset; - if (CONFIG(DRIVERS_EFI_VARIABLE_STORE)) + if (CONFIG(DRIVERS_OPTION_CFR)) + offset = get_uint_option("throttle_offset", tcc_offset); + else if (CONFIG(DRIVERS_EFI_VARIABLE_STORE)) read_u8_var("CpuThrottlingOffset", &offset); return offset; From 2b17921584008b097c8881097be9842c433f79a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= Date: Sun, 23 Mar 2025 17:15:08 +0100 Subject: [PATCH 07/11] mb/lenovo/m900_tiny: hook up CFR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I3a12f8bcf7b5fd52c0153b29e88d5d3fc55312e3 Signed-off-by: Michał Kopeć --- src/mainboard/lenovo/m900_tiny/Makefile.mk | 1 + src/mainboard/lenovo/m900_tiny/cfr.c | 78 ++++++++++++++++++++++ src/mainboard/lenovo/m900_tiny/ramstage.c | 39 +++++++++-- 3 files changed, 112 insertions(+), 6 deletions(-) create mode 100644 src/mainboard/lenovo/m900_tiny/cfr.c diff --git a/src/mainboard/lenovo/m900_tiny/Makefile.mk b/src/mainboard/lenovo/m900_tiny/Makefile.mk index 44db0910ed2..072d9ed81f3 100644 --- a/src/mainboard/lenovo/m900_tiny/Makefile.mk +++ b/src/mainboard/lenovo/m900_tiny/Makefile.mk @@ -10,4 +10,5 @@ romstage-y += romstage.c ramstage-y += gpio.c ramstage-y += hda_verb.c ramstage-y += ramstage.c +ramstage-y += cfr.c ramstage-$(CONFIG_MAINBOARD_USE_LIBGFXINIT) += gma-mainboard.ads diff --git a/src/mainboard/lenovo/m900_tiny/cfr.c b/src/mainboard/lenovo/m900_tiny/cfr.c new file mode 100644 index 00000000000..2e5bffd8c32 --- /dev/null +++ b/src/mainboard/lenovo/m900_tiny/cfr.c @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include + +struct sm_object wifi_slot_enable = SM_DECLARE_BOOL({ + .flags = CFR_OPTFLAG_RUNTIME, + .opt_name = "wifi_slot_enable", + .ui_name = "Enable Wi-Fi card slot", + .ui_helptext = "Enable or disable detection of devices in the Wi-Fi card slot", + .default_value = true, +}); + +struct sm_object ssd_slot_enable = SM_DECLARE_BOOL({ + .flags = CFR_OPTFLAG_RUNTIME, + .opt_name = "ssd_slot_enable", + .ui_name = "Enable SSD slot", + .ui_helptext = "Enable or disable detection of devices in the SSD slot", + .default_value = true, +}); + +struct sm_object hdd_slot_enable = SM_DECLARE_BOOL({ + .flags = CFR_OPTFLAG_RUNTIME, + .opt_name = "hdd_slot_enable", + .ui_name = "Enable 2.5 inch disk slot", + .ui_helptext = "Enable or disable detection of devices in the 2.5 inch disk slot", + .default_value = true, +}); + +static struct sm_obj_form devices = { + .ui_name = "Devices", + .obj_list = (const struct sm_object *[]) { + &wifi_slot_enable, + &ssd_slot_enable, + &hdd_slot_enable, + NULL + }, +}; + +static struct sm_obj_form security = { + .ui_name = "Security", + .obj_list = (const struct sm_object *[]) { + &smm_bwp, + NULL + }, +}; + +static struct sm_obj_form chipset = { + .ui_name = "Chipset", + .obj_list = (const struct sm_object *[]) { + &me_mode, + &ps2_enable, + NULL + }, +}; + +static struct sm_obj_form processor = { + .ui_name = "Processor", + .obj_list = (const struct sm_object *[]) { + &hyper_threading, + &throttle_offset, + &throttle_temp, + NULL + }, +}; + +static struct sm_obj_form *sm_root[] = { + &security, + &processor, + &chipset, + &devices, + NULL +}; + +void mb_cfr_setup_menu(struct lb_cfr *cfr_root) +{ + cfr_write_setup_menu(cfr_root, sm_root); +} diff --git a/src/mainboard/lenovo/m900_tiny/ramstage.c b/src/mainboard/lenovo/m900_tiny/ramstage.c index 6e66f3a7cc7..d2392cc1faf 100644 --- a/src/mainboard/lenovo/m900_tiny/ramstage.c +++ b/src/mainboard/lenovo/m900_tiny/ramstage.c @@ -2,10 +2,14 @@ #include #include +#include #include #include #include +#include #include +#include +#include static void print_board_id(void) { @@ -32,22 +36,45 @@ static void print_board_id(void) } printk(BIOS_INFO, "Serial header %spopulated\n", !gpio_get(GPP_A22) ? "" : "un"); - printk(BIOS_INFO, "PS/2 header %spopulated\n", !gpio_get(GPP_D14) ? "" : "un"); - printk(BIOS_INFO, "USB header %spopulated\n", !gpio_get(GPP_C19) ? "" : "un"); - printk(BIOS_INFO, "DisplayPort header %spopulated\n", !gpio_get(GPP_B15) ? "" : "un"); - printk(BIOS_INFO, "PCIe / SATA header %spopulated\n", !gpio_get(GPP_B21) ? "" : "un"); } -static void mainboard_enable(struct device *dev) +static void devtree_update(void) +{ + config_t *cfg = config_of_soc(); + struct device *wifi_dev = DEV_PTR(pcie_rp7); + struct device *ssd_dev = DEV_PTR(pcie_rp17); + struct device *ps2_dev = dev_find_slot_pnp(0x2e, NCT6687D_KBC); + + if (get_uint_option("wifi_slot_enable", 1) == 0) { + cfg->usb2_ports[8].enable = 0; + wifi_dev->enabled = 0; + } + + if (get_uint_option("ssd_slot_enable", 1) == 0) { + cfg->SataPortsEnable[4] = 0; + ssd_dev->enabled = 0; + } + + if (get_uint_option("hdd_slot_enable", 1) == 0) { + cfg->SataPortsEnable[0] = 0; + cfg->SataPortsEnable[1] = 0; + } + + if (get_uint_option("ps2_enable", 1) == 0) + ps2_dev->enabled = 0; +} + +static void mainboard_init(void *chip_info) { mainboard_configure_gpios(); + devtree_update(); print_board_id(); } struct chip_operations mainboard_ops = { - .enable_dev = mainboard_enable, + .init = mainboard_init, }; From 97c4e6da560640dc2f2224912836efce0519c49b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= Date: Fri, 28 Mar 2025 12:05:36 +0100 Subject: [PATCH 08/11] CFR: add bootloader options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ib3d1df648e50dc85f432f8c9f14fb685edf6facd Signed-off-by: Michał Kopeć --- src/mainboard/lenovo/m900_tiny/cfr.c | 11 +++++++++ src/vendorcode/dasharo/include/dasharo/cfr.h | 25 ++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/src/mainboard/lenovo/m900_tiny/cfr.c b/src/mainboard/lenovo/m900_tiny/cfr.c index 2e5bffd8c32..fe08f436437 100644 --- a/src/mainboard/lenovo/m900_tiny/cfr.c +++ b/src/mainboard/lenovo/m900_tiny/cfr.c @@ -64,11 +64,22 @@ static struct sm_obj_form processor = { }, }; +static struct sm_obj_form bootloader = { + .ui_name = "Bootloader", + .obj_list = (const struct sm_object *[]) { + &network_boot, + &uefi_usb_stack, + &uefi_usb_msc, + NULL + }, +}; + static struct sm_obj_form *sm_root[] = { &security, &processor, &chipset, &devices, + &bootloader, NULL }; diff --git a/src/vendorcode/dasharo/include/dasharo/cfr.h b/src/vendorcode/dasharo/include/dasharo/cfr.h index 41e1ba45f35..77ad5459cc0 100644 --- a/src/vendorcode/dasharo/include/dasharo/cfr.h +++ b/src/vendorcode/dasharo/include/dasharo/cfr.h @@ -102,4 +102,29 @@ struct sm_object throttle_temp = SM_DECLARE_NUMBER({ .ui_name = "Current thermal throttling temperature", }, WITH_CALLBACK(update_throttling_temp)); + +struct sm_object network_boot = SM_DECLARE_BOOL({ + .flags = CFR_OPTFLAG_RUNTIME, + .opt_name = "network_boot", + .ui_name = "Network Boot", + .ui_helptext = "Enable or disable network boot functionality", + .default_value = CONFIG(EDK2_DASHARO_NETWORK_BOOT_DEFAULT_ENABLE), +}); + +struct sm_object uefi_usb_stack = SM_DECLARE_BOOL({ + .flags = CFR_OPTFLAG_RUNTIME, + .opt_name = "uefi_usb_stack", + .ui_name = "UEFI USB stack", + .ui_helptext = "Enable or disable UEFI USB Stack", + .default_value = true, +}); + +struct sm_object uefi_usb_msc = SM_DECLARE_BOOL({ + .flags = CFR_OPTFLAG_RUNTIME, + .opt_name = "uefi_usb_msc", + .ui_name = "UEFI USB Mass Storage driver", + .ui_helptext = "Enable or disable UEFI USB Mass Storage driver", + .default_value = true, +}, WITH_DEP(&uefi_usb_stack)); + #endif // DASHARO_CFG_H From f4a271827f8fb64c4619f592d281586be96dad86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= Date: Sat, 29 Mar 2025 14:25:11 +0100 Subject: [PATCH 09/11] mb/lenovo/m900_tiny: Enable Vboot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ide2a3a4b59be5b27bf7315690520c9392a98d044 Signed-off-by: Michał Kopeć --- src/mainboard/lenovo/m900_tiny/Kconfig | 11 ++++++ src/mainboard/lenovo/m900_tiny/vboot-ro.fmd | 30 ++++++++++++++++ src/mainboard/lenovo/m900_tiny/vboot-rwa.fmd | 36 ++++++++++++++++++++ 3 files changed, 77 insertions(+) create mode 100644 src/mainboard/lenovo/m900_tiny/vboot-ro.fmd create mode 100644 src/mainboard/lenovo/m900_tiny/vboot-rwa.fmd diff --git a/src/mainboard/lenovo/m900_tiny/Kconfig b/src/mainboard/lenovo/m900_tiny/Kconfig index 8ad36e0014a..334957514b0 100644 --- a/src/mainboard/lenovo/m900_tiny/Kconfig +++ b/src/mainboard/lenovo/m900_tiny/Kconfig @@ -38,4 +38,15 @@ config PRERAM_CBMEM_CONSOLE_SIZE config DIMM_SPD_SIZE default 512 #DDR4 +config VBOOT + select GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC + select GBB_FLAG_DISABLE_FWMP + select GBB_FLAG_DISABLE_LID_SHUTDOWN + select GBB_FLAG_DISABLE_PD_SOFTWARE_SYNC + select HAS_RECOVERY_MRC_CACHE + select VBOOT_VBNV_FLASH + +config FMDFILE + default "src/mainboard/\$(CONFIG_MAINBOARD_DIR)/vboot-rwa.fmd" if VBOOT + endif diff --git a/src/mainboard/lenovo/m900_tiny/vboot-ro.fmd b/src/mainboard/lenovo/m900_tiny/vboot-ro.fmd new file mode 100644 index 00000000000..40855e7c010 --- /dev/null +++ b/src/mainboard/lenovo/m900_tiny/vboot-ro.fmd @@ -0,0 +1,30 @@ +FLASH 16M { + SI_ALL 8M { + SI_DESC 4K + SI_GBE 8K + SI_ME + } + SI_BIOS 8M { + RW_MISC 2M { + UNIFIED_MRC_CACHE(PRESERVE) 128K { + RECOVERY_MRC_CACHE 64K + RW_MRC_CACHE 64K + } + SMMSTORE(PRESERVE) 256K + RW_ELOG(PRESERVE) 16K + RW_SHARED 16K { + SHARED_DATA 8K + VBLOCK_DEV 8K + } + RW_NVRAM(PRESERVE) 24K + } + + WP_RO { + FMAP 2K + RO_FRID 128 + RO_PADDING 1920 + GBB 120K + COREBOOT(CBFS) + } + } +} diff --git a/src/mainboard/lenovo/m900_tiny/vboot-rwa.fmd b/src/mainboard/lenovo/m900_tiny/vboot-rwa.fmd new file mode 100644 index 00000000000..df3bfdb417b --- /dev/null +++ b/src/mainboard/lenovo/m900_tiny/vboot-rwa.fmd @@ -0,0 +1,36 @@ +FLASH 16M { + SI_ALL 8M { + SI_DESC 4K + SI_GBE 8K + SI_ME + } + SI_BIOS 8M { + RW_MISC 2M { + UNIFIED_MRC_CACHE(PRESERVE) 128K { + RECOVERY_MRC_CACHE 64K + RW_MRC_CACHE 64K + } + SMMSTORE(PRESERVE) 256K + RW_ELOG(PRESERVE) 16K + RW_SHARED 16K { + SHARED_DATA 8K + VBLOCK_DEV 8K + } + RW_NVRAM(PRESERVE) 24K + } + + RW_SECTION_A 3M { + VBLOCK_A 8K + FW_MAIN_A(CBFS) + RW_FWID_A 128 + } + + WP_RO 3M { + FMAP 2K + RO_FRID 128 + RO_PADDING 1920 + GBB 120K + COREBOOT(CBFS) + } + } +} From c62dd2c8e9d8f0bf421af96454629ebbb9ade57e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= Date: Sat, 29 Mar 2025 15:25:13 +0100 Subject: [PATCH 10/11] Add power failure state and COM0 CFR options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I486d9faae85f79edb2d025578951ef55817198be Signed-off-by: Michał Kopeć --- src/mainboard/lenovo/m900_tiny/cfr.c | 3 +++ src/vendorcode/dasharo/include/dasharo/cfr.h | 21 ++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/mainboard/lenovo/m900_tiny/cfr.c b/src/mainboard/lenovo/m900_tiny/cfr.c index fe08f436437..9cd0163853a 100644 --- a/src/mainboard/lenovo/m900_tiny/cfr.c +++ b/src/mainboard/lenovo/m900_tiny/cfr.c @@ -40,6 +40,7 @@ static struct sm_obj_form devices = { static struct sm_obj_form security = { .ui_name = "Security", .obj_list = (const struct sm_object *[]) { + &lock_bios, &smm_bwp, NULL }, @@ -50,6 +51,7 @@ static struct sm_obj_form chipset = { .obj_list = (const struct sm_object *[]) { &me_mode, &ps2_enable, + &power_on_after_fail, NULL }, }; @@ -70,6 +72,7 @@ static struct sm_obj_form bootloader = { &network_boot, &uefi_usb_stack, &uefi_usb_msc, + &com0_redirection, NULL }, }; diff --git a/src/vendorcode/dasharo/include/dasharo/cfr.h b/src/vendorcode/dasharo/include/dasharo/cfr.h index 77ad5459cc0..98fd218c9c6 100644 --- a/src/vendorcode/dasharo/include/dasharo/cfr.h +++ b/src/vendorcode/dasharo/include/dasharo/cfr.h @@ -45,6 +45,19 @@ struct sm_object watchdog_timeout = SM_DECLARE_NUMBER({ .default_value = CONFIG_SOC_INTEL_COMMON_OC_WDT_TIMEOUT_SECONDS, }, WITH_DEP(&watchdog_enable)); +struct sm_object power_on_after_fail = SM_DECLARE_ENUM({ + .flags = CFR_OPTFLAG_RUNTIME, + .opt_name = "power_on_after_fail", + .ui_name = "Power state after fail", + .ui_helptext = "State of the platform after external power is restored", + .default_value = CONFIG_MAINBOARD_POWER_FAILURE_STATE, + .values = (const struct sm_enum_value[]) { + { "Off", 0 }, + { "On", 1 }, + { "Previous", 2 }, + SM_ENUM_VALUE_END }, +}); + struct sm_object me_mode = SM_DECLARE_ENUM({ .flags = CFR_OPTFLAG_RUNTIME, .opt_name = "me_mode", @@ -127,4 +140,12 @@ struct sm_object uefi_usb_msc = SM_DECLARE_BOOL({ .default_value = true, }, WITH_DEP(&uefi_usb_stack)); +struct sm_object com0_redirection = SM_DECLARE_BOOL({ + .flags = CFR_OPTFLAG_RUNTIME, + .opt_name = "com0_redirection", + .ui_name = "COM0 Console Redirection", + .ui_helptext = "Enable or disable console on COM0 serial port", + .default_value = true, +}); + #endif // DASHARO_CFG_H From 372a6bf64eb76960ff649331fa73c6489219c7cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= Date: Sat, 29 Mar 2025 20:48:45 +0100 Subject: [PATCH 11/11] configs/config.lenovo_m900_tiny: update, hide dasharo menu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I957a0cbd0dbea20f4408775dde5115cbfa7892e7 Signed-off-by: Michał Kopeć --- configs/config.lenovo_m900_tiny | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/configs/config.lenovo_m900_tiny b/configs/config.lenovo_m900_tiny index 62fd6ddc480..5bc8609d66a 100644 --- a/configs/config.lenovo_m900_tiny +++ b/configs/config.lenovo_m900_tiny @@ -1,11 +1,24 @@ +CONFIG_CCACHE=y CONFIG_VENDOR_LENOVO=y -CONFIG_CBFS_SIZE=0x600000 +CONFIG_VBOOT=y +CONFIG_VBOOT_SLOTS_RW_A=y +CONFIG_VBOOT_NO_BOARD_SUPPORT=y CONFIG_BOARD_LENOVO_THINKCENTRE_M900_TINY=y CONFIG_TPM_MEASURED_BOOT=y CONFIG_INTEL_ME_DISABLED_HECI=y CONFIG_DRIVERS_EFI_VARIABLE_STORE=y CONFIG_DRIVERS_OPTION_CFR=y +CONFIG_CBFS_VERIFICATION=y +CONFIG_VBOOT_CBFS_INTEGRATION=y +CONFIG_VBOOT_MOCK_SECDATA=y +CONFIG_VBOOT_CLEAR_RECOVERY_IN_RAMSTAGE=y CONFIG_TPM2=y +CONFIG_TPM_HASH_SHA256=y +CONFIG_BOOTMEDIA_LOCK_CONTROLLER=y +CONFIG_BOOTMEDIA_LOCK_WPRO_VBOOT_RO=y +CONFIG_BOOTMEDIA_LOCK_IN_VERSTAGE=y +CONFIG_BOOTMEDIA_SMM_BWP=y +CONFIG_DEFAULT_CONSOLE_LOGLEVEL_0=y CONFIG_PAYLOAD_EDK2=y CONFIG_EDK2_REPOSITORY="https://github.com/Dasharo/edk2.git" CONFIG_EDK2_TAG_OR_REV="origin/cfr_ng" @@ -15,11 +28,14 @@ CONFIG_EDK2_PLATFORMS_TAG_OR_REV="3323ed481d35096fb6a7eae7b49f35eff00f86cf" CONFIG_EDK2_CBMEM_LOGGING=y CONFIG_EDK2_FOLLOW_BGRT_SPEC=y CONFIG_EDK2_SERIAL_SUPPORT=y -CONFIG_PXE=y +CONFIG_EDK2_CUSTOM_BUILD_PARAMS="--pcd gDasharoSystemFeaturesTokenSpaceGuid.PcdShowMenu=FALSE" CONFIG_BUILD_IPXE=y -# CONFIG_IPXE_SERIAL_CONSOLE is not set +CONFIG_EDK2_ENABLE_IPXE=y +# CONFIG_EDK2_SECURE_BOOT_DEFAULT_ENABLE is not set +CONFIG_EDK2_PERFORMANCE_MEASUREMENT_ENABLE=y CONFIG_EDK2_DASHARO_SYSTEM_FEATURES=y CONFIG_EDK2_DASHARO_SECURITY_OPTIONS=y +CONFIG_EDK2_DASHARO_INTEL_ME_OPTIONS=y CONFIG_EDK2_DASHARO_USB_CONFIG=y CONFIG_EDK2_DASHARO_NETWORK_CONFIG=y CONFIG_EDK2_DASHARO_NETWORK_BOOT_DEFAULT_ENABLE=y @@ -27,5 +43,7 @@ CONFIG_EDK2_DASHARO_SERIAL_REDIRECTION_DEFAULT_ENABLE=y CONFIG_EDK2_DASHARO_CPU_CONFIG=y CONFIG_EDK2_HYPERTHREADING_OPTION=y CONFIG_EDK2_DISABLE_OPTION_ROMS=y +CONFIG_EDK2_CREATE_PREINSTALLED_BOOT_OPTIONS=y +CONFIG_EDK2_USE_UEFIVAR_BACKED_TPM_PPI=y CONFIG_EDK2_ENABLE_FAST_BOOT_FEATURE=y CONFIG_EDK2_ENABLE_QUIET_BOOT_FEATURE=y