From 9090a0266eb13b823656216c665182d45a4cd19b Mon Sep 17 00:00:00 2001
From: Krystian Hebel <krystian.hebel@3mdeb.com>
Date: Tue, 28 Mar 2023 18:31:21 +0200
Subject: [PATCH] drivers/firmware/google: expose CBMEM as sysfs file

Signed-off-by: Krystian Hebel <krystian.hebel@3mdeb.com>
---
 drivers/firmware/google/Kconfig          |  8 ++++++
 drivers/firmware/google/coreboot_table.c | 33 ++++++++++++++++++++++++
 2 files changed, 41 insertions(+)

diff --git a/drivers/firmware/google/Kconfig b/drivers/firmware/google/Kconfig
index a3a6ca659ffa..2d18ee174043 100644
--- a/drivers/firmware/google/Kconfig
+++ b/drivers/firmware/google/Kconfig
@@ -29,6 +29,14 @@ config GOOGLE_COREBOOT_TABLE
 	  device tree node /firmware/coreboot.
 	  If unsure say N.
 
+config GOOGLE_COREBOOT_CBMEM
+	bool "Expose CBMEM as file"
+	depends on GOOGLE_COREBOOT_TABLE
+	help
+	  This option exposes raw contents of coreboot's CBMEM to be consumed
+	  by userspace tools. Path to file: /sys/firmware/cbmem.
+	  If unsure say N.
+
 config GOOGLE_COREBOOT_TABLE_ACPI
 	tristate
 	select GOOGLE_COREBOOT_TABLE
diff --git a/drivers/firmware/google/coreboot_table.c b/drivers/firmware/google/coreboot_table.c
index 8d132e4f008a..f93bdc49b1ac 100644
--- a/drivers/firmware/google/coreboot_table.c
+++ b/drivers/firmware/google/coreboot_table.c
@@ -84,6 +84,18 @@ void coreboot_driver_unregister(struct coreboot_driver *driver)
 }
 EXPORT_SYMBOL(coreboot_driver_unregister);
 
+#ifdef CONFIG_GOOGLE_COREBOOT_CBMEM
+static ssize_t cbmem_read(struct file *filp, struct kobject *kobp,
+			  struct bin_attribute *bin_attr, char *buf,
+			  loff_t pos, size_t count)
+{
+	return memory_read_from_buffer(buf, count, &pos,
+				       bin_attr->private, bin_attr->size);
+}
+
+static BIN_ATTR_RO(cbmem, 0);
+#endif
+
 static int coreboot_table_populate(struct device *dev, void *ptr)
 {
 	int i, ret;
@@ -160,11 +172,32 @@ static int coreboot_table_probe(struct platform_device *pdev)
 	}
 	memunmap(ptr);
 
+#ifdef CONFIG_GOOGLE_COREBOOT_CBMEM
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (res && res->start && res->end && resource_size(res)) {
+		bin_attr_cbmem.size = resource_size(res);
+		bin_attr_cbmem.private = memremap(res->start,
+						  resource_size(res),
+						  MEMREMAP_WB);
+		if (sysfs_create_bin_file(firmware_kobj, &bin_attr_cbmem)) {
+			bin_attr_cbmem.size = 0;
+			bin_attr_cbmem.private = NULL;
+		}
+	}
+#endif
+
 	return ret;
 }
 
 static int coreboot_table_remove(struct platform_device *pdev)
 {
+#ifdef CONFIG_GOOGLE_COREBOOT_CBMEM
+	if (bin_attr_cbmem.private) {
+		sysfs_remove_bin_file(firmware_kobj, &bin_attr_cbmem);
+		memunmap(bin_attr_cbmem.private);
+	}
+#endif
+
 	bus_unregister(&coreboot_bus_type);
 	return 0;
 }
-- 
2.17.1

