coreboot_table.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /*
  2. * coreboot_table.c
  3. *
  4. * Module providing coreboot table access.
  5. *
  6. * Copyright 2017 Google Inc.
  7. * Copyright 2017 Samuel Holland <samuel@sholland.org>
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License v2.0 as published by
  11. * the Free Software Foundation.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. */
  18. #include <linux/device.h>
  19. #include <linux/err.h>
  20. #include <linux/init.h>
  21. #include <linux/io.h>
  22. #include <linux/kernel.h>
  23. #include <linux/module.h>
  24. #include <linux/slab.h>
  25. #include "coreboot_table.h"
  26. #define CB_DEV(d) container_of(d, struct coreboot_device, dev)
  27. #define CB_DRV(d) container_of(d, struct coreboot_driver, drv)
  28. static struct coreboot_table_header __iomem *ptr_header;
  29. static int coreboot_bus_match(struct device *dev, struct device_driver *drv)
  30. {
  31. struct coreboot_device *device = CB_DEV(dev);
  32. struct coreboot_driver *driver = CB_DRV(drv);
  33. return device->entry.tag == driver->tag;
  34. }
  35. static int coreboot_bus_probe(struct device *dev)
  36. {
  37. int ret = -ENODEV;
  38. struct coreboot_device *device = CB_DEV(dev);
  39. struct coreboot_driver *driver = CB_DRV(dev->driver);
  40. if (driver->probe)
  41. ret = driver->probe(device);
  42. return ret;
  43. }
  44. static int coreboot_bus_remove(struct device *dev)
  45. {
  46. int ret = 0;
  47. struct coreboot_device *device = CB_DEV(dev);
  48. struct coreboot_driver *driver = CB_DRV(dev->driver);
  49. if (driver->remove)
  50. ret = driver->remove(device);
  51. return ret;
  52. }
  53. static struct bus_type coreboot_bus_type = {
  54. .name = "coreboot",
  55. .match = coreboot_bus_match,
  56. .probe = coreboot_bus_probe,
  57. .remove = coreboot_bus_remove,
  58. };
  59. static int __init coreboot_bus_init(void)
  60. {
  61. return bus_register(&coreboot_bus_type);
  62. }
  63. module_init(coreboot_bus_init);
  64. static void coreboot_device_release(struct device *dev)
  65. {
  66. struct coreboot_device *device = CB_DEV(dev);
  67. kfree(device);
  68. }
  69. int coreboot_driver_register(struct coreboot_driver *driver)
  70. {
  71. driver->drv.bus = &coreboot_bus_type;
  72. return driver_register(&driver->drv);
  73. }
  74. EXPORT_SYMBOL(coreboot_driver_register);
  75. void coreboot_driver_unregister(struct coreboot_driver *driver)
  76. {
  77. driver_unregister(&driver->drv);
  78. }
  79. EXPORT_SYMBOL(coreboot_driver_unregister);
  80. int coreboot_table_init(struct device *dev, void __iomem *ptr)
  81. {
  82. int i, ret;
  83. void *ptr_entry;
  84. struct coreboot_device *device;
  85. struct coreboot_table_entry entry;
  86. struct coreboot_table_header header;
  87. ptr_header = ptr;
  88. memcpy_fromio(&header, ptr_header, sizeof(header));
  89. if (strncmp(header.signature, "LBIO", sizeof(header.signature))) {
  90. pr_warn("coreboot_table: coreboot table missing or corrupt!\n");
  91. return -ENODEV;
  92. }
  93. ptr_entry = (void *)ptr_header + header.header_bytes;
  94. for (i = 0; i < header.table_entries; i++) {
  95. memcpy_fromio(&entry, ptr_entry, sizeof(entry));
  96. device = kzalloc(sizeof(struct device) + entry.size, GFP_KERNEL);
  97. if (!device) {
  98. ret = -ENOMEM;
  99. break;
  100. }
  101. dev_set_name(&device->dev, "coreboot%d", i);
  102. device->dev.parent = dev;
  103. device->dev.bus = &coreboot_bus_type;
  104. device->dev.release = coreboot_device_release;
  105. memcpy_fromio(&device->entry, ptr_entry, entry.size);
  106. ret = device_register(&device->dev);
  107. if (ret) {
  108. put_device(&device->dev);
  109. break;
  110. }
  111. ptr_entry += entry.size;
  112. }
  113. return ret;
  114. }
  115. EXPORT_SYMBOL(coreboot_table_init);
  116. int coreboot_table_exit(void)
  117. {
  118. if (ptr_header) {
  119. bus_unregister(&coreboot_bus_type);
  120. iounmap(ptr_header);
  121. ptr_header = NULL;
  122. }
  123. return 0;
  124. }
  125. EXPORT_SYMBOL(coreboot_table_exit);
  126. MODULE_AUTHOR("Google, Inc.");
  127. MODULE_LICENSE("GPL");