platform/x86: hp-wmi: Changing bios_args.data to be dynamically allocated
The purpose of this patch is to remove 128 bytes buffer limitation imposed in bios_args structure. A limiting factor discovered during this investigation was the struct bios_args.data size restriction. The data member size limits all possible WMI commands to those requiring buffer size of 128 bytes or less. Several WMI commands and queries require a buffer size larger than 128 bytes hence limiting current and feature supported by the driver. It is for this reason, struct bios_args.data changed and is dynamically allocated. hp_wmi_perform_query function changed to handle the memory allocation and release of any required buffer size. All changes were validated on a HP ZBook Workstation notebook, HP EliteBook x360, and HP EliteBook 850 G8. Additional validation was included in the test process to ensure no other commands were incorrectly handled. Signed-off-by: Jorge Lopez <jorge.lopez2@hp.com> Link: https://lore.kernel.org/r/20220310210853.28367-5-jorge.lopez2@hp.com Reviewed-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
This commit is contained in:
parent
be9d73e649
commit
4b4967cbd2
@ -82,12 +82,17 @@ enum hp_wmi_event_ids {
|
||||
HPWMI_BATTERY_CHARGE_PERIOD = 0x10,
|
||||
};
|
||||
|
||||
/*
|
||||
* struct bios_args buffer is dynamically allocated. New WMI command types
|
||||
* were introduced that exceeds 128-byte data size. Changes to handle
|
||||
* the data size allocation scheme were kept in hp_wmi_perform_qurey function.
|
||||
*/
|
||||
struct bios_args {
|
||||
u32 signature;
|
||||
u32 command;
|
||||
u32 commandtype;
|
||||
u32 datasize;
|
||||
u8 data[128];
|
||||
u8 data[];
|
||||
};
|
||||
|
||||
enum hp_wmi_commandtype {
|
||||
@ -266,37 +271,43 @@ static inline int encode_outsize_for_pvsz(int outsize)
|
||||
static int hp_wmi_perform_query(int query, enum hp_wmi_command command,
|
||||
void *buffer, int insize, int outsize)
|
||||
{
|
||||
int mid;
|
||||
struct acpi_buffer input, output = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
struct bios_return *bios_return;
|
||||
int actual_outsize;
|
||||
union acpi_object *obj;
|
||||
struct bios_args args = {
|
||||
.signature = 0x55434553,
|
||||
.command = command,
|
||||
.commandtype = query,
|
||||
.datasize = insize,
|
||||
.data = { 0 },
|
||||
};
|
||||
struct acpi_buffer input = { sizeof(struct bios_args), &args };
|
||||
struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
int ret = 0;
|
||||
union acpi_object *obj = NULL;
|
||||
struct bios_args *args = NULL;
|
||||
int mid, actual_outsize, ret;
|
||||
size_t bios_args_size;
|
||||
|
||||
mid = encode_outsize_for_pvsz(outsize);
|
||||
if (WARN_ON(mid < 0))
|
||||
return mid;
|
||||
|
||||
if (WARN_ON(insize > sizeof(args.data)))
|
||||
return -EINVAL;
|
||||
memcpy(&args.data[0], buffer, insize);
|
||||
bios_args_size = struct_size(args, data, insize);
|
||||
args = kmalloc(bios_args_size, GFP_KERNEL);
|
||||
if (!args)
|
||||
return -ENOMEM;
|
||||
|
||||
wmi_evaluate_method(HPWMI_BIOS_GUID, 0, mid, &input, &output);
|
||||
input.length = bios_args_size;
|
||||
input.pointer = args;
|
||||
|
||||
args->signature = 0x55434553;
|
||||
args->command = command;
|
||||
args->commandtype = query;
|
||||
args->datasize = insize;
|
||||
memcpy(args->data, buffer, flex_array_size(args, data, insize));
|
||||
|
||||
ret = wmi_evaluate_method(HPWMI_BIOS_GUID, 0, mid, &input, &output);
|
||||
if (ret)
|
||||
goto out_free;
|
||||
|
||||
obj = output.pointer;
|
||||
|
||||
if (!obj)
|
||||
return -EINVAL;
|
||||
if (!obj) {
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (obj->type != ACPI_TYPE_BUFFER) {
|
||||
pr_warn("query 0x%x returned an invalid object 0x%x\n", query, ret);
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
@ -321,6 +332,7 @@ static int hp_wmi_perform_query(int query, enum hp_wmi_command command,
|
||||
|
||||
out_free:
|
||||
kfree(obj);
|
||||
kfree(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user