summaryrefslogtreecommitdiffstats
path: root/src/hci/linux_args.c
diff options
context:
space:
mode:
authorPiotr Jaroszyński2010-05-31 19:07:13 +0200
committerMichael Brown2010-08-19 13:45:41 +0200
commitddef2e1bc1da7a70ffbc03f68a16918b54f7622b (patch)
tree0aeb1e17ab1f4ed36595732ff8e9060f64b2505d /src/hci/linux_args.c
parent[linux] Add device and driver model (diff)
downloadipxe-ddef2e1bc1da7a70ffbc03f68a16918b54f7622b.tar.gz
ipxe-ddef2e1bc1da7a70ffbc03f68a16918b54f7622b.tar.xz
ipxe-ddef2e1bc1da7a70ffbc03f68a16918b54f7622b.zip
[linux] Add command line arguments
Support qemu-like arguments for network setup: --net driver_name[,setting=value]* and global settings: --settings setting=value[,setting=value]* Signed-off-by: Piotr Jaroszyński <p.jaroszynski@gmail.com> Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/hci/linux_args.c')
-rw-r--r--src/hci/linux_args.c190
1 files changed, 190 insertions, 0 deletions
diff --git a/src/hci/linux_args.c b/src/hci/linux_args.c
new file mode 100644
index 00000000..0bce4af9
--- /dev/null
+++ b/src/hci/linux_args.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+FILE_LICENCE(GPL2_OR_LATER);
+
+#include <hci/linux_args.h>
+#include <getopt.h>
+#include <string.h>
+#include <stdio.h>
+#include <ipxe/settings.h>
+#include <ipxe/linux.h>
+#include <ipxe/malloc.h>
+#include <ipxe/init.h>
+
+/** Saved argc */
+static int saved_argc = 0;
+/** Saved argv */
+static char ** saved_argv;
+
+/**
+ * Save argc and argv for later access.
+ *
+ * To be called by linuxprefix
+ */
+__asmcall void save_args(int argc, char **argv)
+{
+ saved_argc = argc;
+ saved_argv = argv;
+}
+
+/** Supported command-line options */
+static struct option options[] = {
+ {"net", 1, 0, 'n'},
+ {"settings", 1, 0, 's'},
+ {0, 0, 0, 0}
+};
+
+/**
+ * Parse k1=v1[,k2=v2]* into linux_settings
+ */
+static int parse_kv(char *kv, struct list_head *list)
+{
+ char *token;
+ char *name;
+ char *value;
+ struct linux_setting *setting;
+
+ while ((token = strsep(&kv, ",")) != NULL) {
+ name = strsep(&token, "=");
+ if (name == NULL)
+ continue;
+ value = token;
+ if (value == NULL) {
+ DBG("Bad parameter: '%s'\n", name);
+ continue;
+ }
+
+ setting = malloc(sizeof(*setting));
+
+ if (! setting)
+ return -1;
+
+ setting->name = name;
+ setting->value = value;
+ setting->applied = 0;
+ list_add(&setting->list, list);
+ }
+
+ return 0;
+}
+
+/**
+ * Parse --net arguments
+ *
+ * Format is --net driver_name[,name=value]*
+ */
+static int parse_net_args(char *args)
+{
+ char *driver;
+ struct linux_device_request *dev_request;
+ int rc;
+
+ driver = strsep(&args, ",");
+
+ if (strlen(driver) == 0) {
+ printf("Missing driver name");
+ return -1;
+ }
+
+ dev_request = malloc(sizeof(*dev_request));
+
+ dev_request->driver = driver;
+ INIT_LIST_HEAD(&dev_request->settings);
+ list_add_tail(&dev_request->list, &linux_device_requests);
+
+ /* Parse rest of the settings */
+ rc = parse_kv(args, &dev_request->settings);
+
+ if (rc)
+ printf("Parsing net settings failed");
+
+ return rc;
+}
+
+/**
+ * Parse --settings arguments
+ *
+ * Format is --settings name=value[,name=value]*
+ */
+static int parse_settings_args(char *args)
+{
+ return parse_kv(args, &linux_global_settings);
+}
+
+
+/** Parse passed command-line arguments */
+void linux_args_parse()
+{
+ int c;
+ int rc;
+
+ reset_getopt();
+ while (1) {
+ int option_index = 0;
+
+ c = getopt_long(saved_argc, saved_argv, "", options, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'n':
+ if ((rc = parse_net_args(optarg)) != 0)
+ return;
+ break;
+ case 's':
+ if ((rc = parse_settings_args(optarg)) != 0)
+ return;
+ break;
+ default:
+ return;
+ }
+ }
+
+ return;
+}
+
+/** Clean up requests and settings */
+void linux_args_cleanup(int flags __unused)
+{
+ struct linux_device_request *request;
+ struct linux_device_request *rtmp;
+ struct linux_setting *setting;
+ struct linux_setting *stmp;
+
+ /* Clean up requests and their settings */
+ list_for_each_entry_safe(request, rtmp, &linux_device_requests, list) {
+ list_for_each_entry_safe(setting, stmp, &request->settings, list) {
+ list_del(&setting->list);
+ free(setting);
+ }
+ list_del(&request->list);
+ free(request);
+ }
+
+ /* Clean up global settings */
+ list_for_each_entry_safe(setting, stmp, &linux_global_settings, list) {
+ list_del(&setting->list);
+ free(setting);
+ }
+}
+
+struct startup_fn startup_linux_args __startup_fn(STARTUP_EARLY) = {
+ .startup = linux_args_parse,
+ .shutdown = linux_args_cleanup,
+};