lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Tue, 23 Jul 2013 16:10:44 +0800
From:	Lv Zheng <lv.zheng@...el.com>
To:	"Rafael J. Wysocki" <rafael.j.wysocki@...el.com>,
	Len Brown <len.brown@...el.com>,
	Corey Minyard <minyard@....org>,
	Zhao Yakui <yakui.zhao@...el.com>
Cc:	Lv Zheng <lv.zheng@...el.com>, <linux-kernel@...r.kernel.org>,
	linux-acpi@...r.kernel.org,
	openipmi-developer@...ts.sourceforge.net
Subject: [PATCH 13/13] ACPI/IPMI: Add IPMI operation region test device driver

This patch is only used for test purpose and should not be merged by any
public Linux kernel repositories.

This patch contains one driver that can drive a fake test device accessing
IPMI operation region fields.

Signed-off-by: Lv Zheng <lv.zheng@...el.com>
---
 drivers/acpi/Kconfig     |   68 +++++++++++++
 drivers/acpi/Makefile    |    1 +
 drivers/acpi/ipmi_test.c |  254 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 323 insertions(+)
 create mode 100644 drivers/acpi/ipmi_test.c

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index d129869..e3dd3fd 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -377,6 +377,74 @@ config ACPI_BGRT
 	  data from the firmware boot splash. It will appear under
 	  /sys/firmware/acpi/bgrt/ .
 
+config ACPI_IPMI_TEST
+	tristate "IPMI operation region tester"
+	help
+	  This is a test device written for such fake ACPI namespace device.
+	    Device (PMIT)
+	    {
+	        Name (_HID, "ZETA0000")  // _HID: Hardware ID
+	        Name (_STA, 0x0F)  // _STA: Status
+	        OperationRegion (SYSI, IPMI, 0x0600, 0x0100)
+	        Field (SYSI, BufferAcc, Lock, Preserve)
+	        {
+	            AccessAs (BufferAcc, 0x01),
+                   Offset (0x01),
+	            GDIC,   8,	// Get Device ID Command
+	        }
+	        Method (GDIM, 0, NotSerialized)  // GDIM: Get Device ID Method
+	        {
+	            Name (GDIR, Package (0x08)
+	            {
+	                0x00,
+	                0x00,
+	                0x0000,
+	                0x00,
+	                0x00,
+	                Buffer (0x03) {0x00, 0x00, 0x00},
+	                Buffer (0x02) {0x00, 0x00},
+	                0x00000000
+	            })
+	            Name (BUFF, Buffer (0x42) {})
+	            CreateByteField (BUFF, 0x00, STAT)
+	            CreateByteField (BUFF, 0x01, LENG)
+	            CreateByteField (BUFF, 0x02, CMPC)
+	            CreateByteField (BUFF, 0x03, DID)
+	            CreateByteField (BUFF, 0x04, DREV)
+	            CreateWordField (BUFF, 0x05, FREV)
+	            CreateByteField (BUFF, 0x07, SREV)
+	            CreateByteField (BUFF, 0x08, ADS)
+	            CreateByteField (BUFF, 0x09, VID0)
+	            CreateByteField (BUFF, 0x0A, VID1)
+	            CreateByteField (BUFF, 0x0B, VID2)
+	            CreateByteField (BUFF, 0x0C, PID0)
+	            CreateByteField (BUFF, 0x0D, PID1)
+	            CreateDWordField (BUFF, 0x0E, AFRI)
+	            Store (0x00, LENG)
+	            Store (Store (BUFF, GDIC), BUFF)
+	            If (LAnd (LEqual (STAT, 0x00), LEqual (CMPC, 0x00)))
+	            {
+	                Name (VBUF, Buffer (0x03) { 0x00, 0x00, 0x00 })
+	                Name (PBUF, Buffer (0x02) { 0x00, 0x00 })
+	                Store (DID, Index (GDIR, 0x00))
+	                Store (DREV, Index (GDIR, 0x01))
+	                Store (FREV, Index (GDIR, 0x02))
+	                Store (SREV, Index (GDIR, 0x03))
+	                Store (ADS, Index (GDIR, 0x04))
+	                Store (VID0, Index (VBUF, 0x00))
+	                Store (VID1, Index (VBUF, 0x01))
+	                Store (VID2, Index (VBUF, 0x02))
+	                Store (VBUF, Index (GDIR, 0x05))
+	                Store (PID0, Index (PBUF, 0x00))
+	                Store (PID1, Index (PBUF, 0x01))
+	                Store (PBUF, Index (GDIR, 0x06))
+	                Store (AFRI, Index (GDIR, 0x07))
+	            }
+	            Return (GDIR)
+	        }
+	    }
+	  It is for validation purpose, only calls "Get Device ID" command.
+
 source "drivers/acpi/apei/Kconfig"
 
 endif	# ACPI
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 81dbeb8..1476623 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -74,6 +74,7 @@ obj-$(CONFIG_ACPI_EC_DEBUGFS)	+= ec_sys.o
 obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o
 obj-$(CONFIG_ACPI_BGRT)		+= bgrt.o
 obj-$(CONFIG_ACPI_I2C)		+= acpi_i2c.o
