You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

linux.c 4.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /*
  2. * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com>
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of the
  7. * License, or any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  17. */
  18. FILE_LICENCE(GPL2_OR_LATER);
  19. /** @file
  20. *
  21. * Linux root_device and root_driver.
  22. */
  23. #include <errno.h>
  24. #include <string.h>
  25. #include <stdio.h>
  26. #include <ipxe/linux.h>
  27. #include <ipxe/malloc.h>
  28. #include <ipxe/settings.h>
  29. LIST_HEAD(linux_device_requests);
  30. LIST_HEAD(linux_global_settings);
  31. /** Go over the device requests looking for a matching linux driver to handle them. */
  32. static int linux_probe(struct root_device *rootdev)
  33. {
  34. struct linux_device_request *request;
  35. struct linux_driver *driver;
  36. struct linux_device *device = NULL;
  37. int rc;
  38. /* Apply global settings */
  39. linux_apply_settings(&linux_global_settings, NULL);
  40. list_for_each_entry(request, &linux_device_requests, list) {
  41. if (! device)
  42. device = zalloc(sizeof(*device));
  43. if (! device)
  44. return -ENOMEM;
  45. rc = 1;
  46. for_each_table_entry(driver, LINUX_DRIVERS) {
  47. if ((rc = strcmp(driver->name, request->driver)) == 0)
  48. break;
  49. }
  50. if (rc != 0) {
  51. printf("Linux driver '%s' not found\n", request->driver);
  52. continue;
  53. }
  54. if (! driver->can_probe) {
  55. printf("Driver '%s' cannot handle any more devices\n", driver->name);
  56. continue;
  57. }
  58. /* We found a matching driver so add the device to the hierarchy */
  59. list_add(&device->dev.siblings, &rootdev->dev.children);
  60. device->dev.parent = &rootdev->dev;
  61. INIT_LIST_HEAD(&device->dev.children);
  62. if (driver->probe(device, request) == 0) {
  63. device->driver = driver;
  64. device->dev.driver_name = driver->name;
  65. /* Driver handled the device so release ownership */
  66. device = NULL;
  67. } else {
  68. /* Driver failed to handle the device so remove it from the hierarchy
  69. * and reuse the object */
  70. list_del(&device->dev.siblings);
  71. }
  72. };
  73. free(device);
  74. return 0;
  75. }
  76. /** Remove all the linux devices registered in probe() */
  77. static void linux_remove(struct root_device *rootdev)
  78. {
  79. struct linux_device *device;
  80. struct linux_device *tmp;
  81. list_for_each_entry_safe(device, tmp, &rootdev->dev.children, dev.siblings) {
  82. list_del(&device->dev.siblings);
  83. device->driver->remove(device);
  84. free(device);
  85. }
  86. }
  87. /** Linux root driver */
  88. static struct root_driver linux_root_driver = {
  89. .probe = linux_probe,
  90. .remove = linux_remove,
  91. };
  92. /** Linux root device */
  93. struct root_device linux_root_device __root_device = {
  94. .dev = { .name = "linux" },
  95. .driver = &linux_root_driver,
  96. };
  97. struct linux_setting *linux_find_setting(char *name, struct list_head *settings)
  98. {
  99. struct linux_setting *setting;
  100. struct linux_setting *result = NULL;
  101. /* Find the last occurrence of a setting with the specified name */
  102. list_for_each_entry(setting, settings, list) {
  103. if (strcmp(setting->name, name) == 0) {
  104. result = setting;
  105. }
  106. }
  107. return result;
  108. }
  109. void linux_apply_settings(struct list_head *new_settings, struct settings *settings_block)
  110. {
  111. struct linux_setting *setting;
  112. int rc;
  113. list_for_each_entry(setting, new_settings, list) {
  114. /* Skip already applied settings */
  115. if (setting->applied)
  116. continue;
  117. struct setting *s = find_setting(setting->name);
  118. if (s) {
  119. rc = storef_setting(settings_block, find_setting(setting->name), setting->value);
  120. if (rc != 0)
  121. DBG("linux storing setting '%s' = '%s' failed\n", setting->name, setting->value);
  122. setting->applied = 1;
  123. } else {
  124. DBG("linux unknown setting '%s'\n", setting->name);
  125. }
  126. }
  127. }