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