2013-05-15 03:13:22

by Ren Qiaowei

[permalink] [raw]
Subject: [PATCH v3 0/3] Intel TXT driver

Changeslog from v2:
* add MODULE_ALIAS()

Changeslog from v1:
* remove tboot log code
* add terms description in commit log and comment at the top of the driver
* check whether a platform has TXT support before registering a device

This module is expected to be a better tool to access below resources
- TXT config space
- SMX parameter

Intel TXT (Trusted Execution Technology) will provide higher assurance
of system configuration and initial state as well as data reset
protection. It also helps solve real end user concerns about having
confidence that their hardware is running the VMM or kernel that
it was configured with, especially since they may be responsible for
providing such assurances to VMs and services running on it.

See Documentation/intel_txt.txt for more information about Intel TXT.

Intel TXT configuration registers are a subset of chipset registers.
These chipset registers that interact with SMX are accessed from two
regions of memory, which represent the public and private configuration
spaces, by system software using memory read/write protocols.

Safer Mode Extensions (SMX) provide a processor's programming
interface in an Intel TXT platform for system software to establish
a measured environment within the platform to support trust decisions
by end users.

With this module, it will be easier to access TXT related information.

Qiaowei Ren (3):
driver: add TXT driver in kernel
driver: provide sysfs interfaces to access TXT config space
driver: provide sysfs interfaces to access SMX parameter

Documentation/ABI/testing/sysfs-platform-intel-txt | 382 ++++++++
drivers/platform/x86/Kconfig | 2 +
drivers/platform/x86/Makefile | 1 +
drivers/platform/x86/intel_txt/Kconfig | 27 +
drivers/platform/x86/intel_txt/Makefile | 5 +
drivers/platform/x86/intel_txt/txt-config.c | 1029 ++++++++++++++++++++
drivers/platform/x86/intel_txt/txt-config.h | 138 +++
drivers/platform/x86/intel_txt/txt-parameter.c | 254 +++++
drivers/platform/x86/intel_txt/txt-parameter.h | 39 +
drivers/platform/x86/intel_txt/txt-sysfs.c | 80 ++
10 files changed, 1957 insertions(+)
create mode 100644 Documentation/ABI/testing/sysfs-platform-intel-txt
create mode 100644 drivers/platform/x86/intel_txt/Kconfig
create mode 100644 drivers/platform/x86/intel_txt/Makefile
create mode 100644 drivers/platform/x86/intel_txt/txt-config.c
create mode 100644 drivers/platform/x86/intel_txt/txt-config.h
create mode 100644 drivers/platform/x86/intel_txt/txt-parameter.c
create mode 100644 drivers/platform/x86/intel_txt/txt-parameter.h
create mode 100644 drivers/platform/x86/intel_txt/txt-sysfs.c

--
1.7.9.5


2013-05-15 03:13:46

by Ren Qiaowei

[permalink] [raw]
Subject: [PATCH v3 3/3] driver: provide sysfs interfaces to access SMX parameter

These interfaces are located in /sys/devices/platform/intel_txt/parameter/,
showing specific parameter information for SMX features supported by
the processor.

Safer Mode Extensions (SMX) provide a processor's programming
interface in an Intel TXT platform for system software to establish
a measured environment within the platform to support trust decisions
by end users.

Signed-off-by: Qiaowei Ren <[email protected]>
Signed-off-by: Xiaoyan Zhang <[email protected]>
Signed-off-by: Gang Wei <[email protected]>
---
Documentation/ABI/testing/sysfs-platform-intel-txt | 73 ++++++
drivers/platform/x86/intel_txt/Makefile | 2 +-
drivers/platform/x86/intel_txt/txt-parameter.c | 254 ++++++++++++++++++++
drivers/platform/x86/intel_txt/txt-parameter.h | 39 +++
drivers/platform/x86/intel_txt/txt-sysfs.c | 5 +
5 files changed, 372 insertions(+), 1 deletion(-)
create mode 100644 drivers/platform/x86/intel_txt/txt-parameter.c
create mode 100644 drivers/platform/x86/intel_txt/txt-parameter.h

