|
| 1 | +From acff0fec046e730871aa7342fe8118479eb092d2 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Eric Chanudet < [email protected]> |
| 3 | +Date: Wed, 23 Jun 2021 10:12:42 -0400 |
| 4 | +Subject: [PATCH] txt_info: expose TXT conf registers to userland |
| 5 | + |
| 6 | +TXT exposes configuration registers documented in its Software |
| 7 | +Development Guide. Accessing these registers in sometimes necessary for |
| 8 | +userland software to perform checks and validate compatibility with |
| 9 | +software resources. |
| 10 | + |
| 11 | +Expose the previously mentioned resources through a platform device |
| 12 | +driver in the sysfs. |
| 13 | + |
| 14 | +Signed-off-by: Eric Chanudet < [email protected]> |
| 15 | +--- |
| 16 | + drivers/misc/Kconfig | 10 +++ |
| 17 | + drivers/misc/Makefile | 1 + |
| 18 | + drivers/misc/txt_info.c | 167 ++++++++++++++++++++++++++++++++++++++++ |
| 19 | + 3 files changed, 178 insertions(+) |
| 20 | + create mode 100644 drivers/misc/txt_info.c |
| 21 | + |
| 22 | +diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig |
| 23 | +index c55b63750757..2d3479593610 100644 |
| 24 | +--- a/drivers/misc/Kconfig |
| 25 | ++++ b/drivers/misc/Kconfig |
| 26 | +@@ -466,6 +466,16 @@ config PVPANIC |
| 27 | + a paravirtualized device provided by QEMU; it lets a virtual machine |
| 28 | + (guest) communicate panic events to the host. |
| 29 | + |
| 30 | ++config TXT_INFO |
| 31 | ++ tristate "Add TXT configuration registers in securityfs" |
| 32 | ++ depends on X86 && TCG_TPM |
| 33 | ++ default n |
| 34 | ++ help |
| 35 | ++ Expose the values of TXT configuration registers via the sysfs for |
| 36 | ++ use in userland. To compile this as a module choose M. |
| 37 | ++ |
| 38 | ++ If unsure, say N. |
| 39 | ++ |
| 40 | + source "drivers/misc/c2port/Kconfig" |
| 41 | + source "drivers/misc/eeprom/Kconfig" |
| 42 | + source "drivers/misc/cb710/Kconfig" |
| 43 | +diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile |
| 44 | +index c1860d35dc7e..4ebacab15df2 100644 |
| 45 | +--- a/drivers/misc/Makefile |
| 46 | ++++ b/drivers/misc/Makefile |
| 47 | +@@ -57,3 +57,4 @@ obj-y += cardreader/ |
| 48 | + obj-$(CONFIG_PVPANIC) += pvpanic.o |
| 49 | + obj-$(CONFIG_HABANA_AI) += habanalabs/ |
| 50 | + obj-$(CONFIG_XILINX_SDFEC) += xilinx_sdfec.o |
| 51 | ++obj-$(CONFIG_TXT_INFO) += txt_info.o |
| 52 | +diff --git a/drivers/misc/txt_info.c b/drivers/misc/txt_info.c |
| 53 | +new file mode 100644 |
| 54 | +index 000000000000..ebece6a50612 |
| 55 | +--- /dev/null |
| 56 | ++++ b/drivers/misc/txt_info.c |
| 57 | +@@ -0,0 +1,167 @@ |
| 58 | ++#include <linux/kobject.h> |
| 59 | ++#include <linux/module.h> |
| 60 | ++#include <linux/device.h> |
| 61 | ++#include <linux/platform_device.h> |
| 62 | ++#include <linux/io.h> |
| 63 | ++ |
| 64 | ++#define TXT_PUB_CR_BASE 0xfed30000 |
| 65 | ++#define TXT_PUB_CR_SIZE 0x10000 |
| 66 | ++static const struct resource txt_resources[] = { |
| 67 | ++ { |
| 68 | ++ .start = TXT_PUB_CR_BASE, |
| 69 | ++ .end = TXT_PUB_CR_BASE + TXT_PUB_CR_SIZE - 1, |
| 70 | ++ .flags = IORESOURCE_MEM, |
| 71 | ++ }, |
| 72 | ++}; |
| 73 | ++#define TXT_PUB_CR_INDEX 0 |
| 74 | ++ |
| 75 | ++struct platform_device *pdev; |
| 76 | ++struct txt_info { |
| 77 | ++ void __iomem *cr_pub; |
| 78 | ++ void __iomem *cr_priv; |
| 79 | ++}; |
| 80 | ++static struct txt_info txt_info; |
| 81 | ++ |
| 82 | ++static void __iomem *txt_info_map_regs(struct platform_device *pdev, |
| 83 | ++ size_t index) |
| 84 | ++{ |
| 85 | ++ struct resource *res; |
| 86 | ++ void __iomem *base; |
| 87 | ++ |
| 88 | ++ res = platform_get_resource(pdev, IORESOURCE_MEM, index); |
| 89 | ++ if (IS_ERR(res)) { |
| 90 | ++ dev_dbg(&pdev->dev, |
| 91 | ++ "Failed to access IOMEM resource %zu.\n", index); |
| 92 | ++ return res; |
| 93 | ++ } |
| 94 | ++ |
| 95 | ++ base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); |
| 96 | ++ if (IS_ERR(base)) |
| 97 | ++ dev_dbg(&pdev->dev, |
| 98 | ++ "Failed to ioremap configuration registers.\n"); |
| 99 | ++ |
| 100 | ++ return base; |
| 101 | ++} |
| 102 | ++ |
| 103 | ++/* Registers offset from TXT_PUB_CR_BASE */ |
| 104 | ++#define TXT_STS_OFFSET 0x000 |
| 105 | ++#define TXT_ESTS_OFFSET 0x008 |
| 106 | ++#define TXT_ERRORCODE_OFFSET 0x030 |
| 107 | ++#define TXT_VER_FSBIF_OFFSET 0x100 |
| 108 | ++#define TXT_DIDVID_OFFSET 0x110 |
| 109 | ++#define TXT_VER_QPIIF_OFFSET 0x200 |
| 110 | ++ |
| 111 | ++#define DECLARE_PUB_SHOW_U8(name, offset) \ |
| 112 | ++static ssize_t name##_show(struct kobject *kobj, \ |
| 113 | ++ struct kobj_attribute *attr, char *buf) \ |
| 114 | ++{ \ |
| 115 | ++ uint8_t v = ioread8(txt_info.cr_pub + (offset)); \ |
| 116 | ++ return sprintf(buf, "%#04x\n", v); \ |
| 117 | ++} \ |
| 118 | ++static struct kobj_attribute txt_attr_##name = __ATTR_RO(name); |
| 119 | ++ |
| 120 | ++#define DECLARE_PUB_SHOW_U32(name, offset) \ |
| 121 | ++static ssize_t name##_show(struct kobject *kobj, \ |
| 122 | ++ struct kobj_attribute *attr, char *buf) \ |
| 123 | ++{ \ |
| 124 | ++ uint32_t v = ioread32(txt_info.cr_pub + (offset)); \ |
| 125 | ++ return sprintf(buf, "%#010x\n", v); \ |
| 126 | ++} \ |
| 127 | ++static struct kobj_attribute txt_attr_##name = __ATTR_RO(name); |
| 128 | ++ |
| 129 | ++#define DECLARE_PUB_SHOW_U64(name, offset) \ |
| 130 | ++static ssize_t name##_show(struct kobject *kobj, \ |
| 131 | ++ struct kobj_attribute *attr, char *buf) \ |
| 132 | ++{ \ |
| 133 | ++ uint64_t v = ioread32(txt_info.cr_pub + (offset) + 0x4); \ |
| 134 | ++ v <<= 32; \ |
| 135 | ++ v |= ioread32(txt_info.cr_pub + (offset)); \ |
| 136 | ++ return sprintf(buf, "%#018llx\n", v); \ |
| 137 | ++} \ |
| 138 | ++static struct kobj_attribute txt_attr_##name = __ATTR_RO(name); |
| 139 | ++ |
| 140 | ++DECLARE_PUB_SHOW_U64(sts, TXT_STS_OFFSET); |
| 141 | ++DECLARE_PUB_SHOW_U8(ests, TXT_ESTS_OFFSET); |
| 142 | ++DECLARE_PUB_SHOW_U32(errorcode, TXT_ERRORCODE_OFFSET); |
| 143 | ++DECLARE_PUB_SHOW_U32(ver_fsbif, TXT_VER_FSBIF_OFFSET); |
| 144 | ++DECLARE_PUB_SHOW_U64(didvid, TXT_DIDVID_OFFSET); |
| 145 | ++DECLARE_PUB_SHOW_U32(ver_qpiif, TXT_VER_QPIIF_OFFSET); |
| 146 | ++ |
| 147 | ++static struct attribute *txt_subsys_attrs[] = { |
| 148 | ++ &txt_attr_sts.attr, |
| 149 | ++ &txt_attr_ests.attr, |
| 150 | ++ &txt_attr_errorcode.attr, |
| 151 | ++ &txt_attr_ver_fsbif.attr, |
| 152 | ++ &txt_attr_didvid.attr, |
| 153 | ++ &txt_attr_ver_qpiif.attr, |
| 154 | ++ NULL, |
| 155 | ++}; |
| 156 | ++ |
| 157 | ++static umode_t txt_attr_is_visible(struct kobject *kobj, |
| 158 | ++ struct attribute *attr, int n) |
| 159 | ++{ |
| 160 | ++ return attr->mode; |
| 161 | ++} |
| 162 | ++ |
| 163 | ++static const struct attribute_group txt_subsys_attr_group = { |
| 164 | ++ .attrs = txt_subsys_attrs, |
| 165 | ++ .is_visible = txt_attr_is_visible, |
| 166 | ++}; |
| 167 | ++ |
| 168 | ++struct kobject *txt_kobj; |
| 169 | ++ |
| 170 | ++static int __init init_txt_info(void) |
| 171 | ++{ |
| 172 | ++ int rc; |
| 173 | ++ void __iomem *base; |
| 174 | ++ |
| 175 | ++ pr_info("%s\n", __func__); |
| 176 | ++ |
| 177 | ++ pdev = platform_device_register_simple( |
| 178 | ++ "txt", -1, txt_resources, ARRAY_SIZE(txt_resources)); |
| 179 | ++ if (IS_ERR(pdev)) { |
| 180 | ++ rc = PTR_ERR(pdev); |
| 181 | ++ pr_err("Failed to register txt platform device driver (%d).\n", rc); |
| 182 | ++ goto fail_register; |
| 183 | ++ } |
| 184 | ++ |
| 185 | ++ base = txt_info_map_regs(pdev, TXT_PUB_CR_INDEX); |
| 186 | ++ if (IS_ERR(base)) { |
| 187 | ++ rc = PTR_ERR(base); |
| 188 | ++ dev_err(&pdev->dev, |
| 189 | ++ "Failed to map TXT public resources (%d).\n", rc); |
| 190 | ++ goto fail_map_pub; |
| 191 | ++ } |
| 192 | ++ txt_info.cr_pub = base; |
| 193 | ++ |
| 194 | ++ rc = sysfs_create_group(&pdev->dev.kobj, &txt_subsys_attr_group); |
| 195 | ++ if (rc) { |
| 196 | ++ dev_err(&pdev->dev, "Failed to create sysfs group (%d).\n", rc); |
| 197 | ++ goto fail_sysfs; |
| 198 | ++ } |
| 199 | ++ |
| 200 | ++ return 0; |
| 201 | ++ |
| 202 | ++fail_sysfs: |
| 203 | ++ devm_iounmap(&pdev->dev, txt_info.cr_pub); |
| 204 | ++fail_map_pub: |
| 205 | ++ platform_device_unregister(pdev); |
| 206 | ++fail_register: |
| 207 | ++ return rc; |
| 208 | ++} |
| 209 | ++ |
| 210 | ++static void __exit cleanup_txt_info(void) |
| 211 | ++{ |
| 212 | ++ pr_info("%s\n", __func__); |
| 213 | ++ |
| 214 | ++ if (pdev) |
| 215 | ++ platform_device_unregister(pdev); |
| 216 | ++} |
| 217 | ++ |
| 218 | ++module_init(init_txt_info); |
| 219 | ++module_exit(cleanup_txt_info); |
| 220 | ++ |
| 221 | ++MODULE_AUTHOR("Assured Information Security, Inc"); |
| 222 | ++MODULE_DESCRIPTION("TXT driver."); |
| 223 | ++MODULE_VERSION("1.0"); |
| 224 | ++MODULE_LICENSE("GPL"); |
| 225 | +-- |
| 226 | +2.17.1 |
| 227 | + |
0 commit comments