Skip to content

Commit 4b4967c

Browse files
Jorge Lopezjwrdegoede
authored andcommitted
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>
1 parent be9d73e commit 4b4967c

1 file changed

Lines changed: 33 additions & 21 deletions

File tree

drivers/platform/x86/hp-wmi.c

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,17 @@ enum hp_wmi_event_ids {
8282
HPWMI_BATTERY_CHARGE_PERIOD = 0x10,
8383
};
8484

85+
/*
86+
* struct bios_args buffer is dynamically allocated. New WMI command types
87+
* were introduced that exceeds 128-byte data size. Changes to handle
88+
* the data size allocation scheme were kept in hp_wmi_perform_qurey function.
89+
*/
8590
struct bios_args {
8691
u32 signature;
8792
u32 command;
8893
u32 commandtype;
8994
u32 datasize;
90-
u8 data[128];
95+
u8 data[];
9196
};
9297

9398
enum hp_wmi_commandtype {
@@ -266,37 +271,43 @@ static inline int encode_outsize_for_pvsz(int outsize)
266271
static int hp_wmi_perform_query(int query, enum hp_wmi_command command,
267272
void *buffer, int insize, int outsize)
268273
{
269-
int mid;
274+
struct acpi_buffer input, output = { ACPI_ALLOCATE_BUFFER, NULL };
270275
struct bios_return *bios_return;
271-
int actual_outsize;
272-
union acpi_object *obj;
273-
struct bios_args args = {
274-
.signature = 0x55434553,
275-
.command = command,
276-
.commandtype = query,
277-
.datasize = insize,
278-
.data = { 0 },
279-
};
280-
struct acpi_buffer input = { sizeof(struct bios_args), &args };
281-
struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
282-
int ret = 0;
276+
union acpi_object *obj = NULL;
277+
struct bios_args *args = NULL;
278+
int mid, actual_outsize, ret;
279+
size_t bios_args_size;
283280

284281
mid = encode_outsize_for_pvsz(outsize);
285282
if (WARN_ON(mid < 0))
286283
return mid;
287284

288-
if (WARN_ON(insize > sizeof(args.data)))
289-
return -EINVAL;
290-
memcpy(&args.data[0], buffer, insize);
285+
bios_args_size = struct_size(args, data, insize);
286+
args = kmalloc(bios_args_size, GFP_KERNEL);
287+
if (!args)
288+
return -ENOMEM;
291289

292-
wmi_evaluate_method(HPWMI_BIOS_GUID, 0, mid, &input, &output);
290+
input.length = bios_args_size;
291+
input.pointer = args;
293292

294-
obj = output.pointer;
293+
args->signature = 0x55434553;
294+
args->command = command;
295+
args->commandtype = query;
296+
args->datasize = insize;
297+
memcpy(args->data, buffer, flex_array_size(args, data, insize));
295298

296-
if (!obj)
297-
return -EINVAL;
299+
ret = wmi_evaluate_method(HPWMI_BIOS_GUID, 0, mid, &input, &output);
300+
if (ret)
301+
goto out_free;
302+
303+
obj = output.pointer;
304+
if (!obj) {
305+
ret = -EINVAL;
306+
goto out_free;
307+
}
298308

299309
if (obj->type != ACPI_TYPE_BUFFER) {
310+
pr_warn("query 0x%x returned an invalid object 0x%x\n", query, ret);
300311
ret = -EINVAL;
301312
goto out_free;
302313
}
@@ -321,6 +332,7 @@ static int hp_wmi_perform_query(int query, enum hp_wmi_command command,
321332

322333
out_free:
323334
kfree(obj);
335+
kfree(args);
324336
return ret;
325337
}
326338

0 commit comments

Comments
 (0)