diff --git a/Documentation/ABI/testing/sysfs-platform-intel-txt b/Documentation/ABI/testing/sysfs-platform-intel-txt
index fa20a9f..b445f5d 100644
--- a/Documentation/ABI/testing/sysfs-platform-intel-txt
+++ b/Documentation/ABI/testing/sysfs-platform-intel-txt
@@ -307,3 +307,76 @@ Contact: "Qiaowei Ren" <[email protected]>
Description: 0 = Chipset acknowledges that no secrets are in memory.
1 = Chipset believes that secrets are in memory and will
provide reset protection.
+
+What: /sys/devices/platform/intel_txt/parameter/
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: The parameter/ directory exposes specific parameter
+ information for SMX features supported by the processor.
+
+ Safer Mode Extensions (SMX) provide a processor's
+ programming interface in an Intel TXT platform for
+ system software to establish a measured environment
+ within the platform to support trust decisions by
+ end users.
+
+What: /sys/devices/platform/intel_txt/parameter/acm_max_size
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: The "acm_max_size" property will show max size of
+ authenticated code execution area.
+
+What: /sys/devices/platform/intel_txt/parameter/acm_mem_types
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: The "acm_max_types" property will show supportable memory
+ types for memory mapped outside of the authenticated code
+ execution area.
+
+What: /sys/devices/platform/intel_txt/parameter/senter_controls
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: The "senter_controls" property will show selective SENTER
+ functionality control.
+
+What: /sys/devices/platform/intel_txt/parameter/preserve_mce
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: The "preserve_mce" property produces a '1' if machine
+ check status registers can be preserved through ENTERACCS
+ and SENTER.
+
+What: /sys/devices/platform/intel_txt/parameter/proc_based_scrtm
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: The "proc_based_scrtm" property produces a '1' if this
+ processor implements a processorrooted S-CRTM capability
+ and '0' if not (S-CRTM is rooted in BIOS).
+
+What: /sys/devices/platform/intel_txt/parameter/n_versions
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: The "n_versions" property will show AC module version
+ numbers supported.
+
+What: /sys/devices/platform/intel_txt/parameter/acm_version
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: The "acm_version" property will output supported AC
+ module version, including version comparison mask and
+ version index.
+
+What: /sys/devices/platform/intel_txt/parameter/acm_version_index
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: The "acm_version_index" property allows you to set the
+ version index for output.
diff --git a/drivers/platform/x86/intel_txt/Makefile b/drivers/platform/x86/intel_txt/Makefile
index 8d5258e..8370582 100644
--- a/drivers/platform/x86/intel_txt/Makefile
+++ b/drivers/platform/x86/intel_txt/Makefile
@@ -2,4 +2,4 @@
# Makefile for the intel TXT drivers.
#
obj-$(CONFIG_INTEL_TXT_DRIVER) += intel_txt.o
-intel_txt-y := txt-sysfs.o txt-config.o
+intel_txt-y := txt-sysfs.o txt-config.o txt-parameter.o
diff --git a/drivers/platform/x86/intel_txt/txt-parameter.c b/drivers/platform/x86/intel_txt/txt-parameter.c
new file mode 100644
index 0000000..a0073bf
--- /dev/null
+++ b/drivers/platform/x86/intel_txt/txt-parameter.c
@@ -0,0 +1,254 @@
+/*
+ * txt-parameter.c
+ *
+ * specific parameter information for SMX features supported by the processor.
+ *
+ * Safer Mode Extensions (SMX) provide a processor's programming
+ * interface in an Intel TXT platform for system software to establish
+ * a measured environment within the platform to support trust decisions
+ * by end users.
+ *
+ * - parameter/
+ * n_versions -r--r--r--;
+ * acm_max_size -r--r--r--;
+ * acm_mem_types -r--r--r--;
+ * senter_controls -r--r--r--;
+ * proc_based_scrtm -r--r--r--;
+ * preserve_mce -r--r--r--;
+ * acm_version_index -rw-rw-r--; desginate which acm_version will be output
+ * acm_version -r--r--r--;
+ */
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sysfs.h>
+
+#include "txt-parameter.h"
+
+static u32 acm_version_index;
+
+static void __getsec_parameters(uint32_t index, int *param_type,
+ uint32_t *peax, uint32_t *pebx,
+ uint32_t *pecx)
+{
+ uint32_t eax, ebx, ecx;
+
+ __asm__ __volatile__ ("getsec"
+ : "=a"(eax), "=b"(ebx), "=c"(ecx)
+ : "a"(IA32_GETSEC_PARAMETERS), "b"(index));
+
+ *param_type = eax & 0x1f;
+ *peax = eax;
+ *pebx = ebx;
+ *pecx = ecx;
+}
+
+static bool get_parameters(struct getsec_parameters *params)
+{
+ uint32_t index, eax, ebx, ecx;
+ int param_type;
+
+ memset(params, 0, sizeof(struct getsec_parameters));
+ params->acm_max_size = DEF_ACM_MAX_SIZE;
+ params->acm_mem_types = DEF_ACM_MEM_TYPES;
+ params->senter_controls = DEF_SENTER_CTRLS;
+ params->proc_based_scrtm = false;
+ params->preserve_mce = false;
+
+ index = 0;
+ do {
+ __getsec_parameters(index++, &param_type, &eax, &ebx, &ecx);
+
+ switch (param_type) {
+ case 1:
+ if (params->n_versions == MAX_SUPPORTED_ACM_VERSIONS)
+ continue;
+ params->acm_versions[params->n_versions].mask = ebx;
+ params->acm_versions[params->n_versions].version = ecx;
+ params->n_versions++;
+ break;
+
+ case 2:
+ params->acm_max_size = eax & 0xffffffe0;
+ break;
+
+ case 3:
+ params->acm_mem_types = eax & 0xffffffe0;
+ break;
+
+ case 4:
+ params->senter_controls = (eax & 0x00007fff) >> 8;
+ break;
+
+ case 5:
+ params->proc_based_scrtm =
+ (eax & 0x00000020) ? true : false;
+ params->preserve_mce =
+ (eax & 0x00000040) ? true : false;
+ break;
+
+ default:
+ param_type = 0;
+ break;
+ }
+ } while (param_type != 0);
+
+ if (params->n_versions == 0) {
+ params->acm_versions[0].mask = DEF_ACM_VER_MASK;
+ params->acm_versions[0].version = DEF_ACM_VER_SUPPORTED;
+ params->n_versions = 1;
+ }
+
+ return true;
+}
+
+static ssize_t show_param(char *buf, u32 index)
+{
+ struct getsec_parameters params;
+
+ if (!get_parameters(&params))
+ return -EPERM;
+
+ switch (index) {
+ case off_n_versions:
+ return scnprintf(buf, PAGE_SIZE, "%d\n",
+ params.n_versions);
+
+ case off_acm_max_size:
+ return scnprintf(buf, PAGE_SIZE, "%u\n",
+ params.acm_max_size);
+
+ case off_acm_mem_types:
+ return scnprintf(buf, PAGE_SIZE, "%u\n",
+ params.acm_mem_types);
+
+ case off_senter_controls:
+ return scnprintf(buf, PAGE_SIZE, "%u\n",
+ params.senter_controls);
+
+ case off_proc_based_scrtm:
+ return scnprintf(buf, PAGE_SIZE, "%d\n",
+ params.proc_based_scrtm);
+
+ case off_preserve_mce:
+ return scnprintf(buf, PAGE_SIZE, "%d\n",
+ params.preserve_mce);
+
+ case off_acm_version:
+ return scnprintf(buf, PAGE_SIZE,
+ "mask: %u\nversion: %u\n",
+ params.acm_versions[acm_version_index].mask,
+ params.acm_versions[acm_version_index].version);
+
+ default:
+ return -EINVAL;
+ }
+}
+
+ssize_t txt_show_param_nversions(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return show_param(buf, off_n_versions);
+}
+static DEVICE_ATTR(n_versions, S_IRUGO, txt_show_param_nversions, NULL);
+
+ssize_t txt_show_param_acmmaxsize(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return show_param(buf, off_acm_max_size);
+}
+static DEVICE_ATTR(acm_max_size, S_IRUGO, txt_show_param_acmmaxsize, NULL);
+
+ssize_t txt_show_param_acmmemtypes(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return show_param(buf, off_acm_mem_types);
+}
+static DEVICE_ATTR(acm_mem_types, S_IRUGO, txt_show_param_acmmemtypes, NULL);
+
+ssize_t txt_show_param_senter(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return show_param(buf, off_senter_controls);
+}
+static DEVICE_ATTR(senter_controls, S_IRUGO, txt_show_param_senter, NULL);
+
+ssize_t txt_show_param_proc(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return show_param(buf, off_proc_based_scrtm);
+}
+static DEVICE_ATTR(proc_based_scrtm, S_IRUGO, txt_show_param_proc, NULL);
+
+ssize_t txt_show_param_preserve(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return show_param(buf, off_preserve_mce);
+}
+static DEVICE_ATTR(preserve_mce, S_IRUGO, txt_show_param_preserve, NULL);
+
+ssize_t txt_show_param_acmvindex(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return scnprintf(buf, PAGE_SIZE, "%d\n", acm_version_index);
+}
+
+ssize_t txt_store_param_acmvindex(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ u32 index;
+ struct getsec_parameters params;
+
+ if (sscanf(buf, "%d", &index) != 1)
+ return -EINVAL;
+
+ if (!get_parameters(&params))
+ return -EPERM;
+
+ if (index >= params.n_versions)
+ return -EINVAL;
+
+ acm_version_index = index;
+
+ return count;
+}
+static DEVICE_ATTR(acm_version_index, S_IRUGO | S_IWUSR | S_IWGRP,
+ txt_show_param_acmvindex, txt_store_param_acmvindex);
+
+ssize_t txt_show_param_acmversion(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return show_param(buf, off_acm_version);
+}
+static DEVICE_ATTR(acm_version, S_IRUGO, txt_show_param_acmversion, NULL);
+
+static struct attribute *param_attrs[] = {
+ &dev_attr_n_versions.attr,
+ &dev_attr_acm_max_size.attr,
+ &dev_attr_acm_mem_types.attr,
+ &dev_attr_senter_controls.attr,
+ &dev_attr_proc_based_scrtm.attr,
+ &dev_attr_preserve_mce.attr,
+ &dev_attr_acm_version_index.attr,
+ &dev_attr_acm_version.attr,
+ NULL,
+};
+
+static struct attribute_group param_attr_grp = {
+ .name = "parameter",
+ .attrs = param_attrs
+};
+
+int sysfs_create_parameter(struct kobject *parent)
+{
+ return sysfs_create_group(parent, &param_attr_grp);
+}
+
diff --git a/drivers/platform/x86/intel_txt/txt-parameter.h b/drivers/platform/x86/intel_txt/txt-parameter.h
new file mode 100644
index 0000000..55b232b
--- /dev/null
+++ b/drivers/platform/x86/intel_txt/txt-parameter.h
@@ -0,0 +1,39 @@
+#ifndef __PARAMETER_H__
+#define __PARAMETER_H__
+
+#define CR4_SMXE 0x00004000
+#define MAX_SUPPORTED_ACM_VERSIONS 16
+
+#define DEF_ACM_MAX_SIZE 0x8000
+#define DEF_ACM_VER_MASK 0xffffffff
+#define DEF_ACM_VER_SUPPORTED 0x00
+#define DEF_ACM_MEM_TYPES 0x0100
+#define DEF_SENTER_CTRLS 0x00
+
+#define IA32_GETSEC_PARAMETERS 6
+
+#define off_n_versions 1
+#define off_acm_max_size 2
+#define off_acm_mem_types 3
+#define off_senter_controls 4
+#define off_proc_based_scrtm 5
+#define off_preserve_mce 6
+#define off_acm_version 7
+
+typedef struct getsec_parameters {
+ struct {
+ uint32_t mask;
+ uint32_t version;
+ } acm_versions[MAX_SUPPORTED_ACM_VERSIONS];
+ int n_versions;
+ uint32_t acm_max_size;
+ uint32_t acm_mem_types;
+ uint32_t senter_controls;
+ bool proc_based_scrtm;
+ bool preserve_mce;
+} getsec_parameters_t;
+
+extern int sysfs_create_parameter(struct kobject *parent);
+
+#endif /* __PARAMETER_H__ */
+
diff --git a/drivers/platform/x86/intel_txt/txt-sysfs.c b/drivers/platform/x86/intel_txt/txt-sysfs.c
index ac889f7..256fbde 100644
--- a/drivers/platform/x86/intel_txt/txt-sysfs.c
+++ b/drivers/platform/x86/intel_txt/txt-sysfs.c
@@ -37,6 +37,7 @@
#include <linux/tboot.h>

#include "txt-config.h"
+#include "txt-parameter.h"

#define DEV_NAME "intel_txt"
static struct platform_device *txt_pdev;
@@ -56,6 +57,10 @@ static int __init txt_sysfs_init(void)
if (retval)
goto err;

+ retval = sysfs_create_parameter(&txt_pdev->dev.kobj);
+ if (retval)
+ goto err;
+
return 0;

err:
--
1.7.9.5

2013-05-15 03:13:28

by Ren Qiaowei

[permalink] [raw]
Subject: [PATCH v3 1/3] driver: add TXT driver in kernel

TXT driver can be used to access below resources:
- TXT config space
- SMX parameter

Intel TXT (Trusted Execution Technology) will provide higher
assurance of system configuration and initial state as well as
data reset protection. It also helps solve real end user concerns
about having confidence that their hardware is running the VMM
or kernel that it was configured with, especially since they may
be responsible for providing such assurances to VMs and services
running on it.

See Documentation/intel_txt.txt for more information about
Intel TXT.

Intel TXT configuration registers are a subset of chipset registers.
These chipset registers that interact with SMX are accessed from two
regions of memory, which represent the public and private configuration
spaces, by system software using memory read/write protocols.

Safer Mode Extensions (SMX) provide a processor's programming
interface in an Intel TXT platform for system software to establish
a measured environment within the platform to support trust decisions
by end users.

Signed-off-by: Qiaowei Ren <[email protected]>
Signed-off-by: Xiaoyan Zhang <[email protected]>
Signed-off-by: Gang Wei <[email protected]>
---
drivers/platform/x86/Kconfig | 2 +
drivers/platform/x86/Makefile | 1 +
drivers/platform/x86/intel_txt/Kconfig | 27 ++++++++++++
drivers/platform/x86/intel_txt/Makefile | 5 +++
drivers/platform/x86/intel_txt/txt-sysfs.c | 63 ++++++++++++++++++++++++++++
5 files changed, 98 insertions(+)
create mode 100644 drivers/platform/x86/intel_txt/Kconfig
create mode 100644 drivers/platform/x86/intel_txt/Makefile
create mode 100644 drivers/platform/x86/intel_txt/txt-sysfs.c

diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 8577261..97173e3 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -693,6 +693,8 @@ config INTEL_IPS
functionality. If in doubt, say Y here; it will only load on
supported platforms.

+source "drivers/platform/x86/intel_txt/Kconfig"
+
config IBM_RTL
tristate "Device driver to enable PRTL support"
depends on X86 && PCI
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index ef0ec74..91541ac 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o
obj-$(CONFIG_INTEL_SCU_IPC_UTIL) += intel_scu_ipcutil.o
obj-$(CONFIG_INTEL_MFLD_THERMAL) += intel_mid_thermal.o
obj-$(CONFIG_INTEL_IPS) += intel_ips.o
+obj-$(CONFIG_INTEL_TXT_DRIVER) += intel_txt/
obj-$(CONFIG_GPIO_INTEL_PMIC) += intel_pmic_gpio.o
obj-$(CONFIG_XO1_RFKILL) += xo1-rfkill.o
obj-$(CONFIG_XO15_EBOOK) += xo15-ebook.o
diff --git a/drivers/platform/x86/intel_txt/Kconfig b/drivers/platform/x86/intel_txt/Kconfig
new file mode 100644
index 0000000..dd81b21
--- /dev/null
+++ b/drivers/platform/x86/intel_txt/Kconfig
@@ -0,0 +1,27 @@
+#
+# intel TXT driver configuration
+#
+
+config INTEL_TXT_DRIVER
+ tristate "INTEL TXT sysfs driver"
+ default m
+ depends on INTEL_TXT
+ select SECURITYFS
+ ---help---
+ TXT Driver can be used to access below resources:
+ - TXT config space
+ - SMX parameter
+
+ Intel TXT configuration registers are a subset of chipset
+ registers. These chipset registers that interact with SMX
+ are accessed from two regions of memory, which represent
+ the public and private configuration spaces, by system
+ software using memory read/write protocols.
+
+ Safer Mode Extensions (SMX) provide a processor's programming
+ interface in an Intel TXT platform for system software to
+ establish a measured environment within the platform to support
+ trust decisions by end users.
+
+ To compile this driver as a module, choose M here; the module
+ will be called intel_txt.
diff --git a/drivers/platform/x86/intel_txt/Makefile b/drivers/platform/x86/intel_txt/Makefile
new file mode 100644
index 0000000..a130308
--- /dev/null
+++ b/drivers/platform/x86/intel_txt/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the intel TXT drivers.
+#
+obj-$(CONFIG_INTEL_TXT_DRIVER) += intel_txt.o
+intel_txt-y := txt-sysfs.o
diff --git a/drivers/platform/x86/intel_txt/txt-sysfs.c b/drivers/platform/x86/intel_txt/txt-sysfs.c
new file mode 100644
index 0000000..def33cb
--- /dev/null
+++ b/drivers/platform/x86/intel_txt/txt-sysfs.c
@@ -0,0 +1,63 @@
+/*
+ * txt-sysfs.c
+ *
+ * This module can be used to access below resources
+ * - TXT config space
+ * - SMX parameter
+ *
+ * Intel TXT (Trusted Execution Technology) will provide higher
+ * assurance of system configuration and initial state as well as
+ * data reset protection. It also helps solve real end user concerns
+ * about having confidence that their hardware is running the VMM
+ * or kernel that it was configured with, especially since they may
+ * be responsible for providing such assurances to VMs and services
+ * running on it.
+ *
+ * See Documentation/intel_txt.txt for more information about
+ * Intel TXT.
+ *
+ * Intel TXT configuration registers are a subset of chipset registers.
+ * These chipset registers that interact with SMX are accessed from two
+ * regions of memory, which represent the public and private configuration
+ * spaces, by system software using memory read/write protocols.
+ *
+ * Safer Mode Extensions (SMX) provide a processor's programming
+ * interface in an Intel TXT platform for system software to establish
+ * a measured environment within the platform to support trust decisions
+ * by end users.
+ *
+ * Data can be found below
+ * /sys/devices/platform/intel_txt/...
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sysfs.h>
+#include <linux/tboot.h>
+
+#define DEV_NAME "intel_txt"
+static struct platform_device *txt_pdev;
+
+static int __init txt_sysfs_init(void)
+{
+ if (!tboot_enabled())
+ return -ENODEV;
+
+ txt_pdev = platform_device_register_simple(DEV_NAME, -1, NULL, 0);
+ if (IS_ERR(txt_pdev))
+ return PTR_ERR(txt_pdev);
+
+ return 0;
+}
+
+static void __exit txt_sysfs_exit(void)
+{
+ platform_device_unregister(txt_pdev);
+}
+
+module_init(txt_sysfs_init);
+module_exit(txt_sysfs_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:intel_txt");
--
1.7.9.5

2013-05-15 03:13:44

by Ren Qiaowei

[permalink] [raw]
Subject: [PATCH v3 2/3] driver: provide sysfs interfaces to access TXT config space

These interfaces are located in /sys/devices/platform/intel_txt/config,
and including totally 37 files, providing access to Intel TXT
configuration registers.

Signed-off-by: Qiaowei Ren <[email protected]>
Signed-off-by: Xiaoyan Zhang <[email protected]>
Signed-off-by: Gang Wei <[email protected]>
---
Documentation/ABI/testing/sysfs-platform-intel-txt | 309 ++++++
drivers/platform/x86/intel_txt/Makefile | 2 +-
drivers/platform/x86/intel_txt/txt-config.c | 1029 ++++++++++++++++++++
drivers/platform/x86/intel_txt/txt-config.h | 138 +++
drivers/platform/x86/intel_txt/txt-sysfs.c | 12 +
5 files changed, 1489 insertions(+), 1 deletion(-)
create mode 100644 Documentation/ABI/testing/sysfs-platform-intel-txt
create mode 100644 drivers/platform/x86/intel_txt/txt-config.c
create mode 100644 drivers/platform/x86/intel_txt/txt-config.h

diff --git a/Documentation/ABI/testing/sysfs-platform-intel-txt b/Documentation/ABI/testing/sysfs-platform-intel-txt
new file mode 100644
index 0000000..fa20a9f
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-platform-intel-txt
@@ -0,0 +1,309 @@
+What: /sys/devices/platform/intel_txt/config/
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: The config/ directory exposes Intel TXT configuration
+ registers. These registers are a subset of chipset registers.
+ They are mapped into two regions of memory, representing the
+ public and private configuration spaces.
+
+ Registers in the private space can only be accessed after a
+ measured environment has been established and before the
+ TXT.CMD.CLOSE-PRIVATE command has been issued. The public space
+ registers are available before, during and after a measured
+ environment launch. All registers are available within both
+ spaces, though with different permissions.
+
+What: /sys/devices/platform/intel_txt/config/STS_raw
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: TXT.STS is the general status register. This read-only register
+ is used by AC modules and the MLE to get the status of various
+ Intel TXT features.
+
+What: /sys/devices/platform/intel_txt/config/STS_enter_done
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: The chipset sets SENTER.DONE.STS status bit when it sees all
+ of the threads have done an TXT.CYC.SENTER-ACK.
+
+What: /sys/devices/platform/intel_txt/config/STS_sexit_done
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: SEXIT.DONE.STS status bit is set when all of the bits in the
+ TXT.THREADS.JOIN register are clear. Thus, this bit will be
+ set immediately after reset.
+
+What: /sys/devices/platform/intel_txt/config/STS_mem_config_lock
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: MEM-CONFIG-LOCK.STS status bit will be set to 1 when the memory
+ configuration has been locked. Cleared by
+ TXT.CMD.UNLOCK.MEMCONFIG or by a system reset.
+
+What: /sys/devices/platform/intel_txt/config/STS_private_open
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: PRIVATE-OPEN.STS status bit will be set to 1 when
+ TXT.CMD.OPEN-PRIVATE is performed. Cleared by
+ TXT.CMD.CLOSE-PRIVATE or by a system reset.
+
+What: /sys/devices/platform/intel_txt/config/STS_locality_1_open
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: TXT.LOCALITY1.OPEN.STS status bit is set when the
+ TXT.CMD.OPEN.LOCALITY1 command is seen by the chipset.
+ It is cleared on reset or when TXT.CMD.CLOSE.LOCALITY1 is seen.
+
+What: /sys/devices/platform/intel_txt/config/STS_locality_2_open
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: TXT.LOCALITY2.OPEN.STS status bit is set when either the
+ TXT.CMD.OPEN.LOCALITY2 command or the TXT.CMD.OPEN.PRIVATE
+ is seen by the chipset. It is cleared on reset, when either
+ TXT.CMD.CLOSE.LOCALITY2 or TXT.CMD.CLOSE.PRIVATE is seen,
+ and by the GETSEC[SEXIT] instruction.
+
+What: /sys/devices/platform/intel_txt/config/ESTS_raw
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: TXT.ESTS is the error status register which contains status
+ information associated with various error conditions. The
+ contents of this read-only register are preserved across
+ soft resets.
+
+What: /sys/devices/platform/intel_txt/config/ESTS_intel_txt_reset
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: TXT_RESET.STS bit is set to '1' to indicate that an event
+ occurred which may prevent the proper use of TXT (possibly
+ including a TXT reset).
+
+What: /sys/devices/platform/intel_txt/config/ERRORCODE
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: TXT.ERRORCODE register holds the Intel TXT shutdown error code.
+ A soft reset does not clear the contents of this register;
+ a hard reset/power cycle will clear the contents. This was
+ formerly labeled the TXT.CRASH register.
+
+What: /sys/devices/platform/intel_txt/config/CMD_RESET
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: A write to TXT.CMD.RESET register causes a system reset.
+ This is performed by the processor as part of an Intel TXT
+ shutdown, after writing to the TXT.ERRORCODE register.
+
+What: /sys/devices/platform/intel_txt/config/CMD_CLOSE_PRIVATE
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: A write to TXT.CMD.CLOSE-PRIVATE register causes the Intel
+ TXT-capable chipset private configuration space to be locked.
+ Locality 2 will also be closed. Once locked, conventional
+ memory read/write operations can no longer be used to access
+ these registers. The private configuration space can only be
+ opened for the MLE by successfully executing GETSEC[SENTER].
+
+What: /sys/devices/platform/intel_txt/config/VER_FSBIF
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: TXT.VER.FSBIF register identifies whether the chipset is
+ debug or release fused.
+
+What: /sys/devices/platform/intel_txt/config/DIDVID_raw
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: TXT.DIDVID register contains the vendor, device, and revision
+ IDs for the memory controller or chipset.
+
+What: /sys/devices/platform/intel_txt/config/DIDVID_vendor_id
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: Vendor ID.
+
+What: /sys/devices/platform/intel_txt/config/DIDVID_device_id
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: Device ID.
+
+What: /sys/devices/platform/intel_txt/config/DIDVID_revision_id
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: Revision ID.
+
+What: /sys/devices/platform/intel_txt/config/VER_QPIIF
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: TXT.VER.QPIIF register identifies whether the memory
+ controller or chipset is debug or release fused.
+
+What: /sys/devices/platform/intel_txt/config/CMD_UNLOCK_MEM_CONFIG
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: When TXT.CMD.UNLOCK-MEM-CONFIG command is invoked, the
+ chipset unlocks all memory configuration registers.
+
+What: /sys/devices/platform/intel_txt/config/SINIT_BASE
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: TXT.SINIT.BASE register contains the physical base address
+ of the memory region set aside by the BIOS for loading an
+ SINIT AC module. If BIOS has provided an SINIT AC module,
+ it will be located at this address. System software that
+ provides an SINIT AC module must store it to this location.
+
+What: /sys/devices/platform/intel_txt/config/SINIT_SIZE
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: TXT.SINIT.SIZE register contains the size (in bytes) of
+ the memory region set aside by the BIOS for loading an
+ SINIT AC module. This register is initialized by the BIOS.
+
+What: /sys/devices/platform/intel_txt/config/MLE_JOIN
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: Holds a physical address pointer to the base of the join
+ data structure used to initialize RLPs in response to
+ GETSEC[WAKEUP].
+
+What: /sys/devices/platform/intel_txt/config/HEAP_BASE
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: TXT.HEAP.BASE register contains the physical base address
+ of the Intel TXT Heap memory region. The BIOS initializes
+ this register.
+
+What: /sys/devices/platform/intel_txt/config/HEAP_SIZE
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: TXT.HEAP.SIZE register contains the size (in bytes) of the
+ Intel TXT Heap memory region. The BIOS initializes this
+ register.
+
+What: /sys/devices/platform/intel_txt/config/DPR_raw
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: TXT.DPR register defines the DMA Protected Range of memory
+ in which the TXT heap and SINIT region are located.
+
+What: /sys/devices/platform/intel_txt/config/DPR_lock
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: Bits 19:0 are locked down in this register when this Lock
+ bit is set.
+
+What: /sys/devices/platform/intel_txt/config/DPR_top
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: Top address + 1 of DPR.
+
+What: /sys/devices/platform/intel_txt/config/DPR_size
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: This is the size of memory, in MB, that will be protected from
+ DMA accesses. A value of 0x00 in this field means no additional
+ memory is protected.
+
+What: /sys/devices/platform/intel_txt/config/CMD_OPEN_LOCALITY1
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: Writing to this TXT.CMD.OPEN.LOCALITY1 register "opens" the
+ TPM locality 1 address range, enabling decoding by the chipset
+ and thus access to the TPM.
+
+What: /sys/devices/platform/intel_txt/config/CMD_CLOSE_LOCALITY1
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: Writing to this TXT.CMD.CLOSE.LOCALITY1 register "closes" the
+ TPM locality 1 address range, disabling decoding by the chipset
+ and thus access to the TPM.
+
+What: /sys/devices/platform/intel_txt/config/CMD_OPEN_LOCALITY2
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: Writing to this TXT.CMD.OPEN.LOCALITY2 register "opens" the
+ TPM locality 2 address range, enabling decoding by the chipset
+ and thus access to the TPM.
+
+What: /sys/devices/platform/intel_txt/config/CMD_CLOSE_LOCALITY2
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: Writing to this TXT.CMD.CLOSE.LOCALITY2 register "closes" the
+ TPM locality 2 address range, disabling decoding by the chipset
+ and thus access to the TPM.
+
+What: /sys/devices/platform/intel_txt/config/PUBLIC_KEY
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: This read-only TXT.PUBLIC.KEY register contains the hash of
+ the public key used for the verification of AC Modules.
+ The size, hash algorithm, and value are specific to the memory
+ controller or chipset.
+
+What: /sys/devices/platform/intel_txt/config/CMD_SECRETS
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: Writing to this TXT.CMD.SECRETS register indicates to the
+ chipset that there are secrets in memory. The chipset tracks
+ this fact with a sticky bit. If the platform reboots with this
+ sticky bit set the BIOS AC module (or BIOS on multiprocessor
+ TXT systems) will scrub memory. The chipset also uses this
+ bit to detect invalid sleep state transitions. If software
+ tries to transition to S3, S4, or S5 while secrets are in
+ memory then the chipset will reset the system.
+
+What: /sys/devices/platform/intel_txt/config/CMD_NO_SECRETS
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: Writing to this TXT.CMD.NO-SECRETS register indicates there
+ are no secrets in memory.
+
+What: /sys/devices/platform/intel_txt/config/E2STS_raw
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: This TXT.E2STS register is used to read the status associated
+ with various errors that might be detected.
+
+What: /sys/devices/platform/intel_txt/config/E2STS_secrets
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <[email protected]>
+Description: 0 = Chipset acknowledges that no secrets are in memory.
+ 1 = Chipset believes that secrets are in memory and will
+ provide reset protection.
diff --git a/drivers/platform/x86/intel_txt/Makefile b/drivers/platform/x86/intel_txt/Makefile
index a130308..8d5258e 100644
--- a/drivers/platform/x86/intel_txt/Makefile
+++ b/drivers/platform/x86/intel_txt/Makefile
@@ -2,4 +2,4 @@
# Makefile for the intel TXT drivers.
#
obj-$(CONFIG_INTEL_TXT_DRIVER) += intel_txt.o
-intel_txt-y := txt-sysfs.o
+intel_txt-y := txt-sysfs.o txt-config.o
diff --git a/drivers/platform/x86/intel_txt/txt-config.c b/drivers/platform/x86/intel_txt/txt-config.c
new file mode 100644
index 0000000..c16b7e7
--- /dev/null
+++ b/drivers/platform/x86/intel_txt/txt-config.c
@@ -0,0 +1,1029 @@
+/*
+ * txt-config.c
+ *
+ * Totally 37 sysfs files with owner root, each related with a register.
+ *
+ * Intel TXT configuration registers are a subset of chipset registers.
+ * These registers are mapped into two regions of memory, representing
+ * the public and private configuration spaces.
+ *
+ * STS_raw -r--r--r-- ERRORCODE -rw-rw-r--
+ * STS_senter_done -r--r--r-- STS_sexit_done -r--r--r--
+ * STS_mem_config_lock -r--r--r-- STS_private_open -r--r--r--
+ * STS_locality_1_open -r--r--r-- STS_locality_2_open -r--r--r--
+ * ESTS_raw -r--r--r-- ESTS_txt_reset -r--r--r--
+ * E2STS_raw -r--r--r-- E2STS_secrets -rw-rw-r--
+ * VER_FSBIF -r--r--r-- VER_QPIIF -r--r--r--
+ * DIDVID_raw -r--r--r-- DIDVID_vendor_id -r--r--r--
+ * DIDVID_device_id -r--r--r-- DIDVID_revision_id -r--r--r--
+ * SINIT_BASE -rw-rw-r-- SINIT_SIZE -rw-rw-r--
+ * HEAP_BASE -rw-rw-r-- HEAP_SIZE -rw-rw-r--
+ * PUBLIC_KEY -r--r--r-- MLE_JOIN -rw-rw-r--
+ * DPR_raw -rw-rw-r-- DPR_lock -rw-rw-r--
+ * DPR_top -rw-rw-r-- DPR_size -rw-rw-r--
+ * CMD_RESET --w--w---- CMD_CLOSE_PRIVATE --w--w----
+ * CMD_SECRETS --w--w---- CMD_NO_SECRETS --w--w----
+ * CMD_OPEN_LOCALITY1 --w--w---- CMD_OPEN_LOCALITY2 --w--w----
+ * CMD_CLOSE_LOCALITY1 --w--w---- CMD_CLOSE_LOCALITY2 --w--w----
+ * CMD_UNLOCK_MEM_CONFIG --w--w----
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sysfs.h>
+#include <linux/io.h>
+#include <linux/stat.h>
+
+#include "txt-config.h"
+
+static ssize_t print_hex(char *buf, void *start, size_t len)
+{
+ char *str = buf;
+ int i;
+
+ for (i = 0; i < len; i++) {
+ str += scnprintf(str, PAGE_SIZE, "%02x ", *(uint8_t *)start);
+ start++;
+ if ((i + 1) % 16 == 0)
+ str += scnprintf(str, PAGE_SIZE, "\n");
+ }
+
+ return str - buf;
+}
+
+static ssize_t show_config(char *buf, u32 offset)
+{
+ void __iomem *config;
+ int retval;
+
+ config = ioremap_nocache(TXT_PUB_CONFIG_REGS_BASE,
+ TXT_CONFIG_REGS_SIZE);
+ if (config == NULL)
+ return -ENOMEM;
+
+ switch (offset) {
+ case off_STS_raw:
+ {
+ txt_sts_t sts;
+
+ sts._raw = read_txt_config_reg(config, TXTCR_STS);
+ retval = scnprintf(buf, PAGE_SIZE, "0x%08llx\n", sts._raw);
+ break;
+ }
+
+ case off_STS_senter_done:
+ {
+ txt_sts_t sts;
+
+ sts._raw = read_txt_config_reg(config, TXTCR_STS);
+ retval = scnprintf(buf, PAGE_SIZE, "%d\n", sts.senter_done_sts);
+ break;
+ }
+
+ case off_STS_sexit_done:
+ {
+ txt_sts_t sts;
+
+ sts._raw = read_txt_config_reg(config, TXTCR_STS);
+ retval = scnprintf(buf, PAGE_SIZE, "%d\n", sts.sexit_done_sts);
+ break;
+ }
+
+ case off_STS_mem_config_lock:
+ {
+ txt_sts_t sts;
+
+ sts._raw = read_txt_config_reg(config, TXTCR_STS);
+ retval = scnprintf(buf, PAGE_SIZE, "%d\n",
+ sts.mem_config_lock_sts);
+ break;
+ }
+
+ case off_STS_private_open:
+ {
+ txt_sts_t sts;
+
+ sts._raw = read_txt_config_reg(config, TXTCR_STS);
+ retval = scnprintf(buf, PAGE_SIZE, "%d\n",
+ sts.private_open_sts);
+ break;
+ }
+
+ case off_STS_locality_1_open:
+ {
+ txt_sts_t sts;
+
+ sts._raw = read_txt_config_reg(config, TXTCR_STS);
+ retval = scnprintf(buf, PAGE_SIZE, "%d\n",
+ sts.locality_1_open_sts);
+ break;
+ }
+
+ case off_STS_locality_2_open:
+ {
+ txt_sts_t sts;
+
+ sts._raw = read_txt_config_reg(config, TXTCR_STS);
+ retval = scnprintf(buf, PAGE_SIZE, "%d\n",
+ sts.locality_2_open_sts);
+ break;
+ }
+
+ case off_ERRORCODE:
+ retval = scnprintf(buf, PAGE_SIZE, "0x%08llx\n",
+ read_txt_config_reg(config, TXTCR_ERRORCODE));
+ break;
+
+ case off_ESTS_raw:
+ {
+ txt_ests_t ests;
+
+ ests._raw = read_txt_config_reg(config, TXTCR_ESTS);
+ retval = scnprintf(buf, PAGE_SIZE, "0x%02llx\n", ests._raw);
+ break;
+ }
+
+ case off_ESTS_txt_reset:
+ {
+ txt_ests_t ests;
+
+ ests._raw = read_txt_config_reg(config, TXTCR_ESTS);
+ retval = scnprintf(buf, PAGE_SIZE, "%d\n", ests.txt_reset_sts);
+ break;
+ }
+
+ case off_E2STS_raw:
+ {
+ txt_e2sts_t e2sts;
+
+ e2sts._raw = read_txt_config_reg(config, TXTCR_E2STS);
+ retval = scnprintf(buf, PAGE_SIZE, "0x%016llx\n", e2sts._raw);
+ break;
+ }
+
+ case off_E2STS_secrets:
+ {
+ txt_e2sts_t e2sts;
+
+ e2sts._raw = read_txt_config_reg(config, TXTCR_E2STS);
+ retval = scnprintf(buf, PAGE_SIZE, "%d\n", e2sts.secrets_sts);
+ break;
+ }
+
+ case off_VER_FSBIF:
+ retval = scnprintf(buf, PAGE_SIZE, "0x%016llx\n",
+ read_txt_config_reg(config, TXTCR_VER_FSBIF));
+ break;
+
+ case off_VER_QPIIF:
+ retval = scnprintf(buf, PAGE_SIZE, "0x%016llx\n",
+ read_txt_config_reg(config, TXTCR_VER_QPIIF));
+ break;
+
+ case off_DIDVID_raw:
+ {
+ txt_didvid_t didvid;
+
+ didvid._raw = read_txt_config_reg(config, TXTCR_DIDVID);
+ retval = scnprintf(buf, PAGE_SIZE, "0x%016llx\n", didvid._raw);
+ break;
+ }
+
+ case off_DIDVID_vendor_id:
+ {
+ txt_didvid_t didvid;
+
+ didvid._raw = read_txt_config_reg(config, TXTCR_DIDVID);
+ retval = scnprintf(buf, PAGE_SIZE, "0x%x\n", didvid.vendor_id);
+ break;
+ }
+
+ case off_DIDVID_device_id:
+ {
+ txt_didvid_t didvid;
+
+ didvid._raw = read_txt_config_reg(config, TXTCR_DIDVID);
+ retval = scnprintf(buf, PAGE_SIZE, "0x%x\n", didvid.device_id);
+ break;
+ }
+
+ case off_DIDVID_revision_id:
+ {
+ txt_didvid_t didvid;
+
+ didvid._raw = read_txt_config_reg(config, TXTCR_DIDVID);
+ retval = scnprintf(buf, PAGE_SIZE, "0x%x\n",
+ didvid.revision_id);
+ break;
+ }
+
+ case off_SINIT_BASE:
+ retval = scnprintf(buf, PAGE_SIZE, "0x%08llx\n",
+ read_txt_config_reg(config, TXTCR_SINIT_BASE));
+ break;
+
+ case off_SINIT_SIZE:
+ retval = scnprintf(buf, PAGE_SIZE, "%lluB (0x%llx)\n",
+ read_txt_config_reg(config, TXTCR_SINIT_SIZE),
+ read_txt_config_reg(config, TXTCR_SINIT_SIZE));
+ break;
+
+ case off_HEAP_BASE:
+ retval = scnprintf(buf, PAGE_SIZE, "0x%08llx\n",
+ read_txt_config_reg(config, TXTCR_HEAP_BASE));
+ break;
+
+ case off_HEAP_SIZE:
+ retval = scnprintf(buf, PAGE_SIZE, "%lluB (0x%llx)\n",
+ read_txt_config_reg(config, TXTCR_HEAP_SIZE),
+ read_txt_config_reg(config, TXTCR_HEAP_SIZE));
+ break;
+
+ case off_PUBLIC_KEY:
+ {
+ uint8_t key[256/8];
+ unsigned int i = 0;
+
+ do {
+ *(uint64_t *)&key[i] = read_txt_config_reg(config,
+ TXTCR_PUBLIC_KEY + i);
+ i += sizeof(uint64_t);
+ } while (i < sizeof(key));
+
+ retval = print_hex(buf, key, sizeof(key));
+ break;
+ }
+
+ case off_MLE_JOIN:
+ retval = scnprintf(buf, PAGE_SIZE, "0x%08llx\n",
+ read_txt_config_reg(config, TXTCR_MLE_JOIN));
+ break;
+
+ case off_DPR_raw:
+ {
+ txt_dpr_t dpr;
+
+ dpr._raw = read_txt_config_reg(config, TXTCR_DPR);
+ retval = scnprintf(buf, PAGE_SIZE, "0x%016llx\n", dpr._raw);
+ break;
+ }
+
+ case off_DPR_lock:
+ {
+ txt_dpr_t dpr;
+
+ dpr._raw = read_txt_config_reg(config, TXTCR_DPR);
+ retval = scnprintf(buf, PAGE_SIZE, "%d\n", dpr.lock);
+ break;
+ }
+
+ case off_DPR_top:
+ {
+ txt_dpr_t dpr;
+
+ dpr._raw = read_txt_config_reg(config, TXTCR_DPR);
+ retval = scnprintf(buf, PAGE_SIZE, "0x%08x\n", dpr.top << 20);
+ break;
+ }
+
+ case off_DPR_size:
+ {
+ txt_dpr_t dpr;
+
+ dpr._raw = read_txt_config_reg(config, TXTCR_DPR);
+ retval = scnprintf(buf, PAGE_SIZE, "%uMB (%uB)\n",
+ dpr.size, dpr.size*1024*1024);
+ break;
+ }
+
+ default:
+ retval = -EINVAL;
+ }
+
+ iounmap(config);
+ return retval;
+}
+
+static ssize_t store_pub_config(const char *buf, u32 offset)
+{
+ void __iomem *config;
+ long value;
+
+ config = ioremap_nocache(TXT_PUB_CONFIG_REGS_BASE,
+ TXT_CONFIG_REGS_SIZE);
+ if (config == NULL)
+ return -ENOMEM;
+
+ if (kstrtol(buf, 0, &value))
+ return -EINVAL;
+
+ switch (offset) {
+ case off_SINIT_BASE:
+ write_txt_config_reg(config, TXTCR_SINIT_BASE, value);
+ break;
+
+ case off_SINIT_SIZE:
+ write_txt_config_reg(config, TXTCR_SINIT_SIZE, value);
+ break;
+
+ case off_HEAP_BASE:
+ write_txt_config_reg(config, TXTCR_HEAP_BASE, value);
+ break;
+
+ case off_HEAP_SIZE:
+ write_txt_config_reg(config, TXTCR_HEAP_SIZE, value);
+ break;
+
+ case off_MLE_JOIN:
+ write_txt_config_reg(config, TXTCR_MLE_JOIN, value);
+ break;
+
+ case off_DPR_raw:
+ write_txt_config_reg(config, TXTCR_DPR, value);
+ break;
+
+ case off_DPR_lock:
+ {
+ txt_dpr_t dpr;
+
+ dpr._raw = read_txt_config_reg(config, TXTCR_DPR);
+ dpr.lock = value;
+
+ write_txt_config_reg(config, TXTCR_DPR, dpr._raw);
+ break;
+ }
+
+ case off_DPR_top:
+ {
+ txt_dpr_t dpr;
+
+ dpr._raw = read_txt_config_reg(config, TXTCR_DPR);
+ dpr.top = value;
+
+ write_txt_config_reg(config, TXTCR_DPR, dpr._raw);
+ break;
+ }
+
+ case off_DPR_size:
+ {
+ txt_dpr_t dpr;
+
+ dpr._raw = read_txt_config_reg(config, TXTCR_DPR);
+ dpr.size = value;
+
+ write_txt_config_reg(config, TXTCR_DPR, dpr._raw);
+ break;
+ }
+
+ default:
+ return -EINVAL;
+ }
+
+ iounmap(config);
+ return 0;
+}
+
+static ssize_t store_priv_config(const char *buf, u32 offset)
+{
+ void __iomem *config;
+ long value;
+ int retval = 0;
+
+ config = ioremap_nocache(TXT_PRIV_CONFIG_REGS_BASE,
+ TXT_CONFIG_REGS_SIZE);
+ if (config == NULL)
+ return -ENOMEM;
+
+ if (kstrtol(buf, 0, &value))
+ return -EINVAL;
+
+ if (offset != off_ERRORCODE && offset != off_E2STS_secrets) {
+ if (value != 0 && value != 1) {
+ retval = -EINVAL;
+ goto out;
+ }
+ }
+
+ switch (offset) {
+ case off_ERRORCODE:
+ write_txt_config_reg(config, TXTCR_ERRORCODE, value);
+ break;
+
+ case off_E2STS_secrets:
+ write_txt_config_reg(config, TXTCR_E2STS, value);
+ break;
+
+ case off_CMD_RESET:
+ write_txt_config_reg(config, TXTCR_CMD_RESET, value);
+ break;
+
+ case off_CMD_CLOSE_PRIVATE:
+ write_txt_config_reg(config, TXTCR_CMD_CLOSE_PRIVATE, value);
+ break;
+
+ case off_CMD_SECRETS:
+ write_txt_config_reg(config, TXTCR_CMD_SECRETS, value);
+ break;
+
+ case off_CMD_NO_SECRETS:
+ write_txt_config_reg(config, TXTCR_CMD_NO_SECRETS, value);
+ break;
+
+ case off_CMD_OPEN_LOCALITY1:
+ write_txt_config_reg(config, TXTCR_CMD_OPEN_LOCALITY1, value);
+ break;
+
+ case off_CMD_OPEN_LOCALITY2:
+ write_txt_config_reg(config, TXTCR_CMD_OPEN_LOCALITY2, value);
+ break;
+
+ case off_CMD_CLOSE_LOCALITY1:
+ write_txt_config_reg(config, TXTCR_CMD_CLOSE_LOCALITY1,
+ value);
+ break;
+
+ case off_CMD_CLOSE_LOCALITY2:
+ write_txt_config_reg(config, TXTCR_CMD_CLOSE_LOCALITY2,
+ value);
+ break;
+
+ case off_CMD_UNLOCK_MEM_CONFIG:
+ write_txt_config_reg(config, TXTCR_CMD_UNLOCK_MEM_CONFIG,
+ value);
+ break;
+
+ default:
+ retval = -EINVAL;
+ }
+
+out:
+ iounmap(config);
+ return retval;
+}
+
+static ssize_t txt_show_STS_raw(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return show_config(buf, off_STS_raw);
+}
+static DEVICE_ATTR(STS_raw, S_IRUGO, txt_show_STS_raw, NULL);
+
+static ssize_t txt_show_STS_senter_done(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return show_config(buf, off_STS_senter_done);
+}
+static DEVICE_ATTR(STS_senter_done, S_IRUGO, txt_show_STS_senter_done, NULL);
+
+static ssize_t txt_show_STS_sexit_done(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return show_config(buf, off_STS_sexit_done);
+}
+static DEVICE_ATTR(STS_sexit_done, S_IRUGO, txt_show_STS_sexit_done, NULL);
+
+static ssize_t txt_show_STS_mem_config_lock(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return show_config(buf, off_STS_mem_config_lock);
+}
+static DEVICE_ATTR(STS_mem_config_lock, S_IRUGO,
+ txt_show_STS_mem_config_lock, NULL);
+
+static ssize_t txt_show_STS_private_open(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return show_config(buf, off_STS_private_open);
+}
+static DEVICE_ATTR(STS_private_open, S_IRUGO,
+ txt_show_STS_private_open, NULL);
+
+static ssize_t txt_show_STS_locality_1_open(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return show_config(buf, off_STS_locality_1_open);
+}
+static DEVICE_ATTR(STS_locality_1_open, S_IRUGO,
+ txt_show_STS_locality_1_open, NULL);
+
+static ssize_t txt_show_STS_locality_2_open(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return show_config(buf, off_STS_locality_2_open);
+}
+static DEVICE_ATTR(STS_locality_2_open, S_IRUGO,
+ txt_show_STS_locality_2_open, NULL);
+
+static ssize_t txt_show_ERRORCODE(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return show_config(buf, off_ERRORCODE);
+}
+
+static ssize_t txt_store_ERRORCODE(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+
+ ret = store_priv_config(buf, off_ERRORCODE);
+ if (!ret)
+ return count;
+
+ return ret;
+}
+static DEVICE_ATTR(ERRORCODE, S_IRUGO | S_IWUSR | S_IWGRP,
+ txt_show_ERRORCODE, txt_store_ERRORCODE);
+
+static ssize_t txt_show_ESTS_raw(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return show_config(buf, off_ESTS_raw);
+}
+static DEVICE_ATTR(ESTS_raw, S_IRUGO, txt_show_ESTS_raw, NULL);
+
+static ssize_t txt_show_ESTS_txt_reset(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return show_config(buf, off_ESTS_txt_reset);
+}
+static DEVICE_ATTR(ESTS_txt_reset, S_IRUGO, txt_show_ESTS_txt_reset, NULL);
+
+static ssize_t txt_show_E2STS_raw(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return show_config(buf, off_E2STS_raw);
+}
+static DEVICE_ATTR(E2STS_raw, S_IRUGO, txt_show_E2STS_raw, NULL);
+
+static ssize_t txt_show_E2STS_secrets(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return show_config(buf, off_E2STS_secrets);
+}
+
+static ssize_t txt_store_E2STS_secrets(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+
+ ret = store_priv_config(buf, off_E2STS_secrets);
+ if (!ret)
+ return count;
+
+ return ret;
+}
+static DEVICE_ATTR(E2STS_secrets, S_IRUGO | S_IWUSR | S_IWGRP,
+ txt_show_E2STS_secrets, txt_store_E2STS_secrets);
+
+static ssize_t txt_show_VER_FSBIF(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return show_config(buf, off_VER_FSBIF);
+}
+static DEVICE_ATTR(VER_FSBIF, S_IRUGO, txt_show_VER_FSBIF, NULL);
+
+static ssize_t txt_show_VER_QPIIF(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return show_config(buf, off_VER_QPIIF);
+}
+static DEVICE_ATTR(VER_QPIIF, S_IRUGO, txt_show_VER_QPIIF, NULL);
+
+static ssize_t txt_show_DIDVID_raw(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return show_config(buf, off_DIDVID_raw);
+}
+static DEVICE_ATTR(DIDVID_raw, S_IRUGO, txt_show_DIDVID_raw, NULL);
+
+static ssize_t txt_show_DIDVID_vendor_id(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return show_config(buf, off_DIDVID_vendor_id);
+}
+static DEVICE_ATTR(DIDVID_vendor_id, S_IRUGO,
+ txt_show_DIDVID_vendor_id, NULL);
+
+static ssize_t txt_show_DIDVID_device_id(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return show_config(buf, off_DIDVID_device_id);
+}
+static DEVICE_ATTR(DIDVID_device_id, S_IRUGO,
+ txt_show_DIDVID_device_id, NULL);
+
+static ssize_t txt_show_DIDVID_revision_id(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return show_config(buf, off_DIDVID_revision_id);
+}
+static DEVICE_ATTR(DIDVID_revision_id, S_IRUGO,
+ txt_show_DIDVID_revision_id, NULL);
+
+static ssize_t txt_show_SINIT_BASE(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return show_config(buf, off_SINIT_BASE);
+}
+
+static ssize_t txt_store_SINIT_BASE(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+
+ ret = store_pub_config(buf, off_SINIT_BASE);
+ if (!ret)
+ return count;
+
+ return ret;
+}
+static DEVICE_ATTR(SINIT_BASE, S_IRUGO | S_IWUSR | S_IWGRP,
+ txt_show_SINIT_BASE, txt_store_SINIT_BASE);
+
+static ssize_t txt_show_SINIT_SIZE(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return show_config(buf, off_SINIT_SIZE);
+}
+
+static ssize_t txt_store_SINIT_SIZE(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+
+ ret = store_pub_config(buf, off_SINIT_SIZE);
+ if (!ret)
+ return count;
+
+ return ret;
+}
+static DEVICE_ATTR(SINIT_SIZE, S_IRUGO | S_IWUSR | S_IWGRP,
+ txt_show_SINIT_SIZE, txt_store_SINIT_SIZE);
+
+static ssize_t txt_show_HEAP_BASE(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return show_config(buf, off_HEAP_BASE);
+}
+
+static ssize_t txt_store_HEAP_BASE(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+
+ ret = store_pub_config(buf, off_HEAP_BASE);
+ if (!ret)
+ return count;
+
+ return ret;
+}
+static DEVICE_ATTR(HEAP_BASE, S_IRUGO | S_IWUSR | S_IWGRP,
+ txt_show_HEAP_BASE, txt_store_HEAP_BASE);
+
+static ssize_t txt_show_HEAP_SIZE(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return show_config(buf, off_HEAP_SIZE);
+}
+
+static ssize_t txt_store_HEAP_SIZE(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+
+ ret = store_pub_config(buf, off_HEAP_SIZE);
+ if (!ret)
+ return count;
+
+ return ret;
+}
+static DEVICE_ATTR(HEAP_SIZE, S_IRUGO | S_IWUSR | S_IWGRP,
+ txt_show_HEAP_SIZE, txt_store_HEAP_SIZE);
+
+static ssize_t txt_show_PUBLIC_KEY(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return show_config(buf, off_PUBLIC_KEY);
+}
+static DEVICE_ATTR(PUBLIC_KEY, S_IRUGO, txt_show_PUBLIC_KEY, NULL);
+
+static ssize_t txt_show_MLE_JOIN(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return show_config(buf, off_MLE_JOIN);
+}
+
+static ssize_t txt_store_MLE_JOIN(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+
+ ret = store_pub_config(buf, off_MLE_JOIN);
+ if (!ret)
+ return count;
+
+ return ret;
+}
+static DEVICE_ATTR(MLE_JOIN, S_IRUGO | S_IWUSR | S_IWGRP,
+ txt_show_MLE_JOIN, txt_store_MLE_JOIN);
+
+static ssize_t txt_show_DPR_raw(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return show_config(buf, off_DPR_raw);
+}
+
+static ssize_t txt_store_DPR_raw(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+
+ ret = store_pub_config(buf, off_DPR_raw);
+ if (!ret)
+ return count;
+
+ return ret;
+}
+static DEVICE_ATTR(DPR_raw, S_IRUGO | S_IWUSR | S_IWGRP,
+ txt_show_DPR_raw, txt_store_DPR_raw);
+
+static ssize_t txt_show_DPR_lock(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return show_config(buf, off_DPR_lock);
+}
+
+static ssize_t txt_store_DPR_lock(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+
+ ret = store_pub_config(buf, off_DPR_lock);
+ if (!ret)
+ return count;
+
+ return ret;
+}
+static DEVICE_ATTR(DPR_lock, S_IRUGO | S_IWUSR | S_IWGRP,
+ txt_show_DPR_lock, txt_store_DPR_lock);
+
+static ssize_t txt_show_DPR_top(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return show_config(buf, off_DPR_top);
+}
+
+static ssize_t txt_store_DPR_top(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+
+ ret = store_pub_config(buf, off_DPR_top);
+ if (!ret)
+ return count;
+
+ return ret;
+}
+static DEVICE_ATTR(DPR_top, S_IRUGO | S_IWUSR | S_IWGRP,
+ txt_show_DPR_top, txt_store_DPR_top);
+
+static ssize_t txt_show_DPR_size(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return show_config(buf, off_DPR_size);
+}
+
+static ssize_t txt_store_DPR_size(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+
+ ret = store_pub_config(buf, off_DPR_size);
+ if (!ret)
+ return count;
+
+ return ret;
+}
+static DEVICE_ATTR(DPR_size, S_IRUGO | S_IWUSR | S_IWGRP,
+ txt_show_DPR_size, txt_store_DPR_size);
+
+static ssize_t txt_store_CMD_RESET(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+
+ ret = store_priv_config(buf, off_CMD_RESET);
+ if (!ret)
+ return count;
+
+ return ret;
+}
+static DEVICE_ATTR(CMD_RESET, S_IWUSR | S_IWGRP,
+ NULL, txt_store_CMD_RESET);
+
+static ssize_t txt_store_CMD_CLOSE_PRIVATE(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+
+ ret = store_priv_config(buf, off_CMD_CLOSE_PRIVATE);
+ if (!ret)
+ return count;
+
+ return ret;
+}
+static DEVICE_ATTR(CMD_CLOSE_PRIVATE, S_IWUSR | S_IWGRP,
+ NULL, txt_store_CMD_CLOSE_PRIVATE);
+
+static ssize_t txt_store_CMD_SECRETS(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+
+ ret = store_priv_config(buf, off_CMD_SECRETS);
+ if (!ret)
+ return count;
+
+ return ret;
+}
+static DEVICE_ATTR(CMD_SECRETS, S_IWUSR | S_IWGRP,
+ NULL, txt_store_CMD_SECRETS);
+
+static ssize_t txt_store_CMD_NO_SECRETS(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+
+ ret = store_priv_config(buf, off_CMD_NO_SECRETS);
+ if (!ret)
+ return count;
+
+ return ret;
+}
+static DEVICE_ATTR(CMD_NO_SECRETS, S_IWUSR | S_IWGRP,
+ NULL, txt_store_CMD_NO_SECRETS);
+
+static ssize_t txt_store_CMD_OPEN_LOCALITY1(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+
+ ret = store_priv_config(buf, off_CMD_OPEN_LOCALITY1);
+ if (!ret)
+ return count;
+
+ return ret;
+}
+static DEVICE_ATTR(CMD_OPEN_LOCALITY1, S_IWUSR | S_IWGRP,
+ NULL, txt_store_CMD_OPEN_LOCALITY1);
+
+static ssize_t txt_store_CMD_OPEN_LOCALITY2(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+
+ ret = store_priv_config(buf, off_CMD_OPEN_LOCALITY2);
+ if (!ret)
+ return count;
+
+ return ret;
+}
+static DEVICE_ATTR(CMD_OPEN_LOCALITY2, S_IWUSR | S_IWGRP,
+ NULL, txt_store_CMD_OPEN_LOCALITY2);
+
+static ssize_t txt_store_CMD_CLOSE_LOCALITY1(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+
+ ret = store_priv_config(buf, off_CMD_CLOSE_LOCALITY1);
+ if (!ret)
+ return count;
+
+ return ret;
+}
+static DEVICE_ATTR(CMD_CLOSE_LOCALITY1, S_IWUSR | S_IWGRP,
+ NULL, txt_store_CMD_CLOSE_LOCALITY1);
+
+static ssize_t txt_store_CMD_CLOSE_LOCALITY2(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+
+ ret = store_priv_config(buf, off_CMD_CLOSE_LOCALITY2);
+ if (!ret)
+ return count;
+
+ return ret;
+}
+static DEVICE_ATTR(CMD_CLOSE_LOCALITY2, S_IWUSR | S_IWGRP,
+ NULL, txt_store_CMD_CLOSE_LOCALITY2);
+
+static ssize_t txt_store_CMD_UNLOCK_MEM_CONFIG(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+
+ ret = store_priv_config(buf, off_CMD_UNLOCK_MEM_CONFIG);
+ if (!ret)
+ return count;
+
+ return ret;
+}
+static DEVICE_ATTR(CMD_UNLOCK_MEM_CONFIG, S_IWUSR | S_IWGRP,
+ NULL, txt_store_CMD_UNLOCK_MEM_CONFIG);
+
+static struct attribute *config_attrs[] = {
+ &dev_attr_STS_raw.attr,
+ &dev_attr_STS_senter_done.attr,
+ &dev_attr_STS_sexit_done.attr,
+ &dev_attr_STS_mem_config_lock.attr,
+ &dev_attr_STS_private_open.attr,
+ &dev_attr_STS_locality_1_open.attr,
+ &dev_attr_STS_locality_2_open.attr,
+ &dev_attr_ERRORCODE.attr,
+ &dev_attr_ESTS_raw.attr,
+ &dev_attr_ESTS_txt_reset.attr,
+ &dev_attr_E2STS_raw.attr,
+ &dev_attr_E2STS_secrets.attr,
+ &dev_attr_VER_FSBIF.attr,
+ &dev_attr_VER_QPIIF.attr,
+ &dev_attr_DIDVID_raw.attr,
+ &dev_attr_DIDVID_vendor_id.attr,
+ &dev_attr_DIDVID_device_id.attr,
+ &dev_attr_DIDVID_revision_id.attr,
+ &dev_attr_SINIT_BASE.attr,
+ &dev_attr_SINIT_SIZE.attr,
+ &dev_attr_HEAP_BASE.attr,
+ &dev_attr_HEAP_SIZE.attr,
+ &dev_attr_PUBLIC_KEY.attr,
+ &dev_attr_MLE_JOIN.attr,
+ &dev_attr_DPR_raw.attr,
+ &dev_attr_DPR_lock.attr,
+ &dev_attr_DPR_top.attr,
+ &dev_attr_DPR_size.attr,
+ &dev_attr_CMD_RESET.attr,
+ &dev_attr_CMD_CLOSE_PRIVATE.attr,
+ &dev_attr_CMD_SECRETS.attr,
+ &dev_attr_CMD_NO_SECRETS.attr,
+ &dev_attr_CMD_OPEN_LOCALITY1.attr,
+ &dev_attr_CMD_OPEN_LOCALITY2.attr,
+ &dev_attr_CMD_CLOSE_LOCALITY1.attr,
+ &dev_attr_CMD_CLOSE_LOCALITY2.attr,
+ &dev_attr_CMD_UNLOCK_MEM_CONFIG.attr,
+ NULL,
+};
+
+static struct attribute_group config_attr_grp = {
+ .name = "config",
+ .attrs = config_attrs
+};
+
+int sysfs_create_config(struct kobject *parent)
+{
+ return sysfs_create_group(parent, &config_attr_grp);
+}
+
diff --git a/drivers/platform/x86/intel_txt/txt-config.h b/drivers/platform/x86/intel_txt/txt-config.h
new file mode 100644
index 0000000..d88cc83
--- /dev/null
+++ b/drivers/platform/x86/intel_txt/txt-config.h
@@ -0,0 +1,138 @@
+#ifndef __CONFIG_H__
+#define __CONFIG_H__
+
+#define TXT_PUB_CONFIG_REGS_BASE 0xfed30000
+#define TXT_PRIV_CONFIG_REGS_BASE 0xfed20000
+#define TXT_CONFIG_REGS_SIZE 0x10000
+
+#define TXTCR_STS 0x0000
+#define TXTCR_ESTS 0x0008
+#define TXTCR_ERRORCODE 0x0030
+#define TXTCR_CMD_RESET 0x0038
+#define TXTCR_CMD_CLOSE_PRIVATE 0x0048
+#define TXTCR_VER_FSBIF 0x0100
+#define TXTCR_DIDVID 0x0110
+#define TXTCR_VER_QPIIF 0x0200
+#define TXTCR_CMD_UNLOCK_MEM_CONFIG 0x0218
+#define TXTCR_SINIT_BASE 0x0270
+#define TXTCR_SINIT_SIZE 0x0278
+#define TXTCR_MLE_JOIN 0x0290
+#define TXTCR_HEAP_BASE 0x0300
+#define TXTCR_HEAP_SIZE 0x0308
+#define TXTCR_MSEG_BASE 0x0310
+#define TXTCR_MSEG_SIZE 0x0318
+#define TXTCR_DPR 0x0330
+#define TXTCR_CMD_OPEN_LOCALITY1 0x0380
+#define TXTCR_CMD_CLOSE_LOCALITY1 0x0388
+#define TXTCR_CMD_OPEN_LOCALITY2 0x0390
+#define TXTCR_CMD_CLOSE_LOCALITY2 0x0398
+#define TXTCR_PUBLIC_KEY 0x0400
+#define TXTCR_CMD_SECRETS 0x08e0
+#define TXTCR_CMD_NO_SECRETS 0x08e8
+#define TXTCR_E2STS 0x08f0
+
+#define off_STS_raw 1
+#define off_STS_senter_done 2
+#define off_STS_sexit_done 3
+#define off_STS_mem_config_lock 4
+#define off_STS_private_open 5
+#define off_STS_locality_1_open 6
+#define off_STS_locality_2_open 7
+#define off_ERRORCODE 8
+#define off_ESTS_raw 9
+#define off_ESTS_txt_reset 10
+#define off_E2STS_raw 11
+#define off_E2STS_secrets 12
+#define off_VER_FSBIF 13
+#define off_VER_QPIIF 14
+#define off_DIDVID_raw 15
+#define off_DIDVID_vendor_id 16
+#define off_DIDVID_device_id 17
+#define off_DIDVID_revision_id 18
+#define off_SINIT_BASE 19
+#define off_SINIT_SIZE 20
+#define off_HEAP_BASE 21
+#define off_HEAP_SIZE 22
+#define off_PUBLIC_KEY 23
+#define off_MLE_JOIN 24
+#define off_DPR_raw 25
+#define off_DPR_lock 26
+#define off_DPR_top 27
+#define off_DPR_size 28
+#define off_CMD_RESET 29
+#define off_CMD_CLOSE_PRIVATE 30
+#define off_CMD_SECRETS 31
+#define off_CMD_NO_SECRETS 32
+#define off_CMD_OPEN_LOCALITY1 33
+#define off_CMD_OPEN_LOCALITY2 34
+#define off_CMD_CLOSE_LOCALITY1 35
+#define off_CMD_CLOSE_LOCALITY2 36
+#define off_CMD_UNLOCK_MEM_CONFIG 37
+
+typedef union txt_ests {
+ uint64_t _raw;
+ struct {
+ uint64_t txt_reset_sts:1;
+ };
+} txt_ests_t;
+
+typedef union txt_e2sts {
+ uint64_t _raw;
+ struct {
+ uint64_t reserved:1;
+ uint64_t secrets_sts:1;
+ };
+} txt_e2sts_t;
+
+typedef union txt_sts {
+ uint64_t _raw;
+ struct {
+ uint64_t senter_done_sts:1;
+ uint64_t sexit_done_sts:1;
+ uint64_t reserved1:4;
+ uint64_t mem_config_lock_sts:1;
+ uint64_t private_open_sts:1;
+ uint64_t reserved2:7;
+ uint64_t locality_1_open_sts:1;
+ uint64_t locality_2_open_sts:1;
+ };
+} txt_sts_t;
+
+typedef union txt_divid {
+ uint64_t _raw;
+ struct {
+ uint16_t vendor_id;
+ uint16_t device_id;
+ uint16_t revision_id;
+ uint16_t reserved;
+ };
+} txt_didvid_t;
+
+typedef union txt_dpr {
+ uint64_t _raw;
+ struct {
+ uint64_t lock:1;
+ uint64_t reserved1:3;
+ uint64_t size:8;
+ uint64_t reserved2:8;
+ uint64_t top:12;
+ uint64_t reserved3:32;
+ };
+} txt_dpr_t;
+
+static inline uint64_t
+read_txt_config_reg(void *config_regs_base, uint32_t reg)
+{
+ return readq(config_regs_base + reg);
+}
+
+static inline void
+write_txt_config_reg(void *config_regs_base, uint32_t reg, uint64_t val)
+{
+ writeq(val, config_regs_base + reg);
+}
+
+extern int sysfs_create_config(struct kobject *parent);
+
+#endif /* __CONFIG_H__ */
+
diff --git a/drivers/platform/x86/intel_txt/txt-sysfs.c b/drivers/platform/x86/intel_txt/txt-sysfs.c
index def33cb..ac889f7 100644
--- a/drivers/platform/x86/intel_txt/txt-sysfs.c
+++ b/drivers/platform/x86/intel_txt/txt-sysfs.c
@@ -36,11 +36,15 @@
#include <linux/sysfs.h>
#include <linux/tboot.h>

