settings->op->applies ( settings, setting ) : 1 );
}
+/**
+ * Find setting applicable to settings block, if any
+ *
+ * @v settings Settings block
+ * @v setting Setting
+ * @ret setting Applicable setting, if any
+ */
+static const struct setting *
+applicable_setting ( struct settings *settings, const struct setting *setting ){
+ const struct setting *applicable;
+
+ /* If setting is already applicable, use it */
+ if ( setting_applies ( settings, setting ) )
+ return setting;
+
+ /* Otherwise, look for a matching predefined setting which does apply */
+ for_each_table_entry ( applicable, SETTINGS ) {
+ if ( ( setting_cmp ( setting, applicable ) == 0 ) &&
+ ( setting_applies ( settings, applicable ) ) )
+ return applicable;
+ }
+
+ return NULL;
+}
+
/**
* Store value of setting
*
/* Find target settings block */
settings = settings_target ( settings );
- /* Fail if tag does not apply to this settings block */
+ /* Fail if setting does not apply to this settings block */
if ( ! setting_applies ( settings, setting ) )
return -ENOTTY;
int fetch_setting ( struct settings *settings, const struct setting *setting,
struct settings **origin, struct setting *fetched,
void *data, size_t len ) {
+ const struct setting *applicable;
struct settings *child;
struct setting tmp;
int ret;
if ( ! settings->op->fetch )
return -ENOTSUP;
- /* Try this block first, if applicable */
- if ( setting_applies ( settings, setting ) ) {
+ /* Try this block first, if an applicable setting exists */
+ if ( ( applicable = applicable_setting ( settings, setting ) ) ) {
/* Create modifiable copy of setting */
- memcpy ( &tmp, setting, sizeof ( tmp ) );
+ memcpy ( &tmp, applicable, sizeof ( tmp ) );
if ( ( ret = settings->op->fetch ( settings, &tmp,
data, len ) ) >= 0 ) {
unsigned int index ) {
struct settings *settings;
struct setting *setting;
+ struct setting *previous = NULL;
unsigned int count = 0;
/* Initialise structure */
/* Include any applicable settings */
for_each_table_entry ( setting, SETTINGS ) {
+
+ /* Skip inapplicable settings */
if ( ! setting_applies ( widget->settings, setting ) )
continue;
- if ( count++ == index ) {
- /* Read current setting value and origin */
+ /* Skip duplicate settings */
+ if ( previous && ( setting_cmp ( setting, previous ) == 0 ) )
+ continue;
+ previous = setting;
+
+ /* Read current setting value and origin */
+ if ( count++ == index ) {
fetchf_setting ( widget->settings, setting,
&widget->row.origin,
&widget->row.setting,
struct efi_ifr_builder *ifr,
unsigned int varstore_id ) {
struct setting *setting;
+ struct setting *previous = NULL;
unsigned int name_id;
unsigned int prompt_id;
unsigned int help_id;
for_each_table_entry ( setting, SETTINGS ) {
if ( ! efi_snp_hii_setting_applies ( snpdev, setting ) )
continue;
+ if ( previous && ( setting_cmp ( setting, previous ) == 0 ) )
+ continue;
+ previous = setting;
name_id = efi_ifr_string ( ifr, "%s", setting->name );
prompt_id = efi_ifr_string ( ifr, "%s", setting->description );
help_id = efi_ifr_string ( ifr, "http://ipxe.org/cfg/%s",