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_args.c 4.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  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. #include <hci/linux_args.h>
  20. #include <getopt.h>
  21. #include <string.h>
  22. #include <stdio.h>
  23. #include <ipxe/settings.h>
  24. #include <ipxe/linux.h>
  25. #include <ipxe/malloc.h>
  26. #include <ipxe/init.h>
  27. /** Saved argc */
  28. static int saved_argc = 0;
  29. /** Saved argv */
  30. static char ** saved_argv;
  31. /**
  32. * Save argc and argv for later access.
  33. *
  34. * To be called by linuxprefix
  35. */
  36. __asmcall void save_args(int argc, char **argv)
  37. {
  38. saved_argc = argc;
  39. saved_argv = argv;
  40. }
  41. /** Supported command-line options */
  42. static struct option options[] = {
  43. {"net", 1, NULL, 'n'},
  44. {"settings", 1, NULL, 's'},
  45. {NULL, 0, NULL, 0}
  46. };
  47. /**
  48. * Parse k1=v1[,k2=v2]* into linux_settings
  49. */
  50. static int parse_kv(char *kv, struct list_head *list)
  51. {
  52. char *token;
  53. char *name;
  54. char *value;
  55. struct linux_setting *setting;
  56. while ((token = strsep(&kv, ",")) != NULL) {
  57. name = strsep(&token, "=");
  58. if (name == NULL)
  59. continue;
  60. value = token;
  61. if (value == NULL) {
  62. DBG("Bad parameter: '%s'\n", name);
  63. continue;
  64. }
  65. setting = malloc(sizeof(*setting));
  66. if (! setting)
  67. return -1;
  68. setting->name = name;
  69. setting->value = value;
  70. setting->applied = 0;
  71. list_add(&setting->list, list);
  72. }
  73. return 0;
  74. }
  75. /**
  76. * Parse --net arguments
  77. *
  78. * Format is --net driver_name[,name=value]*
  79. */
  80. static int parse_net_args(char *args)
  81. {
  82. char *driver;
  83. struct linux_device_request *dev_request;
  84. int rc;
  85. driver = strsep(&args, ",");
  86. if (strlen(driver) == 0) {
  87. printf("Missing driver name");
  88. return -1;
  89. }
  90. dev_request = malloc(sizeof(*dev_request));
  91. dev_request->driver = driver;
  92. INIT_LIST_HEAD(&dev_request->settings);
  93. list_add_tail(&dev_request->list, &linux_device_requests);
  94. /* Parse rest of the settings */
  95. rc = parse_kv(args, &dev_request->settings);
  96. if (rc)
  97. printf("Parsing net settings failed");
  98. return rc;
  99. }
  100. /**
  101. * Parse --settings arguments
  102. *
  103. * Format is --settings name=value[,name=value]*
  104. */
  105. static int parse_settings_args(char *args)
  106. {
  107. return parse_kv(args, &linux_global_settings);
  108. }
  109. /** Parse passed command-line arguments */
  110. void linux_args_parse()
  111. {
  112. int c;
  113. int rc;
  114. reset_getopt();
  115. while (1) {
  116. int option_index = 0;
  117. c = getopt_long(saved_argc, saved_argv, "", options, &option_index);
  118. if (c == -1)
  119. break;
  120. switch (c) {
  121. case 'n':
  122. if ((rc = parse_net_args(optarg)) != 0)
  123. return;
  124. break;
  125. case 's':
  126. if ((rc = parse_settings_args(optarg)) != 0)
  127. return;
  128. break;
  129. default:
  130. return;
  131. }
  132. }
  133. return;
  134. }
  135. /** Clean up requests and settings */
  136. void linux_args_cleanup(int flags __unused)
  137. {
  138. struct linux_device_request *request;
  139. struct linux_device_request *rtmp;
  140. struct linux_setting *setting;
  141. struct linux_setting *stmp;
  142. /* Clean up requests and their settings */
  143. list_for_each_entry_safe(request, rtmp, &linux_device_requests, list) {
  144. list_for_each_entry_safe(setting, stmp, &request->settings, list) {
  145. list_del(&setting->list);
  146. free(setting);
  147. }
  148. list_del(&request->list);
  149. free(request);
  150. }
  151. /* Clean up global settings */
  152. list_for_each_entry_safe(setting, stmp, &linux_global_settings, list) {
  153. list_del(&setting->list);
  154. free(setting);
  155. }
  156. }
  157. struct startup_fn startup_linux_args __startup_fn(STARTUP_EARLY) = {
  158. .name = "linux_args",
  159. .startup = linux_args_parse,
  160. .shutdown = linux_args_cleanup,
  161. };