-
Notifications
You must be signed in to change notification settings - Fork 5.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
firmware: google: Implement cbmem in sysfs driver
The CBMEM area is a downward-growing memory region used by coreboot to dynamically allocate tagged data structures ("CBMEM entries") that remain resident during boot. This implements a driver which exports access to the CBMEM entries via sysfs under /sys/bus/coreboot/devices/cbmem-<id>. This implementation is quite versatile. Examples of how it could be used are given below: * Tools like util/cbmem from the coreboot tree could use this driver instead of finding CBMEM in /dev/mem directly. Alternatively, firmware developers debugging an issue may find the sysfs interface more ergonomic than the cbmem tool and choose to use it directly. * The crossystem tool, which exposes verified boot variables, can use this driver to read the vboot work buffer. * Tools which read the BIOS SPI flash (e.g., flashrom) can find the flash layout in CBMEM directly, which is significantly faster than searching the flash directly. Write access is provided to all CBMEM regions via /sys/bus/coreboot/devices/cbmem-<id>/mem, as the existing cbmem tooling updates this memory region, and envisioned use cases with crossystem can benefit from updating memory regions. Link: https://issuetracker.google.com/239604743 Cc: Stephen Boyd <swboyd@chromium.org> Cc: Tzung-Bi Shih <tzungbi@kernel.org> Reviewed-by: Guenter Roeck <groeck@chromium.org> Reviewed-by: Julius Werner <jwerner@chromium.org> Tested-by: Jack Rosenthal <jrosenth@chromium.org> Signed-off-by: Jack Rosenthal <jrosenth@chromium.org> Link: https://lore.kernel.org/r/20221104161528.531248-1-jrosenth@chromium.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- Loading branch information
1 parent
d88bd09
commit 19d5402
Showing
6 changed files
with
220 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
What: /sys/bus/coreboot | ||
Date: August 2022 | ||
Contact: Jack Rosenthal <jrosenth@chromium.org> | ||
Description: | ||
The coreboot bus provides a variety of virtual devices used to | ||
access data structures created by the Coreboot BIOS. | ||
|
||
What: /sys/bus/coreboot/devices/cbmem-<id> | ||
Date: August 2022 | ||
Contact: Jack Rosenthal <jrosenth@chromium.org> | ||
Description: | ||
CBMEM is a downwards-growing memory region created by Coreboot, | ||
and contains tagged data structures to be shared with payloads | ||
in the boot process and the OS. Each CBMEM entry is given a | ||
directory in /sys/bus/coreboot/devices based on its id. | ||
A list of ids known to Coreboot can be found in the coreboot | ||
source tree at | ||
``src/commonlib/bsd/include/commonlib/bsd/cbmem_id.h``. | ||
|
||
What: /sys/bus/coreboot/devices/cbmem-<id>/address | ||
Date: August 2022 | ||
Contact: Jack Rosenthal <jrosenth@chromium.org> | ||
Description: | ||
This is the pyhsical memory address that the CBMEM entry's data | ||
begins at, in hexadecimal (e.g., ``0x76ffe000``). | ||
|
||
What: /sys/bus/coreboot/devices/cbmem-<id>/size | ||
Date: August 2022 | ||
Contact: Jack Rosenthal <jrosenth@chromium.org> | ||
Description: | ||
This is the size of the CBMEM entry's data, in hexadecimal | ||
(e.g., ``0x1234``). | ||
|
||
What: /sys/bus/coreboot/devices/cbmem-<id>/mem | ||
Date: August 2022 | ||
Contact: Jack Rosenthal <jrosenth@chromium.org> | ||
Description: | ||
A file exposing read/write access to the entry's data. Note | ||
that this file does not support mmap(), as coreboot | ||
does not guarantee that the data will be page-aligned. | ||
|
||
The mode of this file is 0600. While there shouldn't be | ||
anything security-sensitive contained in CBMEM, read access | ||
requires root privileges given this is exposing a small subset | ||
of physical memory. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
// SPDX-License-Identifier: GPL-2.0-only | ||
/* | ||
* cbmem.c | ||
* | ||
* Driver for exporting cbmem entries in sysfs. | ||
* | ||
* Copyright 2022 Google LLC | ||
*/ | ||
|
||
#include <linux/device.h> | ||
#include <linux/init.h> | ||
#include <linux/io.h> | ||
#include <linux/kernel.h> | ||
#include <linux/kobject.h> | ||
#include <linux/module.h> | ||
#include <linux/platform_device.h> | ||
#include <linux/slab.h> | ||
#include <linux/sysfs.h> | ||
|
||
#include "coreboot_table.h" | ||
|
||
struct cbmem_entry { | ||
char *mem_file_buf; | ||
u32 size; | ||
}; | ||
|
||
static struct cbmem_entry *to_cbmem_entry(struct kobject *kobj) | ||
{ | ||
return dev_get_drvdata(kobj_to_dev(kobj)); | ||
} | ||
|
||
static ssize_t mem_read(struct file *filp, struct kobject *kobj, | ||
struct bin_attribute *bin_attr, char *buf, loff_t pos, | ||
size_t count) | ||
{ | ||
struct cbmem_entry *entry = to_cbmem_entry(kobj); | ||
|
||
return memory_read_from_buffer(buf, count, &pos, entry->mem_file_buf, | ||
entry->size); | ||
} | ||
|
||
static ssize_t mem_write(struct file *filp, struct kobject *kobj, | ||
struct bin_attribute *bin_attr, char *buf, loff_t pos, | ||
size_t count) | ||
{ | ||
struct cbmem_entry *entry = to_cbmem_entry(kobj); | ||
|
||
if (pos < 0 || pos >= entry->size) | ||
return -EINVAL; | ||
if (count > entry->size - pos) | ||
count = entry->size - pos; | ||
|
||
memcpy(entry->mem_file_buf + pos, buf, count); | ||
return count; | ||
} | ||
static BIN_ATTR_ADMIN_RW(mem, 0); | ||
|
||
static ssize_t address_show(struct device *dev, struct device_attribute *attr, | ||
char *buf) | ||
{ | ||
struct coreboot_device *cbdev = dev_to_coreboot_device(dev); | ||
|
||
return sysfs_emit(buf, "0x%llx\n", cbdev->cbmem_entry.address); | ||
} | ||
static DEVICE_ATTR_RO(address); | ||
|
||
static ssize_t size_show(struct device *dev, struct device_attribute *attr, | ||
char *buf) | ||
{ | ||
struct coreboot_device *cbdev = dev_to_coreboot_device(dev); | ||
|
||
return sysfs_emit(buf, "0x%x\n", cbdev->cbmem_entry.entry_size); | ||
} | ||
static DEVICE_ATTR_RO(size); | ||
|
||
static struct attribute *attrs[] = { | ||
&dev_attr_address.attr, | ||
&dev_attr_size.attr, | ||
NULL, | ||
}; | ||
|
||
static struct bin_attribute *bin_attrs[] = { | ||
&bin_attr_mem, | ||
NULL, | ||
}; | ||
|
||
static const struct attribute_group cbmem_entry_group = { | ||
.attrs = attrs, | ||
.bin_attrs = bin_attrs, | ||
}; | ||
|
||
static const struct attribute_group *dev_groups[] = { | ||
&cbmem_entry_group, | ||
NULL, | ||
}; | ||
|
||
static int cbmem_entry_probe(struct coreboot_device *dev) | ||
{ | ||
struct cbmem_entry *entry; | ||
|
||
entry = devm_kzalloc(&dev->dev, sizeof(*entry), GFP_KERNEL); | ||
if (!entry) | ||
return -ENOMEM; | ||
|
||
dev_set_drvdata(&dev->dev, entry); | ||
entry->mem_file_buf = devm_memremap(&dev->dev, dev->cbmem_entry.address, | ||
dev->cbmem_entry.entry_size, | ||
MEMREMAP_WB); | ||
if (!entry->mem_file_buf) | ||
return -ENOMEM; | ||
|
||
entry->size = dev->cbmem_entry.entry_size; | ||
|
||
return 0; | ||
} | ||
|
||
static struct coreboot_driver cbmem_entry_driver = { | ||
.probe = cbmem_entry_probe, | ||
.drv = { | ||
.name = "cbmem", | ||
.owner = THIS_MODULE, | ||
.dev_groups = dev_groups, | ||
}, | ||
.tag = LB_TAG_CBMEM_ENTRY, | ||
}; | ||
module_coreboot_driver(cbmem_entry_driver); | ||
|
||
MODULE_AUTHOR("Jack Rosenthal <jrosenth@chromium.org>"); | ||
MODULE_LICENSE("GPL"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters