diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-18 19:26:57 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-18 19:26:57 +0100 |
commit | 07c455ee222f3ad219c2835d05a175a326a138fb (patch) | |
tree | c3fdcd89a4fe87877963162de8bc428bb265bb8e /tools | |
parent | Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc (diff) | |
parent | platform/x86: silead_dmi: Add silead, home-button property to some tablets (diff) | |
download | linux-07c455ee222f3ad219c2835d05a175a326a138fb.tar.xz linux-07c455ee222f3ad219c2835d05a175a326a138fb.zip |
Merge tag 'platform-drivers-x86-v4.15-1' of git://git.infradead.org/linux-platform-drivers-x86
Pull x86 platform driver updates from Andy Shevchenko:
"Here is the collected material against Platform Drivers x86 subsystem.
It's rather bit busy cycle for PDx86, mostly due to Dell SMBIOS driver
activity
For this cycle we have quite an update for the Dell SMBIOS driver
including WMI work to provide an interface for SMBIOS tokens via sysfs
and WMI support for 2017+ Dell laptop models. SMM dispatcher code is
split into a separate driver followed by a new WMI dispatcher. The
latter provides a character device interface to user space.
The git history also contains a merge of immutable branch from Wolfram
Sang in order to apply a dependent fix to the Intel CherryTrail
Battery Management driver.
Other Intel drivers got a lot of cleanups. The Turbo Boost Max 3.0
support is added for Intel Skylake.
Peaq WMI hotkeys driver gets its own maintainer and white list of
supported models.
Silead DMI is expanded to support few additional platforms.
Tablet mode via GMMS ACPI method is added to support some ThinkPad
tablets.
new driver:
- Add driver to force WMI Thunderbolt controller power status
asus-wmi:
- Add lightbar led support
dell-laptop:
- Allocate buffer before rfkill use
dell-smbios:
- fix string overflow
- Add filtering support
- Introduce dispatcher for SMM calls
- Add a sysfs interface for SMBIOS tokens
- only run if proper oem string is detected
- Prefix class/select with cmd_
- Add pr_fmt definition to driver
dell-smbios-smm:
- test for WSMT
dell-smbios-wmi:
- release mutex lock on WMI call failure
- introduce userspace interface
- Add new WMI dispatcher driver
dell-smo8800:
- remove redundant assignments to byte_data
dell-wmi:
- don't check length returned
- clean up wmi descriptor check
- increase severity of some failures
- Do not match on descriptor GUID modalias
- Label driver as handling notifications
dell-*wmi*:
- Relay failed initial probe to dependent drivers
dell-wmi-descriptor:
- check if memory was allocated
- split WMI descriptor into it's own driver
fujitsu-laptop:
- Fix radio LED detection
- Don't oops when FUJ02E3 is not presnt
hp_accel:
- Add quirk for HP ProBook 440 G4
hp-wmi:
- Fix tablet mode detection for convertibles
ideapad-laptop:
- Add Lenovo Yoga 920-13IKB to no_hw_rfkill dmi list
intel_cht_int33fe:
- Update fusb302 type string, add properties
- make a couple of local functions static
- Work around BIOS bug on some devices
intel-hid:
- Power button suspend on Dell Latitude 7275
intel_ips:
- Convert timers to use timer_setup()
- Remove FSF address from GPL notice
- Remove unneeded fields and label
- Keep pointer to struct device
- Use PCI_VDEVICE() macro
- Switch to new PCI IRQ allocation API
- Simplify error handling via devres API
intel_pmc_ipc:
- Revert Use MFD framework to create dependent devices
- Use MFD framework to create dependent devices
- Use spin_lock to protect GCR updates
- Use devm_* calls in driver probe function
intel_punit_ipc:
- Fix resource ioremap warning
intel_telemetry:
- Remove useless default in Kconfig
- Add needed inclusion
- cleanup redundant headers
- Fix typos
- Fix load failure info
intel_telemetry_debugfs:
- Use standard ARRAY_SIZE() macro
intel_turbo_max_3:
- Add Skylake platform
intel-wmi-thunderbolt:
- Silence error cases
mlx-platform:
- make a couple of structures static
peaq_wmi:
- Fix missing terminating entry for peaq_dmi_table
peaq-wmi:
- Remove unnecessary checks from peaq_wmi_exit
- Add DMI check before binding to the WMI interface
- Revert Blacklist Lenovo ideapad 700-15ISK
- Blacklist Lenovo ideapad 700-15ISK
silead_dmi:
- Add silead, home-button property to some tablets
- Add entry for the Digma e200 tablet
- Fix GP-electronic T701 entry
- Add entry for the Chuwi Hi8 Pro tablet
sony-laptop:
- Drop variable assignment in sony_nc_setup_rfkill()
- Fix error handling in sony_nc_setup_rfkill()
thinkpad_acpi:
- Implement tablet mode using GMMS method
tools/wmi:
- add a sample for dell smbios communication over WMI
wmi:
- release mutex on module acquistion failure
- create userspace interface for drivers
- Don't allow drivers to get each other's GUIDs
- Add new method wmidev_evaluate_method
- Destroy on cleanup rather than unregister
- Cleanup exit routine in reverse order of init
- Sort include list"
* tag 'platform-drivers-x86-v4.15-1' of git://git.infradead.org/linux-platform-drivers-x86: (74 commits)
platform/x86: silead_dmi: Add silead, home-button property to some tablets
platform/x86: dell-laptop: Allocate buffer before rfkill use
platform/x86: dell-*wmi*: Relay failed initial probe to dependent drivers
platform/x86: dell-wmi-descriptor: check if memory was allocated
platform/x86: Revert intel_pmc_ipc: Use MFD framework to create dependent devices
platform/x86: dell-smbios-wmi: release mutex lock on WMI call failure
platform/x86: wmi: release mutex on module acquistion failure
platform/x86: dell-smbios: fix string overflow
platform/x86: intel_pmc_ipc: Use MFD framework to create dependent devices
platform/x86: intel_punit_ipc: Fix resource ioremap warning
platform/x86: dell-smo8800: remove redundant assignments to byte_data
platform/x86: hp-wmi: Fix tablet mode detection for convertibles
platform/x86: intel_ips: Convert timers to use timer_setup()
platform/x86: sony-laptop: Drop variable assignment in sony_nc_setup_rfkill()
platform/x86: sony-laptop: Fix error handling in sony_nc_setup_rfkill()
tools/wmi: add a sample for dell smbios communication over WMI
platform/x86: dell-smbios-wmi: introduce userspace interface
platform/x86: wmi: create userspace interface for drivers
platform/x86: dell-smbios: Add filtering support
platform/x86: dell-smbios-smm: test for WSMT
...
Diffstat (limited to 'tools')
-rw-r--r-- | tools/Makefile | 14 | ||||
-rw-r--r-- | tools/wmi/Makefile | 18 | ||||
-rw-r--r-- | tools/wmi/dell-smbios-example.c | 210 |
3 files changed, 236 insertions, 6 deletions
diff --git a/tools/Makefile b/tools/Makefile index c03b4f69d5b7..be02c8b904db 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -30,6 +30,7 @@ help: @echo ' usb - USB testing tools' @echo ' virtio - vhost test module' @echo ' vm - misc vm tools' + @echo ' wmi - WMI interface examples' @echo ' x86_energy_perf_policy - Intel energy policy tool' @echo '' @echo 'You can do:' @@ -58,7 +59,7 @@ acpi: FORCE cpupower: FORCE $(call descend,power/$@) -cgroup firewire hv guest spi usb virtio vm bpf iio gpio objtool leds: FORCE +cgroup firewire hv guest spi usb virtio vm bpf iio gpio objtool leds wmi: FORCE $(call descend,$@) liblockdep: FORCE @@ -93,7 +94,7 @@ kvm_stat: FORCE all: acpi cgroup cpupower gpio hv firewire liblockdep \ perf selftests spi turbostat usb \ virtio vm bpf x86_energy_perf_policy \ - tmon freefall iio objtool kvm_stat + tmon freefall iio objtool kvm_stat wmi acpi_install: $(call descend,power/$(@:_install=),install) @@ -101,7 +102,7 @@ acpi_install: cpupower_install: $(call descend,power/$(@:_install=),install) -cgroup_install firewire_install gpio_install hv_install iio_install perf_install spi_install usb_install virtio_install vm_install bpf_install objtool_install: +cgroup_install firewire_install gpio_install hv_install iio_install perf_install spi_install usb_install virtio_install vm_install bpf_install objtool_install wmi_install: $(call descend,$(@:_install=),install) liblockdep_install: @@ -126,7 +127,8 @@ install: acpi_install cgroup_install cpupower_install gpio_install \ hv_install firewire_install iio_install liblockdep_install \ perf_install selftests_install turbostat_install usb_install \ virtio_install vm_install bpf_install x86_energy_perf_policy_install \ - tmon_install freefall_install objtool_install kvm_stat_install + tmon_install freefall_install objtool_install kvm_stat_install \ + wmi_install acpi_clean: $(call descend,power/acpi,clean) @@ -134,7 +136,7 @@ acpi_clean: cpupower_clean: $(call descend,power/cpupower,clean) -cgroup_clean hv_clean firewire_clean spi_clean usb_clean virtio_clean vm_clean bpf_clean iio_clean gpio_clean objtool_clean leds_clean: +cgroup_clean hv_clean firewire_clean spi_clean usb_clean virtio_clean vm_clean wmi_clean bpf_clean iio_clean gpio_clean objtool_clean leds_clean: $(call descend,$(@:_clean=),clean) liblockdep_clean: @@ -172,6 +174,6 @@ clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean \ perf_clean selftests_clean turbostat_clean spi_clean usb_clean virtio_clean \ vm_clean bpf_clean iio_clean x86_energy_perf_policy_clean tmon_clean \ freefall_clean build_clean libbpf_clean libsubcmd_clean liblockdep_clean \ - gpio_clean objtool_clean leds_clean + gpio_clean objtool_clean leds_clean wmi_clean .PHONY: FORCE diff --git a/tools/wmi/Makefile b/tools/wmi/Makefile new file mode 100644 index 000000000000..e664f1167388 --- /dev/null +++ b/tools/wmi/Makefile @@ -0,0 +1,18 @@ +PREFIX ?= /usr +SBINDIR ?= sbin +INSTALL ?= install +CFLAGS += -D__EXPORTED_HEADERS__ -I../../include/uapi -I../../include +CC = $(CROSS_COMPILE)gcc + +TARGET = dell-smbios-example + +all: $(TARGET) + +%: %.c + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< + +clean: + $(RM) $(TARGET) + +install: dell-smbios-example + $(INSTALL) -D -m 755 $(TARGET) $(DESTDIR)$(PREFIX)/$(SBINDIR)/$(TARGET) diff --git a/tools/wmi/dell-smbios-example.c b/tools/wmi/dell-smbios-example.c new file mode 100644 index 000000000000..9d3bde081249 --- /dev/null +++ b/tools/wmi/dell-smbios-example.c @@ -0,0 +1,210 @@ +/* + * Sample application for SMBIOS communication over WMI interface + * Performs the following: + * - Simple cmd_class/cmd_select lookup for TPM information + * - Simple query of known tokens and their values + * - Simple activation of a token + * + * Copyright (C) 2017 Dell, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <unistd.h> + +/* if uapi header isn't installed, this might not yet exist */ +#ifndef __packed +#define __packed __attribute__((packed)) +#endif +#include <linux/wmi.h> + +/* It would be better to discover these using udev, but for a simple + * application they're hardcoded + */ +static const char *ioctl_devfs = "/dev/wmi/dell-smbios"; +static const char *token_sysfs = + "/sys/bus/platform/devices/dell-smbios.0/tokens"; + +static void show_buffer(struct dell_wmi_smbios_buffer *buffer) +{ + printf("Call: %x/%x [%x,%x,%x,%x]\nResults: [%8x,%8x,%8x,%8x]\n", + buffer->std.cmd_class, buffer->std.cmd_select, + buffer->std.input[0], buffer->std.input[1], + buffer->std.input[2], buffer->std.input[3], + buffer->std.output[0], buffer->std.output[1], + buffer->std.output[2], buffer->std.output[3]); +} + +static int run_wmi_smbios_cmd(struct dell_wmi_smbios_buffer *buffer) +{ + int fd; + int ret; + + fd = open(ioctl_devfs, O_NONBLOCK); + ret = ioctl(fd, DELL_WMI_SMBIOS_CMD, buffer); + close(fd); + return ret; +} + +static int find_token(__u16 token, __u16 *location, __u16 *value) +{ + char location_sysfs[60]; + char value_sysfs[57]; + char buf[4096]; + FILE *f; + int ret; + + ret = sprintf(value_sysfs, "%s/%04x_value", token_sysfs, token); + if (ret < 0) { + printf("sprintf value failed\n"); + return 2; + } + f = fopen(value_sysfs, "rb"); + if (!f) { + printf("failed to open %s\n", value_sysfs); + return 2; + } + fread(buf, 1, 4096, f); + fclose(f); + *value = (__u16) strtol(buf, NULL, 16); + + ret = sprintf(location_sysfs, "%s/%04x_location", token_sysfs, token); + if (ret < 0) { + printf("sprintf location failed\n"); + return 1; + } + f = fopen(location_sysfs, "rb"); + if (!f) { + printf("failed to open %s\n", location_sysfs); + return 2; + } + fread(buf, 1, 4096, f); + fclose(f); + *location = (__u16) strtol(buf, NULL, 16); + + if (*location) + return 0; + return 2; +} + +static int token_is_active(__u16 *location, __u16 *cmpvalue, + struct dell_wmi_smbios_buffer *buffer) +{ + int ret; + + buffer->std.cmd_class = CLASS_TOKEN_READ; + buffer->std.cmd_select = SELECT_TOKEN_STD; + buffer->std.input[0] = *location; + ret = run_wmi_smbios_cmd(buffer); + if (ret != 0 || buffer->std.output[0] != 0) + return ret; + ret = (buffer->std.output[1] == *cmpvalue); + return ret; +} + +static int query_token(__u16 token, struct dell_wmi_smbios_buffer *buffer) +{ + __u16 location; + __u16 value; + int ret; + + ret = find_token(token, &location, &value); + if (ret != 0) { + printf("unable to find token %04x\n", token); + return 1; + } + return token_is_active(&location, &value, buffer); +} + +static int activate_token(struct dell_wmi_smbios_buffer *buffer, + __u16 token) +{ + __u16 location; + __u16 value; + int ret; + + ret = find_token(token, &location, &value); + if (ret != 0) { + printf("unable to find token %04x\n", token); + return 1; + } + buffer->std.cmd_class = CLASS_TOKEN_WRITE; + buffer->std.cmd_select = SELECT_TOKEN_STD; + buffer->std.input[0] = location; + buffer->std.input[1] = 1; + ret = run_wmi_smbios_cmd(buffer); + return ret; +} + +static int query_buffer_size(__u64 *buffer_size) +{ + FILE *f; + + f = fopen(ioctl_devfs, "rb"); + if (!f) + return -EINVAL; + fread(buffer_size, sizeof(__u64), 1, f); + fclose(f); + return EXIT_SUCCESS; +} + +int main(void) +{ + struct dell_wmi_smbios_buffer *buffer; + int ret; + __u64 value = 0; + + ret = query_buffer_size(&value); + if (ret == EXIT_FAILURE || !value) { + printf("Unable to read buffer size\n"); + goto out; + } + printf("Detected required buffer size %lld\n", value); + + buffer = malloc(value); + if (buffer == NULL) { + printf("failed to alloc memory for ioctl\n"); + ret = -ENOMEM; + goto out; + } + buffer->length = value; + + /* simple SMBIOS call for looking up TPM info */ + buffer->std.cmd_class = CLASS_FLASH_INTERFACE; + buffer->std.cmd_select = SELECT_FLASH_INTERFACE; + buffer->std.input[0] = 2; + ret = run_wmi_smbios_cmd(buffer); + if (ret) { + printf("smbios ioctl failed: %d\n", ret); + ret = EXIT_FAILURE; + goto out; + } + show_buffer(buffer); + + /* query some tokens */ + ret = query_token(CAPSULE_EN_TOKEN, buffer); + printf("UEFI Capsule enabled token is: %d\n", ret); + ret = query_token(CAPSULE_DIS_TOKEN, buffer); + printf("UEFI Capsule disabled token is: %d\n", ret); + + /* activate UEFI capsule token if disabled */ + if (ret) { + printf("Enabling UEFI capsule token"); + if (activate_token(buffer, CAPSULE_EN_TOKEN)) { + printf("activate failed\n"); + ret = -1; + goto out; + } + } + ret = EXIT_SUCCESS; +out: + free(buffer); + return ret; +} |