+obj-$(CONFIG_ACPI_IPMI_TEST)	+= ipmi_test.o
 
 # processor has its own "processor." module_param namespace
 processor-y			:= processor_driver.o processor_throttling.o
diff --git a/drivers/acpi/ipmi_test.c b/drivers/acpi/ipmi_test.c
new file mode 100644
index 0000000..5d144e4
--- /dev/null
+++ b/drivers/acpi/ipmi_test.c
@@ -0,0 +1,254 @@
+/*
+ * An IPMI operation region tester driver
+ *
+ * Copyright (C) 2013 Intel Corporation
+ *   Author: Lv Zheng <lv.zheng@...el.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/module.h>
+#include <linux/acpi.h>
+
+#define ACPI_IPMI_TEST_NAME		"ipmi_test"
+ACPI_MODULE_NAME(ACPI_IPMI_TEST_NAME);
+
+#define ACPI_IPMI_TEST_DEVICE		"IPMI Test"
+#define ACPI_IPMI_TEST_CLASS		"ipmi_tester"
+
+static const struct acpi_device_id acpi_ipmi_test_ids[] = {
+	{"ZETA0000", 0},
+	{"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, acpi_ipmi_test_ids);
+
+struct acpi_ipmi_device_id {
+	u64	device_id;
+	u64	device_rev;
+	u64	firmware_rev;
+	u64	ipmi_version;
+	u64	additional_dev_support;
+	u8	*vendor_id;
+	u8	*product_id;
+	u64	aux_firm_rev_info;
+	u8	extra_buf[5];
+} __packed;
+
+struct acpi_ipmi_tester {
+	struct acpi_device	*adev;
+	acpi_bus_id		name;
+	struct acpi_ipmi_device_id	device_id;
+	int			registered_group;
+};
+
+#define ipmi_err(tester, fmt, ...)	\
+	dev_err(&(tester)->adev->dev, fmt, ##__VA_ARGS__)
+#define ipmi_info(tester, fmt, ...)	\
+	dev_info(&(tester)->adev->dev, fmt, ##__VA_ARGS__)
+#define IPMI_ACPI_HANDLE(tester)	((tester)->adev->handle)
+
+static int acpi_ipmi_update_device_id(struct acpi_ipmi_tester *tester)
+{
+	int res = 0;
+	acpi_status status;
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+	struct acpi_buffer format = { sizeof("NNNNNBBN"), "NNNNNBBN" };
+	struct acpi_buffer device_id = { 0, NULL };
+	union acpi_object *did;
+
+	status = acpi_evaluate_object(IPMI_ACPI_HANDLE(tester), "GDIM", NULL,
+				      &buffer);
+	if (ACPI_FAILURE(status) || !buffer.pointer) {
+		ipmi_err(tester, "Evaluating GDIM, status - %d\n", status);
+		return -ENODEV;
+	}
+
+	did = buffer.pointer;
+	if (did->type != ACPI_TYPE_PACKAGE || did->package.count != 8) {
+		ipmi_err(tester, "Invalid GDIM data, type - %d, count - %d\n",
+			 did->type, did->package.count);
+		res = -EFAULT;
+		goto err_buf;
+	}
+
+	device_id.length = sizeof(struct acpi_ipmi_device_id);
+	device_id.pointer = &tester->device_id;
+
+	status = acpi_extract_package(did, &format, &device_id);
+	if (ACPI_FAILURE(status)) {
+		ipmi_err(tester, "Invalid GDIM data\n");
+		res = -EFAULT;
+		goto err_buf;
+	}
+
+err_buf:
+	kfree(buffer.pointer);
+	return res;
+}
+
+static ssize_t show_device_id(struct device *device,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	struct acpi_device *adev = to_acpi_device(device);
+	struct acpi_ipmi_tester *tester = adev->driver_data;
+
+	acpi_ipmi_update_device_id(tester);
+	return sprintf(buf, "%llu\n", tester->device_id.device_id);
+}
+
+static ssize_t show_device_rev(struct device *device,
+			       struct device_attribute *attr,
+			       char *buf)
+{
+	struct acpi_device *adev = to_acpi_device(device);
+	struct acpi_ipmi_tester *tester = adev->driver_data;
+
+	acpi_ipmi_update_device_id(tester);
+	return sprintf(buf, "%llu\n", tester->device_id.device_rev);
+}
+
+static ssize_t show_firmware_rev(struct device *device,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct acpi_device *adev = to_acpi_device(device);
+	struct acpi_ipmi_tester *tester = adev->driver_data;
+
+	acpi_ipmi_update_device_id(tester);
+	return sprintf(buf, "%llu\n", tester->device_id.firmware_rev);
+}
+
+static ssize_t show_ipmi_version(struct device *device,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct acpi_device *adev = to_acpi_device(device);
+	struct acpi_ipmi_tester *tester = adev->driver_data;
+
+	acpi_ipmi_update_device_id(tester);
+	return sprintf(buf, "%llu\n", tester->device_id.ipmi_version);
+}
+
+static ssize_t show_vendor_id(struct device *device,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	struct acpi_device *adev = to_acpi_device(device);
+	struct acpi_ipmi_tester *tester = adev->driver_data;
+
+	acpi_ipmi_update_device_id(tester);
+	return sprintf(buf, "%02x %02x %02x\n",
+		       tester->device_id.vendor_id[0],
+		       tester->device_id.vendor_id[1],
+		       tester->device_id.vendor_id[2]);
+}
+
+static ssize_t show_product_id(struct device *device,
+			       struct device_attribute *attr,
+			       char *buf)
+{
+	struct acpi_device *adev = to_acpi_device(device);
+	struct acpi_ipmi_tester *tester = adev->driver_data;
+
+	acpi_ipmi_update_device_id(tester);
+	return sprintf(buf, "%02x %02x\n",
+		       tester->device_id.product_id[0],
+		       tester->device_id.product_id[1]);
+}
+
+static DEVICE_ATTR(device_id, S_IRUGO, show_device_id, NULL);
+static DEVICE_ATTR(device_rev, S_IRUGO, show_device_rev, NULL);
+static DEVICE_ATTR(firmware_rev, S_IRUGO, show_firmware_rev, NULL);
+static DEVICE_ATTR(ipmi_version, S_IRUGO, show_ipmi_version, NULL);
+static DEVICE_ATTR(vendor_id, S_IRUGO, show_vendor_id, NULL);
+static DEVICE_ATTR(product_id, S_IRUGO, show_product_id, NULL);
+
+static struct attribute *acpi_ipmi_test_attrs[] = {
+	&dev_attr_device_id.attr,
+	&dev_attr_device_rev.attr,
+	&dev_attr_firmware_rev.attr,
+	&dev_attr_ipmi_version.attr,
+	&dev_attr_vendor_id.attr,
+	&dev_attr_product_id.attr,
+	NULL,
+};
+
+static struct attribute_group acpi_ipmi_test_group = {
+	.attrs	= acpi_ipmi_test_attrs,
+};
+
+static int acpi_ipmi_test_add(struct acpi_device *device)
+{
+	struct acpi_ipmi_tester *tester;
+
+	if (!device)
+		return -EINVAL;
+
+	tester = kzalloc(sizeof(struct acpi_ipmi_tester), GFP_KERNEL);
+	if (!tester)
+		return -ENOMEM;
+
+	tester->adev = device;
+	strcpy(acpi_device_name(device), ACPI_IPMI_TEST_DEVICE);
+	strcpy(acpi_device_class(device), ACPI_IPMI_TEST_CLASS);
+	device->driver_data = tester;
+	if (sysfs_create_group(&device->dev.kobj, &acpi_ipmi_test_group) == 0)
+		tester->registered_group = 1;
+
+	return 0;
+}
+
+static int acpi_ipmi_test_remove(struct acpi_device *device)
+{
+	struct acpi_ipmi_tester *tester;
+
+	if (!device || !acpi_driver_data(device))
+		return -EINVAL;
+
+	tester = acpi_driver_data(device);
+
+	if (tester->registered_group)
+		sysfs_remove_group(&device->dev.kobj, &acpi_ipmi_test_group);
+
+	kfree(tester);
+	return 0;
+}
+
+static struct acpi_driver acpi_ipmi_test_driver = {
+	.name = "ipmi_test",
+	.class = ACPI_IPMI_TEST_CLASS,
+	.ids = acpi_ipmi_test_ids,
+	.ops = {
+		.add = acpi_ipmi_test_add,
+		.remove = acpi_ipmi_test_remove,
+	},
+};
+
+static int __init acpi_ipmi_test_init(void)
+{
+	return acpi_bus_register_driver(&acpi_ipmi_test_driver);
+}
+module_init(acpi_ipmi_test_init);
+
+static void __exit acpi_ipmi_test_exit(void)
+{
+	acpi_bus_unregister_driver(&acpi_ipmi_test_driver);
+}
+module_exit(acpi_ipmi_test_exit);
+
+MODULE_AUTHOR("Lv Zheng <lv.zheng@...el.com>");
+MODULE_DESCRIPTION("ACPI IPMI operation region tester driver");
+MODULE_LICENSE("GPL");
-- 
1.7.10

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