Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / 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         .startup = linux_args_parse,
189         .shutdown = linux_args_cleanup,
190 };