| /* | |
| * 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 <getopt.h> | |
| #include <string.h> | |
| #include <stdio.h> | |
| #include <ipxe/settings.h> | |
| #include <ipxe/linux.h> | |
| #include <ipxe/malloc.h> | |
| #include <ipxe/init.h> | |
| int linux_argc; | |
| char **linux_argv; | |
| /** Supported command-line options */ | |
| static struct option options[] = { | |
| {"net", 1, NULL, 'n'}, | |
| {"settings", 1, NULL, 's'}, | |
| {NULL, 0, NULL, 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(linux_argc, linux_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) = { | |
| .name = "linux_args", | |
| .startup = linux_args_parse, | |
| .shutdown = linux_args_cleanup, | |
| }; |