[gPXE-devel] [PATCH 16/33] [linux] Add command line arguments

Piotr Jaroszyński p.jaroszynski at gmail.com
Sun Aug 15 18:59:21 EDT 2010


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 at gmail.com>
---
 src/arch/i386/prefix/linuxprefix.S   |    3 +
 src/arch/x86_64/prefix/linuxprefix.S |    3 +
 src/hci/linux_args.c                 |  190 ++++++++++++++++++++++++++++++++++
 src/include/hci/linux_args.h         |   31 ++++++
 4 files changed, 227 insertions(+), 0 deletions(-)
 create mode 100644 src/hci/linux_args.c
 create mode 100644 src/include/hci/linux_args.h

diff --git a/src/arch/i386/prefix/linuxprefix.S b/src/arch/i386/prefix/linuxprefix.S
index 881c61d..b32b08f 100644
--- a/src/arch/i386/prefix/linuxprefix.S
+++ b/src/arch/i386/prefix/linuxprefix.S
@@ -16,6 +16,9 @@ _start:
 	pushl	%edi // argv -> C arg2
 	pushl	%esi // argc -> C arg1
 
+	call	save_args
+
+	/* Our main doesn't use any arguments */
 	call	main
 
 	movl	%eax, %ebx // rc -> syscall arg1
diff --git a/src/arch/x86_64/prefix/linuxprefix.S b/src/arch/x86_64/prefix/linuxprefix.S
index 20163b8..4aa0b84 100644
--- a/src/arch/x86_64/prefix/linuxprefix.S
+++ b/src/arch/x86_64/prefix/linuxprefix.S
@@ -13,6 +13,9 @@ _start:
 
 	andq	$~15, %rsp // 16-byte align the stack
 
+	call	save_args
+
+	/* Our main doesn't use any arguments */
 	call	main
 
 	movq	%rax, %rdi // rc -> syscall arg1
diff --git a/src/hci/linux_args.c b/src/hci/linux_args.c
new file mode 100644
index 0000000..1a17aee
--- /dev/null
+++ b/src/hci/linux_args.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski at 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 <gpxe/settings.h>
+#include <gpxe/linux.h>
+#include <gpxe/malloc.h>
+#include <gpxe/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,
+};
diff --git a/src/include/hci/linux_args.h b/src/include/hci/linux_args.h
new file mode 100644
index 0000000..71c9f81
--- /dev/null
+++ b/src/include/hci/linux_args.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski at 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.
+ */
+
+#ifndef _HCI_LINUX_ARGS_H
+#define _HCI_LINUX_ARGS_H
+
+FILE_LICENCE(GPL2_OR_LATER);
+
+/**
+ * Save argc and argv for later access.
+ *
+ * To be called by linuxprefix
+ */
+__asmcall void save_args(int argc, char **argv);
+
+#endif /* _HCI_LINUX_ARGS_H */
-- 
1.7.1



More information about the gPXE-devel mailing list