940 lines · c
1/*2 * drivers/firmware/qemu_fw_cfg.c3 *4 * Copyright 2015 Carnegie Mellon University5 *6 * Expose entries from QEMU's firmware configuration (fw_cfg) device in7 * sysfs (read-only, under "/sys/firmware/qemu_fw_cfg/...").8 *9 * The fw_cfg device may be instantiated via either an ACPI node (on x8610 * and select subsets of aarch64), a Device Tree node (on arm), or using11 * a kernel module (or command line) parameter with the following syntax:12 *13 * [qemu_fw_cfg.]ioport=<size>@<base>[:<ctrl_off>:<data_off>[:<dma_off>]]14 * or15 * [qemu_fw_cfg.]mmio=<size>@<base>[:<ctrl_off>:<data_off>[:<dma_off>]]16 *17 * where:18 * <size> := size of ioport or mmio range19 * <base> := physical base address of ioport or mmio range20 * <ctrl_off> := (optional) offset of control register21 * <data_off> := (optional) offset of data register22 * <dma_off> := (optional) offset of dma register23 *24 * e.g.:25 * qemu_fw_cfg.ioport=12@0x510:0:1:4 (the default on x86)26 * or27 * qemu_fw_cfg.mmio=16@0x9020000:8:0:16 (the default on arm)28 */29 30#include <linux/module.h>31#include <linux/mod_devicetable.h>32#include <linux/platform_device.h>33#include <linux/acpi.h>34#include <linux/slab.h>35#include <linux/io.h>36#include <linux/ioport.h>37#include <uapi/linux/qemu_fw_cfg.h>38#include <linux/delay.h>39#include <linux/crash_dump.h>40#include <linux/vmcore_info.h>41 42MODULE_AUTHOR("Gabriel L. Somlo <somlo@cmu.edu>");43MODULE_DESCRIPTION("QEMU fw_cfg sysfs support");44MODULE_LICENSE("GPL");45 46/* fw_cfg revision attribute, in /sys/firmware/qemu_fw_cfg top-level dir. */47static u32 fw_cfg_rev;48 49/* fw_cfg device i/o register addresses */50static bool fw_cfg_is_mmio;51static phys_addr_t fw_cfg_p_base;52static resource_size_t fw_cfg_p_size;53static void __iomem *fw_cfg_dev_base;54static void __iomem *fw_cfg_reg_ctrl;55static void __iomem *fw_cfg_reg_data;56static void __iomem *fw_cfg_reg_dma;57 58/* atomic access to fw_cfg device (potentially slow i/o, so using mutex) */59static DEFINE_MUTEX(fw_cfg_dev_lock);60 61/* pick appropriate endianness for selector key */62static void fw_cfg_sel_endianness(u16 key)63{64 if (fw_cfg_is_mmio)65 iowrite16be(key, fw_cfg_reg_ctrl);66 else67 iowrite16(key, fw_cfg_reg_ctrl);68}69 70#ifdef CONFIG_VMCORE_INFO71static inline bool fw_cfg_dma_enabled(void)72{73 return (fw_cfg_rev & FW_CFG_VERSION_DMA) && fw_cfg_reg_dma;74}75 76/* qemu fw_cfg device is sync today, but spec says it may become async */77static void fw_cfg_wait_for_control(struct fw_cfg_dma_access *d)78{79 for (;;) {80 u32 ctrl = be32_to_cpu(READ_ONCE(d->control));81 82 /* do not reorder the read to d->control */83 rmb();84 if ((ctrl & ~FW_CFG_DMA_CTL_ERROR) == 0)85 return;86 87 cpu_relax();88 }89}90 91static ssize_t fw_cfg_dma_transfer(void *address, u32 length, u32 control)92{93 phys_addr_t dma;94 struct fw_cfg_dma_access *d = NULL;95 ssize_t ret = length;96 97 d = kmalloc(sizeof(*d), GFP_KERNEL);98 if (!d) {99 ret = -ENOMEM;100 goto end;101 }102 103 /* fw_cfg device does not need IOMMU protection, so use physical addresses */104 *d = (struct fw_cfg_dma_access) {105 .address = cpu_to_be64(address ? virt_to_phys(address) : 0),106 .length = cpu_to_be32(length),107 .control = cpu_to_be32(control)108 };109 110 dma = virt_to_phys(d);111 112 iowrite32be((u64)dma >> 32, fw_cfg_reg_dma);113 /* force memory to sync before notifying device via MMIO */114 wmb();115 iowrite32be(dma, fw_cfg_reg_dma + 4);116 117 fw_cfg_wait_for_control(d);118 119 if (be32_to_cpu(READ_ONCE(d->control)) & FW_CFG_DMA_CTL_ERROR) {120 ret = -EIO;121 }122 123end:124 kfree(d);125 126 return ret;127}128#endif129 130/* read chunk of given fw_cfg blob (caller responsible for sanity-check) */131static ssize_t fw_cfg_read_blob(u16 key,132 void *buf, loff_t pos, size_t count)133{134 u32 glk = -1U;135 acpi_status status;136 137 /* If we have ACPI, ensure mutual exclusion against any potential138 * device access by the firmware, e.g. via AML methods:139 */140 status = acpi_acquire_global_lock(ACPI_WAIT_FOREVER, &glk);141 if (ACPI_FAILURE(status) && status != AE_NOT_CONFIGURED) {142 /* Should never get here */143 WARN(1, "fw_cfg_read_blob: Failed to lock ACPI!\n");144 memset(buf, 0, count);145 return -EINVAL;146 }147 148 mutex_lock(&fw_cfg_dev_lock);149 fw_cfg_sel_endianness(key);150 while (pos-- > 0)151 ioread8(fw_cfg_reg_data);152 ioread8_rep(fw_cfg_reg_data, buf, count);153 mutex_unlock(&fw_cfg_dev_lock);154 155 acpi_release_global_lock(glk);156 return count;157}158 159#ifdef CONFIG_VMCORE_INFO160/* write chunk of given fw_cfg blob (caller responsible for sanity-check) */161static ssize_t fw_cfg_write_blob(u16 key,162 void *buf, loff_t pos, size_t count)163{164 u32 glk = -1U;165 acpi_status status;166 ssize_t ret = count;167 168 /* If we have ACPI, ensure mutual exclusion against any potential169 * device access by the firmware, e.g. via AML methods:170 */171 status = acpi_acquire_global_lock(ACPI_WAIT_FOREVER, &glk);172 if (ACPI_FAILURE(status) && status != AE_NOT_CONFIGURED) {173 /* Should never get here */174 WARN(1, "%s: Failed to lock ACPI!\n", __func__);175 return -EINVAL;176 }177 178 mutex_lock(&fw_cfg_dev_lock);179 if (pos == 0) {180 ret = fw_cfg_dma_transfer(buf, count, key << 16181 | FW_CFG_DMA_CTL_SELECT182 | FW_CFG_DMA_CTL_WRITE);183 } else {184 fw_cfg_sel_endianness(key);185 ret = fw_cfg_dma_transfer(NULL, pos, FW_CFG_DMA_CTL_SKIP);186 if (ret < 0)187 goto end;188 ret = fw_cfg_dma_transfer(buf, count, FW_CFG_DMA_CTL_WRITE);189 }190 191end:192 mutex_unlock(&fw_cfg_dev_lock);193 194 acpi_release_global_lock(glk);195 196 return ret;197}198#endif /* CONFIG_VMCORE_INFO */199 200/* clean up fw_cfg device i/o */201static void fw_cfg_io_cleanup(void)202{203 if (fw_cfg_is_mmio) {204 iounmap(fw_cfg_dev_base);205 release_mem_region(fw_cfg_p_base, fw_cfg_p_size);206 } else {207 ioport_unmap(fw_cfg_dev_base);208 release_region(fw_cfg_p_base, fw_cfg_p_size);209 }210}211 212/* arch-specific ctrl & data register offsets are not available in ACPI, DT */213#if !(defined(FW_CFG_CTRL_OFF) && defined(FW_CFG_DATA_OFF))214# if (defined(CONFIG_ARM) || defined(CONFIG_ARM64) || defined(CONFIG_RISCV))215# define FW_CFG_CTRL_OFF 0x08216# define FW_CFG_DATA_OFF 0x00217# define FW_CFG_DMA_OFF 0x10218# elif defined(CONFIG_PARISC) /* parisc */219# define FW_CFG_CTRL_OFF 0x00220# define FW_CFG_DATA_OFF 0x04221# elif (defined(CONFIG_PPC_PMAC) || defined(CONFIG_SPARC32)) /* ppc/mac,sun4m */222# define FW_CFG_CTRL_OFF 0x00223# define FW_CFG_DATA_OFF 0x02224# elif (defined(CONFIG_X86) || defined(CONFIG_SPARC64)) /* x86, sun4u */225# define FW_CFG_CTRL_OFF 0x00226# define FW_CFG_DATA_OFF 0x01227# define FW_CFG_DMA_OFF 0x04228# else229# error "QEMU FW_CFG not available on this architecture!"230# endif231#endif232 233/* initialize fw_cfg device i/o from platform data */234static int fw_cfg_do_platform_probe(struct platform_device *pdev)235{236 char sig[FW_CFG_SIG_SIZE];237 struct resource *range, *ctrl, *data, *dma;238 239 /* acquire i/o range details */240 fw_cfg_is_mmio = false;241 range = platform_get_resource(pdev, IORESOURCE_IO, 0);242 if (!range) {243 fw_cfg_is_mmio = true;244 range = platform_get_resource(pdev, IORESOURCE_MEM, 0);245 if (!range)246 return -EINVAL;247 }248 fw_cfg_p_base = range->start;249 fw_cfg_p_size = resource_size(range);250 251 if (fw_cfg_is_mmio) {252 if (!request_mem_region(fw_cfg_p_base,253 fw_cfg_p_size, "fw_cfg_mem"))254 return -EBUSY;255 fw_cfg_dev_base = ioremap(fw_cfg_p_base, fw_cfg_p_size);256 if (!fw_cfg_dev_base) {257 release_mem_region(fw_cfg_p_base, fw_cfg_p_size);258 return -EFAULT;259 }260 } else {261 if (!request_region(fw_cfg_p_base,262 fw_cfg_p_size, "fw_cfg_io"))263 return -EBUSY;264 fw_cfg_dev_base = ioport_map(fw_cfg_p_base, fw_cfg_p_size);265 if (!fw_cfg_dev_base) {266 release_region(fw_cfg_p_base, fw_cfg_p_size);267 return -EFAULT;268 }269 }270 271 /* were custom register offsets provided (e.g. on the command line)? */272 ctrl = platform_get_resource_byname(pdev, IORESOURCE_REG, "ctrl");273 data = platform_get_resource_byname(pdev, IORESOURCE_REG, "data");274 dma = platform_get_resource_byname(pdev, IORESOURCE_REG, "dma");275 if (ctrl && data) {276 fw_cfg_reg_ctrl = fw_cfg_dev_base + ctrl->start;277 fw_cfg_reg_data = fw_cfg_dev_base + data->start;278 } else {279 /* use architecture-specific offsets */280 fw_cfg_reg_ctrl = fw_cfg_dev_base + FW_CFG_CTRL_OFF;281 fw_cfg_reg_data = fw_cfg_dev_base + FW_CFG_DATA_OFF;282 }283 284 if (dma)285 fw_cfg_reg_dma = fw_cfg_dev_base + dma->start;286#ifdef FW_CFG_DMA_OFF287 else288 fw_cfg_reg_dma = fw_cfg_dev_base + FW_CFG_DMA_OFF;289#endif290 291 /* verify fw_cfg device signature */292 if (fw_cfg_read_blob(FW_CFG_SIGNATURE, sig,293 0, FW_CFG_SIG_SIZE) < 0 ||294 memcmp(sig, "QEMU", FW_CFG_SIG_SIZE) != 0) {295 fw_cfg_io_cleanup();296 return -ENODEV;297 }298 299 return 0;300}301 302static ssize_t fw_cfg_showrev(struct kobject *k, struct kobj_attribute *a,303 char *buf)304{305 return sprintf(buf, "%u\n", fw_cfg_rev);306}307 308static const struct kobj_attribute fw_cfg_rev_attr = {309 .attr = { .name = "rev", .mode = S_IRUSR },310 .show = fw_cfg_showrev,311};312 313/* fw_cfg_sysfs_entry type */314struct fw_cfg_sysfs_entry {315 struct kobject kobj;316 u32 size;317 u16 select;318 char name[FW_CFG_MAX_FILE_PATH];319 struct list_head list;320};321 322#ifdef CONFIG_VMCORE_INFO323static ssize_t fw_cfg_write_vmcoreinfo(const struct fw_cfg_file *f)324{325 static struct fw_cfg_vmcoreinfo *data;326 ssize_t ret;327 328 data = kmalloc(sizeof(struct fw_cfg_vmcoreinfo), GFP_KERNEL);329 if (!data)330 return -ENOMEM;331 332 *data = (struct fw_cfg_vmcoreinfo) {333 .guest_format = cpu_to_le16(FW_CFG_VMCOREINFO_FORMAT_ELF),334 .size = cpu_to_le32(VMCOREINFO_NOTE_SIZE),335 .paddr = cpu_to_le64(paddr_vmcoreinfo_note())336 };337 /* spare ourself reading host format support for now since we338 * don't know what else to format - host may ignore ours339 */340 ret = fw_cfg_write_blob(be16_to_cpu(f->select), data,341 0, sizeof(struct fw_cfg_vmcoreinfo));342 343 kfree(data);344 return ret;345}346#endif /* CONFIG_VMCORE_INFO */347 348/* get fw_cfg_sysfs_entry from kobject member */349static inline struct fw_cfg_sysfs_entry *to_entry(struct kobject *kobj)350{351 return container_of(kobj, struct fw_cfg_sysfs_entry, kobj);352}353 354/* fw_cfg_sysfs_attribute type */355struct fw_cfg_sysfs_attribute {356 struct attribute attr;357 ssize_t (*show)(struct fw_cfg_sysfs_entry *entry, char *buf);358};359 360/* get fw_cfg_sysfs_attribute from attribute member */361static inline struct fw_cfg_sysfs_attribute *to_attr(struct attribute *attr)362{363 return container_of(attr, struct fw_cfg_sysfs_attribute, attr);364}365 366/* global cache of fw_cfg_sysfs_entry objects */367static LIST_HEAD(fw_cfg_entry_cache);368 369/* kobjects removed lazily by kernel, mutual exclusion needed */370static DEFINE_SPINLOCK(fw_cfg_cache_lock);371 372static inline void fw_cfg_sysfs_cache_enlist(struct fw_cfg_sysfs_entry *entry)373{374 spin_lock(&fw_cfg_cache_lock);375 list_add_tail(&entry->list, &fw_cfg_entry_cache);376 spin_unlock(&fw_cfg_cache_lock);377}378 379static inline void fw_cfg_sysfs_cache_delist(struct fw_cfg_sysfs_entry *entry)380{381 spin_lock(&fw_cfg_cache_lock);382 list_del(&entry->list);383 spin_unlock(&fw_cfg_cache_lock);384}385 386static void fw_cfg_sysfs_cache_cleanup(void)387{388 struct fw_cfg_sysfs_entry *entry, *next;389 390 list_for_each_entry_safe(entry, next, &fw_cfg_entry_cache, list) {391 fw_cfg_sysfs_cache_delist(entry);392 kobject_del(&entry->kobj);393 kobject_put(&entry->kobj);394 }395}396 397/* per-entry attributes and show methods */398 399#define FW_CFG_SYSFS_ATTR(_attr) \400struct fw_cfg_sysfs_attribute fw_cfg_sysfs_attr_##_attr = { \401 .attr = { .name = __stringify(_attr), .mode = S_IRUSR }, \402 .show = fw_cfg_sysfs_show_##_attr, \403}404 405static ssize_t fw_cfg_sysfs_show_size(struct fw_cfg_sysfs_entry *e, char *buf)406{407 return sprintf(buf, "%u\n", e->size);408}409 410static ssize_t fw_cfg_sysfs_show_key(struct fw_cfg_sysfs_entry *e, char *buf)411{412 return sprintf(buf, "%u\n", e->select);413}414 415static ssize_t fw_cfg_sysfs_show_name(struct fw_cfg_sysfs_entry *e, char *buf)416{417 return sprintf(buf, "%s\n", e->name);418}419 420static FW_CFG_SYSFS_ATTR(size);421static FW_CFG_SYSFS_ATTR(key);422static FW_CFG_SYSFS_ATTR(name);423 424static struct attribute *fw_cfg_sysfs_entry_attrs[] = {425 &fw_cfg_sysfs_attr_size.attr,426 &fw_cfg_sysfs_attr_key.attr,427 &fw_cfg_sysfs_attr_name.attr,428 NULL,429};430ATTRIBUTE_GROUPS(fw_cfg_sysfs_entry);431 432/* sysfs_ops: find fw_cfg_[entry, attribute] and call appropriate show method */433static ssize_t fw_cfg_sysfs_attr_show(struct kobject *kobj, struct attribute *a,434 char *buf)435{436 struct fw_cfg_sysfs_entry *entry = to_entry(kobj);437 struct fw_cfg_sysfs_attribute *attr = to_attr(a);438 439 return attr->show(entry, buf);440}441 442static const struct sysfs_ops fw_cfg_sysfs_attr_ops = {443 .show = fw_cfg_sysfs_attr_show,444};445 446/* release: destructor, to be called via kobject_put() */447static void fw_cfg_sysfs_release_entry(struct kobject *kobj)448{449 struct fw_cfg_sysfs_entry *entry = to_entry(kobj);450 451 kfree(entry);452}453 454/* kobj_type: ties together all properties required to register an entry */455static const struct kobj_type fw_cfg_sysfs_entry_ktype = {456 .default_groups = fw_cfg_sysfs_entry_groups,457 .sysfs_ops = &fw_cfg_sysfs_attr_ops,458 .release = fw_cfg_sysfs_release_entry,459};460 461/* raw-read method and attribute */462static ssize_t fw_cfg_sysfs_read_raw(struct file *filp, struct kobject *kobj,463 struct bin_attribute *bin_attr,464 char *buf, loff_t pos, size_t count)465{466 struct fw_cfg_sysfs_entry *entry = to_entry(kobj);467 468 if (pos > entry->size)469 return -EINVAL;470 471 if (count > entry->size - pos)472 count = entry->size - pos;473 474 return fw_cfg_read_blob(entry->select, buf, pos, count);475}476 477static struct bin_attribute fw_cfg_sysfs_attr_raw = {478 .attr = { .name = "raw", .mode = S_IRUSR },479 .read = fw_cfg_sysfs_read_raw,480};481 482/*483 * Create a kset subdirectory matching each '/' delimited dirname token484 * in 'name', starting with sysfs kset/folder 'dir'; At the end, create485 * a symlink directed at the given 'target'.486 * NOTE: We do this on a best-effort basis, since 'name' is not guaranteed487 * to be a well-behaved path name. Whenever a symlink vs. kset directory488 * name collision occurs, the kernel will issue big scary warnings while489 * refusing to add the offending link or directory. We follow up with our490 * own, slightly less scary error messages explaining the situation :)491 */492static int fw_cfg_build_symlink(struct kset *dir,493 struct kobject *target, const char *name)494{495 int ret;496 struct kset *subdir;497 struct kobject *ko;498 char *name_copy, *p, *tok;499 500 if (!dir || !target || !name || !*name)501 return -EINVAL;502 503 /* clone a copy of name for parsing */504 name_copy = p = kstrdup(name, GFP_KERNEL);505 if (!name_copy)506 return -ENOMEM;507 508 /* create folders for each dirname token, then symlink for basename */509 while ((tok = strsep(&p, "/")) && *tok) {510 511 /* last (basename) token? If so, add symlink here */512 if (!p || !*p) {513 ret = sysfs_create_link(&dir->kobj, target, tok);514 break;515 }516 517 /* does the current dir contain an item named after tok ? */518 ko = kset_find_obj(dir, tok);519 if (ko) {520 /* drop reference added by kset_find_obj */521 kobject_put(ko);522 523 /* ko MUST be a kset - we're about to use it as one ! */524 if (ko->ktype != dir->kobj.ktype) {525 ret = -EINVAL;526 break;527 }528 529 /* descend into already existing subdirectory */530 dir = to_kset(ko);531 } else {532 /* create new subdirectory kset */533 subdir = kzalloc(sizeof(struct kset), GFP_KERNEL);534 if (!subdir) {535 ret = -ENOMEM;536 break;537 }538 subdir->kobj.kset = dir;539 subdir->kobj.ktype = dir->kobj.ktype;540 ret = kobject_set_name(&subdir->kobj, "%s", tok);541 if (ret) {542 kfree(subdir);543 break;544 }545 ret = kset_register(subdir);546 if (ret) {547 kfree(subdir);548 break;549 }550 551 /* descend into newly created subdirectory */552 dir = subdir;553 }554 }555 556 /* we're done with cloned copy of name */557 kfree(name_copy);558 return ret;559}560 561/* recursively unregister fw_cfg/by_name/ kset directory tree */562static void fw_cfg_kset_unregister_recursive(struct kset *kset)563{564 struct kobject *k, *next;565 566 list_for_each_entry_safe(k, next, &kset->list, entry)567 /* all set members are ksets too, but check just in case... */568 if (k->ktype == kset->kobj.ktype)569 fw_cfg_kset_unregister_recursive(to_kset(k));570 571 /* symlinks are cleanly and automatically removed with the directory */572 kset_unregister(kset);573}574 575/* kobjects & kset representing top-level, by_key, and by_name folders */576static struct kobject *fw_cfg_top_ko;577static struct kobject *fw_cfg_sel_ko;578static struct kset *fw_cfg_fname_kset;579 580/* register an individual fw_cfg file */581static int fw_cfg_register_file(const struct fw_cfg_file *f)582{583 int err;584 struct fw_cfg_sysfs_entry *entry;585 586#ifdef CONFIG_VMCORE_INFO587 if (fw_cfg_dma_enabled() &&588 strcmp(f->name, FW_CFG_VMCOREINFO_FILENAME) == 0 &&589 !is_kdump_kernel()) {590 if (fw_cfg_write_vmcoreinfo(f) < 0)591 pr_warn("fw_cfg: failed to write vmcoreinfo");592 }593#endif594 595 /* allocate new entry */596 entry = kzalloc(sizeof(*entry), GFP_KERNEL);597 if (!entry)598 return -ENOMEM;599 600 /* set file entry information */601 entry->size = be32_to_cpu(f->size);602 entry->select = be16_to_cpu(f->select);603 strscpy(entry->name, f->name, FW_CFG_MAX_FILE_PATH);604 605 /* register entry under "/sys/firmware/qemu_fw_cfg/by_key/" */606 err = kobject_init_and_add(&entry->kobj, &fw_cfg_sysfs_entry_ktype,607 fw_cfg_sel_ko, "%d", entry->select);608 if (err)609 goto err_put_entry;610 611 /* add raw binary content access */612 err = sysfs_create_bin_file(&entry->kobj, &fw_cfg_sysfs_attr_raw);613 if (err)614 goto err_del_entry;615 616 /* try adding "/sys/firmware/qemu_fw_cfg/by_name/" symlink */617 fw_cfg_build_symlink(fw_cfg_fname_kset, &entry->kobj, entry->name);618 619 /* success, add entry to global cache */620 fw_cfg_sysfs_cache_enlist(entry);621 return 0;622 623err_del_entry:624 kobject_del(&entry->kobj);625err_put_entry:626 kobject_put(&entry->kobj);627 return err;628}629 630/* iterate over all fw_cfg directory entries, registering each one */631static int fw_cfg_register_dir_entries(void)632{633 int ret = 0;634 __be32 files_count;635 u32 count, i;636 struct fw_cfg_file *dir;637 size_t dir_size;638 639 ret = fw_cfg_read_blob(FW_CFG_FILE_DIR, &files_count,640 0, sizeof(files_count));641 if (ret < 0)642 return ret;643 644 count = be32_to_cpu(files_count);645 dir_size = count * sizeof(struct fw_cfg_file);646 647 dir = kmalloc(dir_size, GFP_KERNEL);648 if (!dir)649 return -ENOMEM;650 651 ret = fw_cfg_read_blob(FW_CFG_FILE_DIR, dir,652 sizeof(files_count), dir_size);653 if (ret < 0)654 goto end;655 656 for (i = 0; i < count; i++) {657 ret = fw_cfg_register_file(&dir[i]);658 if (ret)659 break;660 }661 662end:663 kfree(dir);664 return ret;665}666 667/* unregister top-level or by_key folder */668static inline void fw_cfg_kobj_cleanup(struct kobject *kobj)669{670 kobject_del(kobj);671 kobject_put(kobj);672}673 674static int fw_cfg_sysfs_probe(struct platform_device *pdev)675{676 int err;677 __le32 rev;678 679 /* NOTE: If we supported multiple fw_cfg devices, we'd first create680 * a subdirectory named after e.g. pdev->id, then hang per-device681 * by_key (and by_name) subdirectories underneath it. However, only682 * one fw_cfg device exist system-wide, so if one was already found683 * earlier, we might as well stop here.684 */685 if (fw_cfg_sel_ko)686 return -EBUSY;687 688 /* create by_key and by_name subdirs of /sys/firmware/qemu_fw_cfg/ */689 err = -ENOMEM;690 fw_cfg_sel_ko = kobject_create_and_add("by_key", fw_cfg_top_ko);691 if (!fw_cfg_sel_ko)692 goto err_sel;693 fw_cfg_fname_kset = kset_create_and_add("by_name", NULL, fw_cfg_top_ko);694 if (!fw_cfg_fname_kset)695 goto err_name;696 697 /* initialize fw_cfg device i/o from platform data */698 err = fw_cfg_do_platform_probe(pdev);699 if (err)700 goto err_probe;701 702 /* get revision number, add matching top-level attribute */703 err = fw_cfg_read_blob(FW_CFG_ID, &rev, 0, sizeof(rev));704 if (err < 0)705 goto err_probe;706 707 fw_cfg_rev = le32_to_cpu(rev);708 err = sysfs_create_file(fw_cfg_top_ko, &fw_cfg_rev_attr.attr);709 if (err)710 goto err_rev;711 712 /* process fw_cfg file directory entry, registering each file */713 err = fw_cfg_register_dir_entries();714 if (err)715 goto err_dir;716 717 /* success */718 pr_debug("fw_cfg: loaded.\n");719 return 0;720 721err_dir:722 fw_cfg_sysfs_cache_cleanup();723 sysfs_remove_file(fw_cfg_top_ko, &fw_cfg_rev_attr.attr);724err_rev:725 fw_cfg_io_cleanup();726err_probe:727 fw_cfg_kset_unregister_recursive(fw_cfg_fname_kset);728err_name:729 fw_cfg_kobj_cleanup(fw_cfg_sel_ko);730err_sel:731 return err;732}733 734static void fw_cfg_sysfs_remove(struct platform_device *pdev)735{736 pr_debug("fw_cfg: unloading.\n");737 fw_cfg_sysfs_cache_cleanup();738 sysfs_remove_file(fw_cfg_top_ko, &fw_cfg_rev_attr.attr);739 fw_cfg_io_cleanup();740 fw_cfg_kset_unregister_recursive(fw_cfg_fname_kset);741 fw_cfg_kobj_cleanup(fw_cfg_sel_ko);742}743 744static const struct of_device_id fw_cfg_sysfs_mmio_match[] = {745 { .compatible = "qemu,fw-cfg-mmio", },746 {},747};748MODULE_DEVICE_TABLE(of, fw_cfg_sysfs_mmio_match);749 750#ifdef CONFIG_ACPI751static const struct acpi_device_id fw_cfg_sysfs_acpi_match[] = {752 { FW_CFG_ACPI_DEVICE_ID, },753 {},754};755MODULE_DEVICE_TABLE(acpi, fw_cfg_sysfs_acpi_match);756#endif757 758static struct platform_driver fw_cfg_sysfs_driver = {759 .probe = fw_cfg_sysfs_probe,760 .remove_new = fw_cfg_sysfs_remove,761 .driver = {762 .name = "fw_cfg",763 .of_match_table = fw_cfg_sysfs_mmio_match,764 .acpi_match_table = ACPI_PTR(fw_cfg_sysfs_acpi_match),765 },766};767 768#ifdef CONFIG_FW_CFG_SYSFS_CMDLINE769 770static struct platform_device *fw_cfg_cmdline_dev;771 772/* this probably belongs in e.g. include/linux/types.h,773 * but right now we are the only ones doing it...774 */775#ifdef CONFIG_PHYS_ADDR_T_64BIT776#define __PHYS_ADDR_PREFIX "ll"777#else778#define __PHYS_ADDR_PREFIX ""779#endif780 781/* use special scanf/printf modifier for phys_addr_t, resource_size_t */782#define PH_ADDR_SCAN_FMT "@%" __PHYS_ADDR_PREFIX "i%n" \783 ":%" __PHYS_ADDR_PREFIX "i" \784 ":%" __PHYS_ADDR_PREFIX "i%n" \785 ":%" __PHYS_ADDR_PREFIX "i%n"786 787#define PH_ADDR_PR_1_FMT "0x%" __PHYS_ADDR_PREFIX "x@" \788 "0x%" __PHYS_ADDR_PREFIX "x"789 790#define PH_ADDR_PR_3_FMT PH_ADDR_PR_1_FMT \791 ":%" __PHYS_ADDR_PREFIX "u" \792 ":%" __PHYS_ADDR_PREFIX "u"793 794#define PH_ADDR_PR_4_FMT PH_ADDR_PR_3_FMT \795 ":%" __PHYS_ADDR_PREFIX "u"796 797static int fw_cfg_cmdline_set(const char *arg, const struct kernel_param *kp)798{799 struct resource res[4] = {};800 char *str;801 phys_addr_t base;802 resource_size_t size, ctrl_off, data_off, dma_off;803 int processed, consumed = 0;804 805 /* only one fw_cfg device can exist system-wide, so if one806 * was processed on the command line already, we might as807 * well stop here.808 */809 if (fw_cfg_cmdline_dev) {810 /* avoid leaking previously registered device */811 platform_device_unregister(fw_cfg_cmdline_dev);812 return -EINVAL;813 }814 815 /* consume "<size>" portion of command line argument */816 size = memparse(arg, &str);817 818 /* get "@<base>[:<ctrl_off>:<data_off>[:<dma_off>]]" chunks */819 processed = sscanf(str, PH_ADDR_SCAN_FMT,820 &base, &consumed,821 &ctrl_off, &data_off, &consumed,822 &dma_off, &consumed);823 824 /* sscanf() must process precisely 1, 3 or 4 chunks:825 * <base> is mandatory, optionally followed by <ctrl_off>826 * and <data_off>, and <dma_off>;827 * there must be no extra characters after the last chunk,828 * so str[consumed] must be '\0'.829 */830 if (str[consumed] ||831 (processed != 1 && processed != 3 && processed != 4))832 return -EINVAL;833 834 res[0].start = base;835 res[0].end = base + size - 1;836 res[0].flags = !strcmp(kp->name, "mmio") ? IORESOURCE_MEM :837 IORESOURCE_IO;838 839 /* insert register offsets, if provided */840 if (processed > 1) {841 res[1].name = "ctrl";842 res[1].start = ctrl_off;843 res[1].flags = IORESOURCE_REG;844 res[2].name = "data";845 res[2].start = data_off;846 res[2].flags = IORESOURCE_REG;847 }848 if (processed > 3) {849 res[3].name = "dma";850 res[3].start = dma_off;851 res[3].flags = IORESOURCE_REG;852 }853 854 /* "processed" happens to nicely match the number of resources855 * we need to pass in to this platform device.856 */857 fw_cfg_cmdline_dev = platform_device_register_simple("fw_cfg",858 PLATFORM_DEVID_NONE, res, processed);859 860 return PTR_ERR_OR_ZERO(fw_cfg_cmdline_dev);861}862 863static int fw_cfg_cmdline_get(char *buf, const struct kernel_param *kp)864{865 /* stay silent if device was not configured via the command866 * line, or if the parameter name (ioport/mmio) doesn't match867 * the device setting868 */869 if (!fw_cfg_cmdline_dev ||870 (!strcmp(kp->name, "mmio") ^871 (fw_cfg_cmdline_dev->resource[0].flags == IORESOURCE_MEM)))872 return 0;873 874 switch (fw_cfg_cmdline_dev->num_resources) {875 case 1:876 return snprintf(buf, PAGE_SIZE, PH_ADDR_PR_1_FMT,877 resource_size(&fw_cfg_cmdline_dev->resource[0]),878 fw_cfg_cmdline_dev->resource[0].start);879 case 3:880 return snprintf(buf, PAGE_SIZE, PH_ADDR_PR_3_FMT,881 resource_size(&fw_cfg_cmdline_dev->resource[0]),882 fw_cfg_cmdline_dev->resource[0].start,883 fw_cfg_cmdline_dev->resource[1].start,884 fw_cfg_cmdline_dev->resource[2].start);885 case 4:886 return snprintf(buf, PAGE_SIZE, PH_ADDR_PR_4_FMT,887 resource_size(&fw_cfg_cmdline_dev->resource[0]),888 fw_cfg_cmdline_dev->resource[0].start,889 fw_cfg_cmdline_dev->resource[1].start,890 fw_cfg_cmdline_dev->resource[2].start,891 fw_cfg_cmdline_dev->resource[3].start);892 }893 894 /* Should never get here */895 WARN(1, "Unexpected number of resources: %d\n",896 fw_cfg_cmdline_dev->num_resources);897 return 0;898}899 900static const struct kernel_param_ops fw_cfg_cmdline_param_ops = {901 .set = fw_cfg_cmdline_set,902 .get = fw_cfg_cmdline_get,903};904 905device_param_cb(ioport, &fw_cfg_cmdline_param_ops, NULL, S_IRUSR);906device_param_cb(mmio, &fw_cfg_cmdline_param_ops, NULL, S_IRUSR);907 908#endif /* CONFIG_FW_CFG_SYSFS_CMDLINE */909 910static int __init fw_cfg_sysfs_init(void)911{912 int ret;913 914 /* create /sys/firmware/qemu_fw_cfg/ top level directory */915 fw_cfg_top_ko = kobject_create_and_add("qemu_fw_cfg", firmware_kobj);916 if (!fw_cfg_top_ko)917 return -ENOMEM;918 919 ret = platform_driver_register(&fw_cfg_sysfs_driver);920 if (ret)921 fw_cfg_kobj_cleanup(fw_cfg_top_ko);922 923 return ret;924}925 926static void __exit fw_cfg_sysfs_exit(void)927{928 platform_driver_unregister(&fw_cfg_sysfs_driver);929 930#ifdef CONFIG_FW_CFG_SYSFS_CMDLINE931 platform_device_unregister(fw_cfg_cmdline_dev);932#endif933 934 /* clean up /sys/firmware/qemu_fw_cfg/ */935 fw_cfg_kobj_cleanup(fw_cfg_top_ko);936}937 938module_init(fw_cfg_sysfs_init);939module_exit(fw_cfg_sysfs_exit);940