+#include "txt-config.h"
+
#define DEV_NAME "intel_txt"
static struct platform_device *txt_pdev;

static int __init txt_sysfs_init(void)
{
+ int retval;
+
if (!tboot_enabled())
return -ENODEV;

@@ -48,7 +52,15 @@ static int __init txt_sysfs_init(void)
if (IS_ERR(txt_pdev))
return PTR_ERR(txt_pdev);

+ retval = sysfs_create_config(&txt_pdev->dev.kobj);
+ if (retval)
+ goto err;
+
return 0;
+
+err:
+ platform_device_unregister(txt_pdev);
+ return retval;
}

static void __exit txt_sysfs_exit(void)
--
1.7.9.5

2013-05-24 09:58:37

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH v3 2/3] driver: provide sysfs interfaces to access TXT config space

On Wed 2013-05-15 11:04:33, Qiaowei Ren wrote:
> These interfaces are located in /sys/devices/platform/intel_txt/config,
> and including totally 37 files, providing access to Intel TXT
> configuration registers.
>
> Signed-off-by: Qiaowei Ren <[email protected]>
> Signed-off-by: Xiaoyan Zhang <[email protected]>
> Signed-off-by: Gang Wei <[email protected]>

You forgot to Cc sysfs maintainer, and proposed interface is not
suitable for reasons explained before.

--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html