+static int call_biosattributes_interface(struct wmi_device *wdev, char*in_args, size_t size,
+ int method_id)
+{
+ struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
+ struct acpi_buffer input;
+ union acpi_object *obj;
+ acpi_status status;
+ int ret = -EIO;
+
+ input.length = (acpi_size) size;
+ input.pointer = in_args;
+ status = wmidev_evaluate_method(wdev, 0, method_id, &input, &output);
+ if (ACPI_FAILURE(status))
+ return -EIO;
+ obj = (union acpi_object *)output.pointer;
+ if (obj->type == ACPI_TYPE_INTEGER)
+ ret = obj->integer.value;
+
+ kfree(output.pointer);
+ kobject_uevent(&wdev->dev.kobj, KOBJ_CHANGE);
Why are you generating an uevent here? I think this needs a comment (or it
should be removed).
It's there so that userspace can know that a setting has been changed and doesn't
need to poll the attribute indicating a reboot is pending.
We can certainly add a comment to this effect.
+ return map_wmi_error(ret);UTF16_HOST_ENDIAN,
+}
+
+/**
+ * set_attribute() - Update an attribute value
+ * @a_name: The attribute name
+ * @a_value: The attribute value
+ *
+ * Sets an attribute to new value
+ **/
+int set_attribute(const char *a_name, const char *a_value)
+{
+ size_t security_area_size, string_area_size, buffer_size;
+ char *attribute_name, *attribute_value;
+ u8 *name_len, *value_len;
+ char *buffer;
+ int ret;
+
+ /* build/calculate buffer */
+ security_area_size = calculate_security_buffer();
+ string_area_size = (strlen(a_name) + strlen(a_value))*2;
+ buffer_size = security_area_size + string_area_size + sizeof(u16) * 2;
+ buffer = kzalloc(buffer_size, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ /* build security area */
+ if (strlen(wmi_priv.current_admin_password) > 0)
+ populate_security_buffer(buffer, wmi_priv.current_admin_password);
+
+ /* build variables to set */
+ name_len = buffer + security_area_size;
+ attribute_name = name_len + sizeof(u16);
+ *name_len = utf8s_to_utf16s(a_name, strlen(a_name), UTF16_HOST_ENDIAN,
+ (wchar_t *) attribute_name, MAX_BUFF) * 2;
+ if (*name_len < 0) {
+ ret = -EINVAL;
+ pr_err("UTF16 conversion failed");
+ goto out_set_attribute;
+ }
+
+ value_len = (u8 *) attribute_name + *name_len;
+ attribute_value = value_len + sizeof(u16);
+ *value_len = utf8s_to_utf16s(a_value, strlen(a_value),
+ (wchar_t *) attribute_value, MAX_BUFF) * 2;
+ if (*value_len < 0) {
+ ret = -EINVAL;
+ pr_err("UTF16 conversion failed");
+ goto out_set_attribute;
+ }
+
+ mutex_lock(&call_mutex);
+ if (!wmi_priv.bios_attr_wdev) {
+ ret = -ENODEV;
+ pr_err("no WMI backend bound");
+ goto out_set_attribute;
+ }
It is probably better to move this to the top, as I mentioned in my reply
to Mario, you could add something like this to the top of each function,
even before allocating the buffer and filling it.
The placement was intentional to avoid taking the mutex until data was validated.
Is it preferable to make it specifically on entry into functions then?
mutex_lock(&wmi_priv.mutex);
if (!wmi_priv.bios_attr_wdev || !wmi_priv.password_attr_wdev) {
ret = -ENODEV;
goto out_set_attribute;
}
Note this requires that you initialize the buf pointer to NULL
when declaring it.
Having this at the top of each function establishes a pattern where
it easy for a reader of the code to:
a) See that the check is present when checking that the driver being
unbound is checked everywhere
b) Ignore the check as "boilerplate" when looking at other parts of
the code
I guess this argument makes sense - setting up a pattern is a good way
to spot the function that stands out when a coding mistake occurs.