[PATCH 2/4] driver: provide sysfs interfaces to access TXT config space

From: Qiaowei Ren
Date: Tue May 07 2013 - 03:05:59 EST


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 <qiaowei.ren@xxxxxxxxx>
Signed-off-by: Xiaoyan Zhang <xiaoyan.zhang@xxxxxxxxx>
Signed-off-by: Gang Wei <gang.wei@xxxxxxxxx>
---
Documentation/ABI/testing/sysfs-platform-intel-txt | 309 ++++++
drivers/platform/x86/intel_txt/Makefile | 2 +-
drivers/platform/x86/intel_txt/txt-config.c | 1032 ++++++++++++++++++++
drivers/platform/x86/intel_txt/txt-config.h | 138 +++
drivers/platform/x86/intel_txt/txt-sysfs.c | 12 +
5 files changed, 1492 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" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+Description: Vendor ID.
+
+What: /sys/devices/platform/intel_txt/config/DIDVID_device_id
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <qiaowei.ren@xxxxxxxxx>
+Description: Device ID.
+
+What: /sys/devices/platform/intel_txt/config/DIDVID_revision_id
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <qiaowei.ren@xxxxxxxxx>
+Description: Revision ID.
+
+What: /sys/devices/platform/intel_txt/config/VER_QPIIF
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+Description: Top address + 1 of DPR.
+
+What: /sys/devices/platform/intel_txt/config/DPR_size
+Date: May 2013
+KernelVersion: 3.9
+Contact: "Qiaowei Ren" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+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" <qiaowei.ren@xxxxxxxxx>
+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..34311a2
--- /dev/null
+++ b/drivers/platform/x86/intel_txt/txt-config.c
@@ -0,0 +1,1032 @@
+/*
+ * 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);
+}
+EXPORT_SYMBOL_GPL(sysfs_create_config);
+
+MODULE_LICENSE("GPL");
+
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 96efe87..28cc8a2 100644
--- a/drivers/platform/x86/intel_txt/txt-sysfs.c
+++ b/drivers/platform/x86/intel_txt/txt-sysfs.c
@@ -15,16 +15,28 @@
#include <linux/platform_device.h>
#include <linux/sysfs.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;
+
txt_pdev = platform_device_register_simple(DEV_NAME, -1, NULL, 0);
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

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