summaryrefslogtreecommitdiffstats
path: root/drivers/firmware/google/coreboot_table.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 01:02:30 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 01:02:30 +0000
commit76cb841cb886eef6b3bee341a2266c76578724ad (patch)
treef5892e5ba6cc11949952a6ce4ecbe6d516d6ce58 /drivers/firmware/google/coreboot_table.c
parentInitial commit. (diff)
downloadlinux-76cb841cb886eef6b3bee341a2266c76578724ad.tar.xz
linux-76cb841cb886eef6b3bee341a2266c76578724ad.zip
Adding upstream version 4.19.249.upstream/4.19.249
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/firmware/google/coreboot_table.c')
-rw-r--r--drivers/firmware/google/coreboot_table.c159
1 files changed, 159 insertions, 0 deletions
diff --git a/drivers/firmware/google/coreboot_table.c b/drivers/firmware/google/coreboot_table.c
new file mode 100644
index 000000000..898bb9abc
--- /dev/null
+++ b/drivers/firmware/google/coreboot_table.c
@@ -0,0 +1,159 @@
+/*
+ * coreboot_table.c
+ *
+ * Module providing coreboot table access.
+ *
+ * Copyright 2017 Google Inc.
+ * Copyright 2017 Samuel Holland <samuel@sholland.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License v2.0 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "coreboot_table.h"
+
+#define CB_DEV(d) container_of(d, struct coreboot_device, dev)
+#define CB_DRV(d) container_of(d, struct coreboot_driver, drv)
+
+static struct coreboot_table_header __iomem *ptr_header;
+
+static int coreboot_bus_match(struct device *dev, struct device_driver *drv)
+{
+ struct coreboot_device *device = CB_DEV(dev);
+ struct coreboot_driver *driver = CB_DRV(drv);
+
+ return device->entry.tag == driver->tag;
+}
+
+static int coreboot_bus_probe(struct device *dev)
+{
+ int ret = -ENODEV;
+ struct coreboot_device *device = CB_DEV(dev);
+ struct coreboot_driver *driver = CB_DRV(dev->driver);
+
+ if (driver->probe)
+ ret = driver->probe(device);
+
+ return ret;
+}
+
+static int coreboot_bus_remove(struct device *dev)
+{
+ int ret = 0;
+ struct coreboot_device *device = CB_DEV(dev);
+ struct coreboot_driver *driver = CB_DRV(dev->driver);
+
+ if (driver->remove)
+ ret = driver->remove(device);
+
+ return ret;
+}
+
+static struct bus_type coreboot_bus_type = {
+ .name = "coreboot",
+ .match = coreboot_bus_match,
+ .probe = coreboot_bus_probe,
+ .remove = coreboot_bus_remove,
+};
+
+static int __init coreboot_bus_init(void)
+{
+ return bus_register(&coreboot_bus_type);
+}
+module_init(coreboot_bus_init);
+
+static void coreboot_device_release(struct device *dev)
+{
+ struct coreboot_device *device = CB_DEV(dev);
+
+ kfree(device);
+}
+
+int coreboot_driver_register(struct coreboot_driver *driver)
+{
+ driver->drv.bus = &coreboot_bus_type;
+
+ return driver_register(&driver->drv);
+}
+EXPORT_SYMBOL(coreboot_driver_register);
+
+void coreboot_driver_unregister(struct coreboot_driver *driver)
+{
+ driver_unregister(&driver->drv);
+}
+EXPORT_SYMBOL(coreboot_driver_unregister);
+
+int coreboot_table_init(struct device *dev, void __iomem *ptr)
+{
+ int i, ret;
+ void *ptr_entry;
+ struct coreboot_device *device;
+ struct coreboot_table_entry entry;
+ struct coreboot_table_header header;
+
+ ptr_header = ptr;
+ memcpy_fromio(&header, ptr_header, sizeof(header));
+
+ if (strncmp(header.signature, "LBIO", sizeof(header.signature))) {
+ pr_warn("coreboot_table: coreboot table missing or corrupt!\n");
+ ret = -ENODEV;
+ goto out;
+ }
+
+ ptr_entry = (void *)ptr_header + header.header_bytes;
+ for (i = 0; i < header.table_entries; i++) {
+ memcpy_fromio(&entry, ptr_entry, sizeof(entry));
+
+ device = kzalloc(sizeof(struct device) + entry.size, GFP_KERNEL);
+ if (!device) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ dev_set_name(&device->dev, "coreboot%d", i);
+ device->dev.parent = dev;
+ device->dev.bus = &coreboot_bus_type;
+ device->dev.release = coreboot_device_release;
+ memcpy_fromio(&device->entry, ptr_entry, entry.size);
+
+ ret = device_register(&device->dev);
+ if (ret) {
+ put_device(&device->dev);
+ break;
+ }
+
+ ptr_entry += entry.size;
+ }
+out:
+ iounmap(ptr);
+ return ret;
+}
+EXPORT_SYMBOL(coreboot_table_init);
+
+int coreboot_table_exit(void)
+{
+ if (ptr_header) {
+ bus_unregister(&coreboot_bus_type);
+ ptr_header = NULL;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(coreboot_table_exit);
+
+MODULE_AUTHOR("Google, Inc.");
+MODULE_LICENSE("GPL");