#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/acpi.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <uapi/linux/qemu_fw_cfg.h>
#include <linux/delay.h>
#include <linux/crash_dump.h>
#include <linux/vmcore_info.h>
MODULE_AUTHOR(…) …;
MODULE_DESCRIPTION(…) …;
MODULE_LICENSE(…) …;
static u32 fw_cfg_rev;
static bool fw_cfg_is_mmio;
static phys_addr_t fw_cfg_p_base;
static resource_size_t fw_cfg_p_size;
static void __iomem *fw_cfg_dev_base;
static void __iomem *fw_cfg_reg_ctrl;
static void __iomem *fw_cfg_reg_data;
static void __iomem *fw_cfg_reg_dma;
static DEFINE_MUTEX(fw_cfg_dev_lock);
static void fw_cfg_sel_endianness(u16 key)
{ … }
#ifdef CONFIG_VMCORE_INFO
static inline bool fw_cfg_dma_enabled(void)
{ … }
static void fw_cfg_wait_for_control(struct fw_cfg_dma_access *d)
{ … }
static ssize_t fw_cfg_dma_transfer(void *address, u32 length, u32 control)
{ … }
#endif
static ssize_t fw_cfg_read_blob(u16 key,
void *buf, loff_t pos, size_t count)
{ … }
#ifdef CONFIG_VMCORE_INFO
static ssize_t fw_cfg_write_blob(u16 key,
void *buf, loff_t pos, size_t count)
{ … }
#endif
static void fw_cfg_io_cleanup(void)
{ … }
#if !(defined(FW_CFG_CTRL_OFF) && defined(FW_CFG_DATA_OFF))
# if (defined(CONFIG_ARM) || defined(CONFIG_ARM64) || defined(CONFIG_RISCV))
#define FW_CFG_CTRL_OFF …
#define FW_CFG_DATA_OFF …
#define FW_CFG_DMA_OFF …
# elif defined(CONFIG_PARISC)
#define FW_CFG_CTRL_OFF …
#define FW_CFG_DATA_OFF …
# elif (defined(CONFIG_PPC_PMAC) || defined(CONFIG_SPARC32))
#define FW_CFG_CTRL_OFF …
#define FW_CFG_DATA_OFF …
# elif (defined(CONFIG_X86) || defined(CONFIG_SPARC64))
#define FW_CFG_CTRL_OFF …
#define FW_CFG_DATA_OFF …
#define FW_CFG_DMA_OFF …
# else
# error "QEMU FW_CFG not available on this architecture!"
# endif
#endif
static int fw_cfg_do_platform_probe(struct platform_device *pdev)
{ … }
static ssize_t fw_cfg_showrev(struct kobject *k, struct kobj_attribute *a,
char *buf)
{ … }
static const struct kobj_attribute fw_cfg_rev_attr = …;
struct fw_cfg_sysfs_entry { … };
#ifdef CONFIG_VMCORE_INFO
static ssize_t fw_cfg_write_vmcoreinfo(const struct fw_cfg_file *f)
{ … }
#endif
static inline struct fw_cfg_sysfs_entry *to_entry(struct kobject *kobj)
{ … }
struct fw_cfg_sysfs_attribute { … };
static inline struct fw_cfg_sysfs_attribute *to_attr(struct attribute *attr)
{ … }
static LIST_HEAD(fw_cfg_entry_cache);
static DEFINE_SPINLOCK(fw_cfg_cache_lock);
static inline void fw_cfg_sysfs_cache_enlist(struct fw_cfg_sysfs_entry *entry)
{ … }
static inline void fw_cfg_sysfs_cache_delist(struct fw_cfg_sysfs_entry *entry)
{ … }
static void fw_cfg_sysfs_cache_cleanup(void)
{ … }
#define FW_CFG_SYSFS_ATTR(_attr) …
static ssize_t fw_cfg_sysfs_show_size(struct fw_cfg_sysfs_entry *e, char *buf)
{ … }
static ssize_t fw_cfg_sysfs_show_key(struct fw_cfg_sysfs_entry *e, char *buf)
{ … }
static ssize_t fw_cfg_sysfs_show_name(struct fw_cfg_sysfs_entry *e, char *buf)
{ … }
static FW_CFG_SYSFS_ATTR(size);
static FW_CFG_SYSFS_ATTR(key);
static FW_CFG_SYSFS_ATTR(name);
static struct attribute *fw_cfg_sysfs_entry_attrs[] = …;
ATTRIBUTE_GROUPS(…);
static ssize_t fw_cfg_sysfs_attr_show(struct kobject *kobj, struct attribute *a,
char *buf)
{ … }
static const struct sysfs_ops fw_cfg_sysfs_attr_ops = …;
static void fw_cfg_sysfs_release_entry(struct kobject *kobj)
{ … }
static struct kobj_type fw_cfg_sysfs_entry_ktype = …;
static ssize_t fw_cfg_sysfs_read_raw(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t pos, size_t count)
{ … }
static struct bin_attribute fw_cfg_sysfs_attr_raw = …;
static int fw_cfg_build_symlink(struct kset *dir,
struct kobject *target, const char *name)
{ … }
static void fw_cfg_kset_unregister_recursive(struct kset *kset)
{ … }
static struct kobject *fw_cfg_top_ko;
static struct kobject *fw_cfg_sel_ko;
static struct kset *fw_cfg_fname_kset;
static int fw_cfg_register_file(const struct fw_cfg_file *f)
{ … }
static int fw_cfg_register_dir_entries(void)
{ … }
static inline void fw_cfg_kobj_cleanup(struct kobject *kobj)
{ … }
static int fw_cfg_sysfs_probe(struct platform_device *pdev)
{ … }
static void fw_cfg_sysfs_remove(struct platform_device *pdev)
{ … }
static const struct of_device_id fw_cfg_sysfs_mmio_match[] = …;
MODULE_DEVICE_TABLE(of, fw_cfg_sysfs_mmio_match);
#ifdef CONFIG_ACPI
static const struct acpi_device_id fw_cfg_sysfs_acpi_match[] = …;
MODULE_DEVICE_TABLE(acpi, fw_cfg_sysfs_acpi_match);
#endif
static struct platform_driver fw_cfg_sysfs_driver = …;
#ifdef CONFIG_FW_CFG_SYSFS_CMDLINE
static struct platform_device *fw_cfg_cmdline_dev;
#ifdef CONFIG_PHYS_ADDR_T_64BIT
#define __PHYS_ADDR_PREFIX …
#else
#define __PHYS_ADDR_PREFIX …
#endif
#define PH_ADDR_SCAN_FMT …
#define PH_ADDR_PR_1_FMT …
#define PH_ADDR_PR_3_FMT …
#define PH_ADDR_PR_4_FMT …
static int fw_cfg_cmdline_set(const char *arg, const struct kernel_param *kp)
{ … }
static int fw_cfg_cmdline_get(char *buf, const struct kernel_param *kp)
{ … }
static const struct kernel_param_ops fw_cfg_cmdline_param_ops = …;
device_param_cb(…);
device_param_cb(…);
#endif
static int __init fw_cfg_sysfs_init(void)
{ … }
static void __exit fw_cfg_sysfs_exit(void)
{ … }
module_init(…) …;
module_exit(fw_cfg_sysfs_exit);