On 4/7/20 3:29 AM, patrick.rudolph@9elements.com wrote:
From: Patrick Rudolph patrick.rudolph@9elements.com
Make all CBMEM buffers available to userland. This is useful for tools that are currently using /dev/mem.
Make the id, size and address available, as well as the raw table data.
Tools can easily scan the right CBMEM buffer by reading /sys/bus/coreboot/drivers/cbmem/coreboot*/cbmem_attributes/id or /sys/bus/coreboot/devices/coreboot*/cbmem_attributes/id
The binary table data can then be read from /sys/bus/coreboot/drivers/cbmem/coreboot*/cbmem_attributes/data or /sys/bus/coreboot/devices/coreboot*/cbmem_attributes/data
Signed-off-by: Patrick Rudolph patrick.rudolph@9elements.com
-v2: - Add ABI documentation - Add 0x prefix on hex values -v3: - Use BIN_ATTR_RO -v4: - Use temporary memremap instead of persistent ioremap - Constify a struct - Get rid of unused headers - Use dev_{get|set}_drvdata - Use dev_groups to automatically handle attributes - Updated file description - Updated ABI documentation
Documentation/ABI/stable/sysfs-bus-coreboot | 44 +++++++ drivers/firmware/google/Kconfig | 9 ++ drivers/firmware/google/Makefile | 1 + drivers/firmware/google/cbmem-coreboot.c | 128 ++++++++++++++++++++ drivers/firmware/google/coreboot_table.h | 14 +++ 5 files changed, 196 insertions(+) create mode 100644 Documentation/ABI/stable/sysfs-bus-coreboot create mode 100644 drivers/firmware/google/cbmem-coreboot.c
diff --git a/Documentation/ABI/stable/sysfs-bus-coreboot b/Documentation/ABI/stable/sysfs-bus-coreboot new file mode 100644 index 000000000000..6055906f41f2 --- /dev/null +++ b/Documentation/ABI/stable/sysfs-bus-coreboot @@ -0,0 +1,44 @@ +What: /sys/bus/coreboot/devices/.../cbmem_attributes/id +Date: Apr 2020 +KernelVersion: 5.6
I guess these will be 5.8 now.
+Contact: Patrick Rudolph patrick.rudolph@9elements.com +Description:
coreboot device directory can contain a file named
cbmem_attributes/id if the device corresponds to a CBMEM
buffer.
The file holds an ASCII representation of the CBMEM ID in hex
(e.g. 0xdeadbeef).
+What: /sys/bus/coreboot/devices/.../cbmem_attributes/size +Date: Apr 2020 +KernelVersion: 5.6 +Contact: Patrick Rudolph patrick.rudolph@9elements.com +Description:
coreboot device directory can contain a file named
cbmem_attributes/size if the device corresponds to a CBMEM
buffer.
The file holds an representation as decimal number of the
nit: "a representation" (maybe "a decimal representation"?)
CBMEM buffer size (e.g. 64).
+What: /sys/bus/coreboot/devices/.../cbmem_attributes/address +Date: Apr 2020 +KernelVersion: 5.6 +Contact: Patrick Rudolph patrick.rudolph@9elements.com +Description:
coreboot device directory can contain a file named
cbmem_attributes/address if the device corresponds to a CBMEM
buffer.
The file holds an ASCII representation of the physical address
of the CBMEM buffer in hex (e.g. 0x000000008000d000) and should
be used for debugging only.
+What: /sys/bus/coreboot/devices/.../cbmem_attributes/data +Date: Apr 2020 +KernelVersion: 5.6 +Contact: Patrick Rudolph patrick.rudolph@9elements.com +Description:
coreboot device directory can contain a file named
cbmem_attributes/data if the device corresponds to a CBMEM
buffer.
The file holds a read-only binary representation of the CBMEM
buffer.
diff --git a/drivers/firmware/google/Kconfig b/drivers/firmware/google/Kconfig index a3a6ca659ffa..11a67c397ab3 100644 --- a/drivers/firmware/google/Kconfig +++ b/drivers/firmware/google/Kconfig @@ -58,6 +58,15 @@ config GOOGLE_FRAMEBUFFER_COREBOOT This option enables the kernel to search for a framebuffer in the coreboot table. If found, it is registered with simplefb.
+config GOOGLE_CBMEM_COREBOOT
- tristate "Coreboot CBMEM access"
- depends on GOOGLE_COREBOOT_TABLE
- help
This option exposes all available CBMEM buffers to userland.
The CBMEM id, size and address as well as the raw table data
are exported as sysfs attributes of the corresponding coreboot
table.
config GOOGLE_MEMCONSOLE_COREBOOT tristate "Firmware Memory Console" depends on GOOGLE_COREBOOT_TABLE diff --git a/drivers/firmware/google/Makefile b/drivers/firmware/google/Makefile index d17caded5d88..62053cd6d058 100644 --- a/drivers/firmware/google/Makefile +++ b/drivers/firmware/google/Makefile @@ -2,6 +2,7 @@
obj-$(CONFIG_GOOGLE_SMI) += gsmi.o obj-$(CONFIG_GOOGLE_COREBOOT_TABLE) += coreboot_table.o +obj-$(CONFIG_GOOGLE_CBMEM_COREBOOT) += cbmem-coreboot.o obj-$(CONFIG_GOOGLE_FRAMEBUFFER_COREBOOT) += framebuffer-coreboot.o obj-$(CONFIG_GOOGLE_MEMCONSOLE) += memconsole.o obj-$(CONFIG_GOOGLE_MEMCONSOLE_COREBOOT) += memconsole-coreboot.o diff --git a/drivers/firmware/google/cbmem-coreboot.c b/drivers/firmware/google/cbmem-coreboot.c new file mode 100644 index 000000000000..f76704a6eec7 --- /dev/null +++ b/drivers/firmware/google/cbmem-coreboot.c @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: GPL-2.0-only +/*
- cbmem-coreboot.c
- Exports CBMEM as attributes in sysfs.
- Copyright 2012-2013 David Herrmann dh.herrmann@gmail.com
- Copyright 2017 Google Inc.
- Copyright 2019 9elements Agency GmbH
- */
+#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/module.h> +#include <linux/io.h>
+#include "coreboot_table.h"
+#define CB_TAG_CBMEM_ENTRY 0x31
+struct cb_priv {
- struct lb_cbmem_entry entry;
+};
+static ssize_t id_show(struct device *dev,
struct device_attribute *attr, char *buffer)
+{
- const struct cb_priv *priv = dev_get_drvdata(dev);
- return sprintf(buffer, "%#08x\n", priv->entry.id);
+}
+static ssize_t size_show(struct device *dev,
struct device_attribute *attr, char *buffer)
+{
- const struct cb_priv *priv = dev_get_drvdata(dev);
- return sprintf(buffer, "%u\n", priv->entry.entry_size);
+}
+static ssize_t address_show(struct device *dev,
struct device_attribute *attr, char *buffer)
+{
- const struct cb_priv *priv = dev_get_drvdata(dev);
- return sprintf(buffer, "%#016llx\n", priv->entry.address);
+}
+static DEVICE_ATTR_RO(id); +static DEVICE_ATTR_RO(size); +static DEVICE_ATTR_RO(address);
+static struct attribute *cb_mem_attrs[] = {
- &dev_attr_address.attr,
- &dev_attr_id.attr,
- &dev_attr_size.attr,
- NULL
+};
+static ssize_t data_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buffer, loff_t offset, size_t count)
+{
- const struct device *dev = kobj_to_dev(kobj);
- const struct cb_priv *priv = dev_get_drvdata(dev);
- void *ptr;
- /* CBMEM is always RAM with unknown caching attributes. */
- ptr = memremap(priv->entry.address, priv->entry.entry_size,
MEMREMAP_WB | MEMREMAP_WT);
- if (!ptr)
return -ENOMEM;
- count = memory_read_from_buffer(buffer, count, &offset, ptr,
priv->entry.entry_size);
- memunmap(ptr);
- return count;
+}
+static BIN_ATTR_RO(data, 0);
+static struct bin_attribute *cb_mem_bin_attrs[] = {
- &bin_attr_data,
- NULL
+};
+static const struct attribute_group cb_mem_attr_group = {
- .name = "cbmem_attributes",
- .attrs = cb_mem_attrs,
- .bin_attrs = cb_mem_bin_attrs,
+};
+static const struct attribute_group *attribute_groups[] = {
- &cb_mem_attr_group,
- NULL,
+};
+static int cbmem_probe(struct coreboot_device *cdev) +{
- struct device *dev = &cdev->dev;
- struct cb_priv *priv;
- priv = devm_kmalloc(dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
return -ENOMEM;
- memcpy(&priv->entry, &cdev->cbmem_entry, sizeof(priv->entry));
I don't think it is necessary to create a second copy of the table entry, when it is already available at cdev->cbmem_entry. You could do:
dev_set_drvdata(dev, cdev);
and that removes the need for struct cb_priv.
Otherwise,
Reviewed-by: Samuel Holland samuel@sholland.org Tested-by: Samuel Holland samuel@sholland.org
I hacked nvramtool to pull the CMOS layout from /sys/bus/coreboot/devices/coreboot0/attributes/data, and that seemed to work.
Cheers, Samuel
- dev_set_drvdata(dev, priv);
- return 0;
+}
+static struct coreboot_driver cbmem_driver = {
- .probe = cbmem_probe,
- .drv = {
.name = "cbmem",
.dev_groups = attribute_groups,
- },
- .tag = CB_TAG_CBMEM_ENTRY,
+};
+module_coreboot_driver(cbmem_driver);
+MODULE_AUTHOR("9elements Agency GmbH"); +MODULE_LICENSE("GPL"); diff --git a/drivers/firmware/google/coreboot_table.h b/drivers/firmware/google/coreboot_table.h index 7b7b4a6eedda..fc20b8649882 100644 --- a/drivers/firmware/google/coreboot_table.h +++ b/drivers/firmware/google/coreboot_table.h @@ -59,6 +59,19 @@ struct lb_framebuffer { u8 reserved_mask_size; };
+/*
- There can be more than one of these records as there is one per cbmem entry.
- Describes a buffer in memory containing runtime data.
- */
+struct lb_cbmem_entry {
- u32 tag;
- u32 size;
- u64 address;
- u32 entry_size;
- u32 id;
+};
/* A device, additionally with information from coreboot. */ struct coreboot_device { struct device dev; @@ -66,6 +79,7 @@ struct coreboot_device { struct coreboot_table_entry entry; struct lb_cbmem_ref cbmem_ref; struct lb_framebuffer framebuffer;
};struct lb_cbmem_entry cbmem_entry;
};