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 3.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  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. /* Driver handled the device so release ownership */
  65. device = NULL;
  66. } else {
  67. /* Driver failed to handle the device so remove it from the hierarchy
  68. * and reuse the object */
  69. list_del(&device->dev.siblings);
  70. }
  71. };
  72. free(device);
  73. return 0;
  74. }
  75. /** Remove all the linux devices registered in probe() */
  76. static void linux_remove(struct root_device *rootdev)
  77. {
  78. struct linux_device *device;
  79. struct linux_device *tmp;
  80. list_for_each_entry_safe(device, tmp, &rootdev->dev.children, dev.siblings) {
  81. list_del(&device->dev.siblings);
  82. device->driver->remove(device);
  83. free(device);
  84. }
  85. }
  86. /** Linux root driver */
  87. static struct root_driver linux_root_driver = {
  88. .probe = linux_probe,
  89. .remove = linux_remove,
  90. };
  91. /** Linux root device */
  92. struct root_device linux_root_device __root_device = {
  93. .dev = { .name = "linux" },
  94. .driver = &linux_root_driver,
  95. };
  96. struct linux_setting *linux_find_setting(char *name, struct list_head *settings)
  97. {
  98. struct linux_setting *setting;
  99. struct linux_setting *result = NULL;
  100. /* Find the last occurrence of a setting with the specified name */
  101. list_for_each_entry(setting, settings, list) {
  102. if (strcmp(setting->name, name) == 0) {
  103. result = setting;
  104. }
  105. }
  106. return result;
  107. }
  108. void linux_apply_settings(struct list_head *new_settings, struct settings *settings_block)
  109. {
  110. struct linux_setting *setting;
  111. int rc;
  112. list_for_each_entry(setting, new_settings, list) {
  113. /* Skip already applied settings */
  114. if (setting->applied)
  115. continue;
  116. struct setting *s = find_setting(setting->name);
  117. if (s) {
  118. rc = storef_setting(settings_block, find_setting(setting->name), setting->value);
  119. if (rc != 0)
  120. DBG("linux storing setting '%s' = '%s' failed\n", setting->name, setting->value);
  121. setting->applied = 1;
  122. } else {
  123. DBG("linux unknown setting '%s'\n", setting->name);
  124. }
  125. }
  126. }