From patchwork Tue Jun 6 03:16:44 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andy Lutomirski X-Patchwork-Id: 9767999 X-Patchwork-Delegate: dvhart@infradead.org Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 4A6B66034B for ; Tue, 6 Jun 2017 03:16:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3EB93283AF for ; Tue, 6 Jun 2017 03:16:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 332C8283CF; Tue, 6 Jun 2017 03:16:50 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 12864283AF for ; Tue, 6 Jun 2017 03:16:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751215AbdFFDQs (ORCPT ); Mon, 5 Jun 2017 23:16:48 -0400 Received: from bombadil.infradead.org ([65.50.211.133]:34937 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751194AbdFFDQr (ORCPT ); Mon, 5 Jun 2017 23:16:47 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:MIME-Version:Message-ID:Subject:Cc:To:From:Date:Reply-To: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=N+n9trI1d8ntLwIsYUVADWcnpf1DxXBEtE5N/Vne9h4=; b=C8On63/wq4KWSn5v2YuYz+Uhc eXyTXtF0w+G+NQJoHri4xk7w4Le9FTfvG/+WXeDkF4R29L6xm5ZLDRgi5d11feYdx8xfhVF4AX4G0 aT1HSN4IJPKW07Qe8rk59f1X5P2h0JkMdreUyecUr4uXYUSewneb6jxWAvZYxabkAvjwqp6qudI35 d2MADB/hPLedHOKXjrvgzIi101DkdbmMmNyvbppBEksozbZ3hH59/lwoBjRn/9ZWpsi9WHi2a6T37 sWCs5uSu4y0yiyBd8wn/TFc7uHS3OLHQJ0X3NCCvVJ0dkNdzjvQKfjd8nz5pJOXqeAnemm2z2DtMh DMR15fmEg==; Received: from dvhart by bombadil.infradead.org with local (Exim 4.87 #1 (Red Hat Linux)) id 1dI4z7-0005Id-EX; Tue, 06 Jun 2017 03:16:45 +0000 Date: Mon, 5 Jun 2017 20:16:44 -0700 From: Andy Lutomirski To: pali.rohar@gmail.com Cc: platform-driver-x86@vger.kernel.org, Andy Shevchenko , Andy Lutomirski , Andy Lutomirski , Mario Limonciello , Rafael Wysocki , linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org Subject: [PATCH v2] platform/x86: wmi-bmof: New driver to expose embedded Binary WMI MOF metadata Message-ID: MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.8.0 (2017-02-23) Sender: platform-driver-x86-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: platform-driver-x86@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Many laptops (and maybe servers?) have embedded WMI Binary MOF metadata. We do not yet have open-source tools for processing the data, although one is in the works thanks to Pali: https://github.com/pali/bmfdec There is currently no interface to get the data in the first place. By exposing it, we facilitate the development of new tools. Signed-off-by: Andy Lutomirski Cc: Andy Lutomirski Cc: Mario Limonciello Cc: Pali Rohár Cc: linux-kernel@vger.kernel.org Cc: platform-driver-x86@vger.kernel.org Cc: linux-acpi@vger.kernel.org [dvhart: make sysfs mof binary read only, fixup comment block format] [dvhart: use bmof terminology and dev_err instead of dev_warn] Acked-by: Rafael J. Wysocki Signed-off-by: Darren Hart (VMware) Reviewed-by: Andy Shevchenko --- since-v1: * address Pali's comments: * update the cover letter for clarity and accuracy * update mof->bmof and MOF to Binary MOF throughout the patch * use dev_err instead of dev_warn in wmi_bmof_probe drivers/platform/x86/Kconfig | 12 ++++ drivers/platform/x86/Makefile | 1 + drivers/platform/x86/wmi-bmof.c | 125 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 138 insertions(+) create mode 100644 drivers/platform/x86/wmi-bmof.c diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 49a1d01..6ebe393 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -656,6 +656,18 @@ config ACPI_WMI It is safe to enable this driver even if your DSDT doesn't define any ACPI-WMI devices. +config WMI_BMOF + tristate "WMI embedded Binary MOF driver" + depends on ACPI_WMI + default y + ---help--- + Say Y here if you want to be able to read a firmware-embedded + WMI Binary MOF data. Using this requires userspace tools and may be + rather tedious. + + To compile this driver as a module, choose M here: the module will + be called wmi-bmof. + config MSI_WMI tristate "MSI WMI extras" depends on ACPI_WMI diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index 652d7c8..6a1063e 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_MSI_WMI) += msi-wmi.o obj-$(CONFIG_PEAQ_WMI) += peaq-wmi.o obj-$(CONFIG_SURFACE3_WMI) += surface3-wmi.o obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o +obj-$(CONFIG_WMI_BMOF) += wmi-bmof.o # toshiba_acpi must link after wmi to ensure that wmi devices are found # before toshiba_acpi initializes diff --git a/drivers/platform/x86/wmi-bmof.c b/drivers/platform/x86/wmi-bmof.c new file mode 100644 index 0000000..e1c0963 --- /dev/null +++ b/drivers/platform/x86/wmi-bmof.c @@ -0,0 +1,125 @@ +/* + * WMI embedded Binary MOF driver + * + * Copyright (c) 2015 Andrew Lutomirski + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define WMI_BMOF_GUID "05901221-D566-11D1-B2F0-00A0C9062910" +MODULE_ALIAS("wmi:" WMI_BMOF_GUID); + +struct bmof_priv { + union acpi_object *bmofdata; + struct bin_attribute bmof_bin_attr; +}; + +static ssize_t +read_bmof(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct bmof_priv *priv = + container_of(attr, struct bmof_priv, bmof_bin_attr); + + if (off >= priv->bmofdata->buffer.length) + return 0; + + if (count > priv->bmofdata->buffer.length - off) + count = priv->bmofdata->buffer.length - off; + + memcpy(buf, priv->bmofdata->buffer.pointer + off, count); + return count; +} + +static int wmi_bmof_probe(struct wmi_device *wdev) +{ + int ret; + + struct bmof_priv *priv = + devm_kzalloc(&wdev->dev, sizeof(struct bmof_priv), GFP_KERNEL); + + if (!priv) + return -ENOMEM; + + dev_set_drvdata(&wdev->dev, priv); + + priv->bmofdata = wmidev_block_query(wdev, 0); + if (!priv->bmofdata) { + dev_err(&wdev->dev, "failed to read Binary MOF\n"); + return -EIO; + } + + if (priv->bmofdata->type != ACPI_TYPE_BUFFER) { + dev_err(&wdev->dev, "Binary MOF is not a buffer\n"); + ret = -EIO; + goto err_free; + } + + sysfs_bin_attr_init(&priv->bmof_bin_attr); + priv->bmof_bin_attr.attr.name = "bmof"; + priv->bmof_bin_attr.attr.mode = 0400; + priv->bmof_bin_attr.read = read_bmof; + priv->bmof_bin_attr.size = priv->bmofdata->buffer.length; + + ret = sysfs_create_bin_file(&wdev->dev.kobj, &priv->bmof_bin_attr); + if (ret) + goto err_free; + + return 0; + + err_free: + kfree(priv->bmofdata); + return ret; +} + +static int wmi_bmof_remove(struct wmi_device *wdev) +{ + struct bmof_priv *priv = dev_get_drvdata(&wdev->dev); + + sysfs_remove_bin_file(&wdev->dev.kobj, &priv->bmof_bin_attr); + kfree(priv->bmofdata); + return 0; +} + +static const struct wmi_device_id wmi_bmof_id_table[] = { + { .guid_string = WMI_BMOF_GUID }, + { }, +}; + +static struct wmi_driver wmi_bmof_driver = { + .driver = { + .name = "wmi-bmof", + }, + .probe = wmi_bmof_probe, + .remove = wmi_bmof_remove, + .id_table = wmi_bmof_id_table, +}; + +module_wmi_driver(wmi_bmof_driver); + +MODULE_AUTHOR("Andrew Lutomirski "); +MODULE_DESCRIPTION("WMI embedded Binary MOF driver"); +MODULE_LICENSE("GPL");