lkml.org 
[lkml]   [2023]   [May]   [5]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    From
    Date
    SubjectRe: [PATCH v11 05/14] HP BIOSCFG driver - ordered-attributes
    On Sun, Apr 23, 2023 at 1:55 AM <thomas@t-8ch.de> wrote:
    >
    > On 2023-04-20 11:54:45-0500, Jorge Lopez wrote:
    > > .../x86/hp/hp-bioscfg/ordered-attributes.c | 563 ++++++++++++++++++
    > > 1 file changed, 563 insertions(+)
    > > create mode 100644 drivers/platform/x86/hp/hp-bioscfg/ordered-attributes.c
    > >
    > > diff --git a/drivers/platform/x86/hp/hp-bioscfg/ordered-attributes.c b/drivers/platform/x86/hp/hp-bioscfg/ordered-attributes.c
    > > new file mode 100644
    > > index 000000000000..5e5d540f728d
    > > --- /dev/null
    > > +++ b/drivers/platform/x86/hp/hp-bioscfg/ordered-attributes.c
    > > @@ -0,0 +1,563 @@
    > > +// SPDX-License-Identifier: GPL-2.0
    > > +/*
    > > + * Functions corresponding to ordered list type attributes under
    > > + * BIOS ORDERED LIST GUID for use with hp-bioscfg driver.
    > > + *
    > > + * Copyright (c) 2022 HP Development Company, L.P.
    > > + */
    > > +
    > > +#include "bioscfg.h"
    > > +
    > > +GET_INSTANCE_ID(ordered_list);
    > > +
    > > +static ssize_t current_value_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
    > > +{
    > > +
    > > + int instance_id = get_ordered_list_instance_id(kobj);
    > > +
    > > + if (instance_id < 0)
    > > + return -EIO;
    > > +
    > > + return sysfs_emit(buf, "%s\n",
    > > + bioscfg_drv.ordered_list_data[instance_id].current_value);
    > > +}
    > > +
    > > +/*
    > > + * validate_ordered_list_value -
    > > + * Validate input of current_value against possible values
    >
    > Does the firmware not also validate this?
    >
    > If so it may be easier to just let it do so and remove the validations
    > from the driver.

    Yes. the firmware validates the data.
    Will remove the validation
    >
    > > + *
    > > + * @instance_id: The instance on which input is validated
    > > + * @buf: Input value
    > > + */
    > > +static int validate_ordered_list_values(int instance_id, const char *buf)
    > > +{
    > > + int ret = 0;
    > > + int found = 0;
    > > + char *new_values = NULL;
    > > + char *value;
    > > + int elem;
    > > + int elem_found = 0;
    > > +
    > > + /* Is it a read only attribute */
    > > + if (bioscfg_drv.ordered_list_data[instance_id].common.is_readonly)
    > > + return -EIO;
    > > +
    > > + new_values = kstrdup(buf, GFP_KERNEL);
    > > +
    > > + /*
    > > + * Changes to ordered list values require checking that new
    > > + * values are found in the list of elements.
    > > + */
    > > + elem_found = 0;
    > > + while (elem_found < bioscfg_drv.ordered_list_data[instance_id].elements_size) {
    > > +
    > > + value = strsep(&new_values, ",");
    >
    > The docs say the separator is semicolon.

    BIOS reports the current value using ',' as separator instead of ";".

    ./hp-bioscfg/attributes/UEFI Boot Order/current_value
    HDD:M.2:3,HDD:USB:1(Disabled),HDD:M.2:4,HDD:M.2:1,HDD:M.2:2,NETWORK
    IPV4:EMBEDDED:1,NETWORK IPV6:EMBEDDED:1,NETWORK
    IPV4:EXPANSION:1,NETWORK IPV6:EXPANSION:1

    To avoid having to convert from "," to ";" and vice versa, I will
    update the documentation to reflect the use of "'," commas as the
    separator

    >
    > > + if (value != NULL) {
    > > + if (!*value)
    > > + continue;
    > > + elem_found++;
    > > + }
    > > +
    > > + found = 0;
    > > + for (elem = 0; elem < bioscfg_drv.ordered_list_data[instance_id].elements_size; elem++) {
    > > + if (!strcasecmp(bioscfg_drv.ordered_list_data[instance_id].elements[elem], value)) {
    >
    > It's surprising that this is case-insensitive.

    As validated in earlier reviews, BIOS rejects strings that do not
    match the internal values.

    >
    > > + found = 1;
    > > + break;
    > > + }
    > > + }
    > > +
    > > +
    > > + if (!found) {
    > > + ret = -EINVAL;
    > > + goto out_list_value;
    > > + }
    > > + }
    > > +
    > > + if (elem_found == bioscfg_drv.ordered_list_data[instance_id].elements_size) {
    > > + pr_warn("Number of new values is not equal to number of ordered list elements (%d)\n",
    > > + bioscfg_drv.ordered_list_data[instance_id].elements_size);
    > > + ret = -EINVAL;
    > > + goto out_list_value;
    > > + }
    > > +
    > > +out_list_value:
    > > + kfree(new_values);
    > > + return ret;
    > > +}
    >
    > This algorithm does not seem to validate that different values are
    > provided.
    >
    > So if "possible_values" is "foo,bar,baz" this function would accept
    > "foo,foo,foo".
    >

    BIOS will reject strings such as "foo,foo,foo" when the current value
    is "foo,bar,baz". It is ok to provide a string which items are
    ordered differently. i.e. "baz,bar,foo"
    validate_ordered_list_values() function will be removed as indicated earlier.

    > > +
    > > +/*
    > > + * validate_ordered_input() -
    > > + * Validate input of current_value against possible values
    > > + *
    > > + * @instance_id: The instance on which input is validated
    > > + * @buf: Input value
    > > + */
    > > +static int validate_ordered_list_input(int instance_id, const char *buf)
    > > +{
    > > + int ret = 0;
    > > +
    > > + ret = validate_ordered_list_values(instance_id, buf);
    > > + if (ret < 0)
    > > + return -EINVAL;
    > > +
    > > + /*
    > > + * set pending reboot flag depending on
    > > + * "RequiresPhysicalPresence" value
    > > + */
    > > + if (bioscfg_drv.ordered_list_data[instance_id].common.requires_physical_presence)
    > > + bioscfg_drv.pending_reboot = true;
    > > +
    > > + return ret;
    > > +}
    > > +
    > > +static void update_ordered_list_value(int instance_id, char *attr_value)
    > > +{
    > > + strscpy(bioscfg_drv.ordered_list_data[instance_id].current_value,
    > > + attr_value,
    > > + sizeof(bioscfg_drv.ordered_list_data[instance_id].current_value));
    > > +}
    > > +
    > > +ATTRIBUTE_S_COMMON_PROPERTY_SHOW(display_name_language_code, ordered_list);
    > > +static struct kobj_attribute ordered_list_display_langcode =
    > > + __ATTR_RO(display_name_language_code);
    > > +
    > > +ATTRIBUTE_S_COMMON_PROPERTY_SHOW(display_name, ordered_list);
    > > +static struct kobj_attribute ordered_list_display_name =
    > > + __ATTR_RO(display_name);
    > > +
    > > +ATTRIBUTE_PROPERTY_STORE(current_value, ordered_list);
    > > +static struct kobj_attribute ordered_list_current_val =
    > > + __ATTR_RW_MODE(current_value, 0644);
    > > +
    > > +
    > > +ATTRIBUTE_N_COMMON_PROPERTY_SHOW(prerequisites_size, ordered_list);
    > > +static struct kobj_attribute ordered_list_prerequisites_size_val =
    > > + __ATTR_RO(prerequisites_size);
    > > +
    > > +ATTRIBUTE_V_COMMON_PROPERTY_SHOW(prerequisites, ordered_list);
    > > +static struct kobj_attribute ordered_list_prerequisites_val =
    > > + __ATTR_RO(prerequisites);
    > > +
    > > +ATTRIBUTE_N_PROPERTY_SHOW(elements_size, ordered_list);
    > > +static struct kobj_attribute ordered_list_elements_size_val =
    > > + __ATTR_RO(elements_size);
    >
    > "size" and "length" attributes are fairly useless to userspace.
    > They can't be trusted to provide information about another attribute as
    > the information can be out of date when the other attribute is read.
    >

    Prerequisites, prerequisites_size and elements_size will be removed

    > > +
    > > +ATTRIBUTE_VALUES_PROPERTY_SHOW(elements, ordered_list);
    > > +static struct kobj_attribute ordered_list_elements_val =
    > > + __ATTR_RO(elements);
    > > +

    <snip>

    > > +
    > > +
    > > +int populate_ordered_list_elements_from_package(union acpi_object *order_obj,
    > > + int order_obj_count,
    > > + int instance_id)
    > > +{
    > > + char *str_value = NULL;
    > > + int value_len;
    > > + int ret = 0;
    > > + u32 size = 0;
    > > + u32 int_value;
    > > + int elem = 0;
    > > + int reqs;
    > > + int eloc;
    > > + char *tmpstr = NULL;
    > > + char *part_tmp = NULL;
    > > + int tmp_len = 0;
    > > + char *part = NULL;
    > > +
    > > + if (!order_obj)
    > > + return -EINVAL;
    > > +
    > > + strscpy(bioscfg_drv.ordered_list_data[instance_id].common.display_name_language_code,
    > > + LANG_CODE_STR,
    > > + sizeof(bioscfg_drv.ordered_list_data[instance_id].common.display_name_language_code));
    >
    > This seems to be the same for every type. Can it not be moved into
    > common code?

    Each instance requires to report 'display_name_language_code' hence it
    cannot be moved to a common code.
    >

    <snip>

    \
     
     \ /
      Last update: 2023-05-05 18:11    [W:5.186 / U:1.216 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site