Blame dmiopt.c

Packit a55458
/*
Packit a55458
 * Command line handling of dmidecode
Packit a55458
 * This file is part of the dmidecode project.
Packit a55458
 *
Packit a55458
 *   Copyright (C) 2005-2008 Jean Delvare <jdelvare@suse.de>
Packit a55458
 *
Packit a55458
 *   This program is free software; you can redistribute it and/or modify
Packit a55458
 *   it under the terms of the GNU General Public License as published by
Packit a55458
 *   the Free Software Foundation; either version 2 of the License, or
Packit a55458
 *   (at your option) any later version.
Packit a55458
 *
Packit a55458
 *   This program is distributed in the hope that it will be useful,
Packit a55458
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit a55458
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit a55458
 *   GNU General Public License for more details.
Packit a55458
 *
Packit a55458
 *   You should have received a copy of the GNU General Public License
Packit a55458
 *   along with this program; if not, write to the Free Software
Packit a55458
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
Packit a55458
 */
Packit a55458
Packit a55458
#include <stdio.h>
Packit a55458
#include <string.h>
Packit a55458
#include <strings.h>
Packit a55458
#include <stdlib.h>
Packit a55458
#include <getopt.h>
Packit a55458
Packit a55458
#include "config.h"
Packit a55458
#include "types.h"
Packit a55458
#include "util.h"
Packit a55458
#include "dmidecode.h"
Packit a55458
#include "dmiopt.h"
Packit a55458
Packit a55458
Packit a55458
/* Options are global */
Packit a55458
struct opt opt;
Packit a55458
Packit a55458
Packit a55458
/*
Packit a55458
 * Handling of option --type
Packit a55458
 */
Packit a55458
Packit a55458
struct type_keyword
Packit a55458
{
Packit a55458
	const char *keyword;
Packit a55458
	const u8 *type;
Packit a55458
};
Packit a55458
Packit a55458
static const u8 opt_type_bios[] = { 0, 13, 255 };
Packit a55458
static const u8 opt_type_system[] = { 1, 12, 15, 23, 32, 255 };
Packit a55458
static const u8 opt_type_baseboard[] = { 2, 10, 41, 255 };
Packit a55458
static const u8 opt_type_chassis[] = { 3, 255 };
Packit a55458
static const u8 opt_type_processor[] = { 4, 255 };
Packit a55458
static const u8 opt_type_memory[] = { 5, 6, 16, 17, 255 };
Packit a55458
static const u8 opt_type_cache[] = { 7, 255 };
Packit a55458
static const u8 opt_type_connector[] = { 8, 255 };
Packit a55458
static const u8 opt_type_slot[] = { 9, 255 };
Packit a55458
Packit a55458
static const struct type_keyword opt_type_keyword[] = {
Packit a55458
	{ "bios", opt_type_bios },
Packit a55458
	{ "system", opt_type_system },
Packit a55458
	{ "baseboard", opt_type_baseboard },
Packit a55458
	{ "chassis", opt_type_chassis },
Packit a55458
	{ "processor", opt_type_processor },
Packit a55458
	{ "memory", opt_type_memory },
Packit a55458
	{ "cache", opt_type_cache },
Packit a55458
	{ "connector", opt_type_connector },
Packit a55458
	{ "slot", opt_type_slot },
Packit a55458
};
Packit a55458
Packit a55458
static void print_opt_type_list(void)
Packit a55458
{
Packit a55458
	unsigned int i;
Packit a55458
Packit a55458
	fprintf(stderr, "Valid type keywords are:\n");
Packit a55458
	for (i = 0; i < ARRAY_SIZE(opt_type_keyword); i++)
Packit a55458
	{
Packit a55458
		fprintf(stderr, "  %s\n", opt_type_keyword[i].keyword);
Packit a55458
	}
Packit a55458
}
Packit a55458
Packit a55458
static u8 *parse_opt_type(u8 *p, const char *arg)
Packit a55458
{
Packit a55458
	unsigned int i;
Packit a55458
Packit a55458
	/* Allocate memory on first call only */
Packit a55458
	if (p == NULL)
Packit a55458
	{
Packit a55458
		p = (u8 *)calloc(256, sizeof(u8));
Packit a55458
		if (p == NULL)
Packit a55458
		{
Packit a55458
			perror("calloc");
Packit a55458
			return NULL;
Packit a55458
		}
Packit a55458
	}
Packit a55458
Packit a55458
	/* First try as a keyword */
Packit a55458
	for (i = 0; i < ARRAY_SIZE(opt_type_keyword); i++)
Packit a55458
	{
Packit a55458
		if (!strcasecmp(arg, opt_type_keyword[i].keyword))
Packit a55458
		{
Packit a55458
			int j = 0;
Packit a55458
			while (opt_type_keyword[i].type[j] != 255)
Packit a55458
				p[opt_type_keyword[i].type[j++]] = 1;
Packit a55458
			goto found;
Packit a55458
		}
Packit a55458
	}
Packit a55458
Packit a55458
	/* Else try as a number */
Packit a55458
	while (*arg != '\0')
Packit a55458
	{
Packit a55458
		unsigned long val;
Packit a55458
		char *next;
Packit a55458
Packit a55458
		val = strtoul(arg, &next, 0);
Packit a55458
		if (next == arg || (*next != '\0' && *next != ',' && *next != ' '))
Packit a55458
		{
Packit a55458
			fprintf(stderr, "Invalid type keyword: %s\n", arg);
Packit a55458
			print_opt_type_list();
Packit a55458
			goto exit_free;
Packit a55458
		}
Packit a55458
		if (val > 0xff)
Packit a55458
		{
Packit a55458
			fprintf(stderr, "Invalid type number: %lu\n", val);
Packit a55458
			goto exit_free;
Packit a55458
		}
Packit a55458
Packit a55458
		p[val] = 1;
Packit a55458
		arg = next;
Packit a55458
		while (*arg == ',' || *arg == ' ')
Packit a55458
			arg++;
Packit a55458
	}
Packit a55458
Packit a55458
found:
Packit a55458
	return p;
Packit a55458
Packit a55458
exit_free:
Packit a55458
	free(p);
Packit a55458
	return NULL;
Packit a55458
}
Packit a55458
Packit a55458
Packit a55458
/*
Packit a55458
 * Handling of option --string
Packit a55458
 */
Packit a55458
Packit a55458
/* This lookup table could admittedly be reworked for improved performance.
Packit a55458
   Due to the low count of items in there at the moment, it did not seem
Packit a55458
   worth the additional code complexity though. */
Packit a55458
static const struct string_keyword opt_string_keyword[] = {
Packit a55458
	{ "bios-vendor", 0, 0x04 },
Packit a55458
	{ "bios-version", 0, 0x05 },
Packit a55458
	{ "bios-release-date", 0, 0x08 },
Packit Service 9df206
	{ "bios-revision", 0, 0x15 },		/* 0x14 and 0x15 */
Packit Service afe2ab
	{ "firmware-revision", 0, 0x17 },	/* 0x16 and 0x17 */
Packit a55458
	{ "system-manufacturer", 1, 0x04 },
Packit a55458
	{ "system-product-name", 1, 0x05 },
Packit a55458
	{ "system-version", 1, 0x06 },
Packit a55458
	{ "system-serial-number", 1, 0x07 },
Packit a55458
	{ "system-uuid", 1, 0x08 },             /* dmi_system_uuid() */
Packit a55458
	{ "system-family", 1, 0x1a },
Packit a55458
	{ "baseboard-manufacturer", 2, 0x04 },
Packit a55458
	{ "baseboard-product-name", 2, 0x05 },
Packit a55458
	{ "baseboard-version", 2, 0x06 },
Packit a55458
	{ "baseboard-serial-number", 2, 0x07 },
Packit a55458
	{ "baseboard-asset-tag", 2, 0x08 },
Packit a55458
	{ "chassis-manufacturer", 3, 0x04 },
Packit a55458
	{ "chassis-type", 3, 0x05 },            /* dmi_chassis_type() */
Packit a55458
	{ "chassis-version", 3, 0x06 },
Packit a55458
	{ "chassis-serial-number", 3, 0x07 },
Packit a55458
	{ "chassis-asset-tag", 3, 0x08 },
Packit a55458
	{ "processor-family", 4, 0x06 },        /* dmi_processor_family() */
Packit a55458
	{ "processor-manufacturer", 4, 0x07 },
Packit a55458
	{ "processor-version", 4, 0x10 },
Packit a55458
	{ "processor-frequency", 4, 0x16 },     /* dmi_processor_frequency() */
Packit a55458
};
Packit a55458
Packit a55458
/* This is a template, 3rd field is set at runtime. */
Packit a55458
static struct string_keyword opt_oem_string_keyword =
Packit a55458
	{ NULL, 11, 0x00 };
Packit a55458
Packit a55458
static void print_opt_string_list(void)
Packit a55458
{
Packit a55458
	unsigned int i;
Packit a55458
Packit a55458
	fprintf(stderr, "Valid string keywords are:\n");
Packit a55458
	for (i = 0; i < ARRAY_SIZE(opt_string_keyword); i++)
Packit a55458
	{
Packit a55458
		fprintf(stderr, "  %s\n", opt_string_keyword[i].keyword);
Packit a55458
	}
Packit a55458
}
Packit a55458
Packit a55458
static int parse_opt_string(const char *arg)
Packit a55458
{
Packit a55458
	unsigned int i;
Packit a55458
Packit a55458
	if (opt.string)
Packit a55458
	{
Packit a55458
		fprintf(stderr, "Only one string can be specified\n");
Packit a55458
		return -1;
Packit a55458
	}
Packit a55458
Packit a55458
	for (i = 0; i < ARRAY_SIZE(opt_string_keyword); i++)
Packit a55458
	{
Packit a55458
		if (!strcasecmp(arg, opt_string_keyword[i].keyword))
Packit a55458
		{
Packit a55458
			opt.string = &opt_string_keyword[i];
Packit a55458
			return 0;
Packit a55458
		}
Packit a55458
	}
Packit a55458
Packit a55458
	fprintf(stderr, "Invalid string keyword: %s\n", arg);
Packit a55458
	print_opt_string_list();
Packit a55458
	return -1;
Packit a55458
}
Packit a55458
Packit a55458
static int parse_opt_oem_string(const char *arg)
Packit a55458
{
Packit a55458
	unsigned long val;
Packit a55458
	char *next;
Packit a55458
Packit a55458
	if (opt.string)
Packit a55458
	{
Packit a55458
		fprintf(stderr, "Only one string can be specified\n");
Packit a55458
		return -1;
Packit a55458
	}
Packit a55458
Packit a55458
	/* Return the number of OEM strings */
Packit a55458
	if (strcmp(arg, "count") == 0)
Packit a55458
		goto done;
Packit a55458
Packit a55458
	val = strtoul(arg, &next, 10);
Packit a55458
	if (next == arg  || *next != '\0' || val == 0x00 || val > 0xff)
Packit a55458
	{
Packit a55458
		fprintf(stderr, "Invalid OEM string number: %s\n", arg);
Packit a55458
		return -1;
Packit a55458
	}
Packit a55458
Packit a55458
	opt_oem_string_keyword.offset = val;
Packit a55458
done:
Packit a55458
	opt.string = &opt_oem_string_keyword;
Packit a55458
	return 0;
Packit a55458
}
Packit a55458
Packit a55458
static u32 parse_opt_handle(const char *arg)
Packit a55458
{
Packit a55458
	u32 val;
Packit a55458
	char *next;
Packit a55458
Packit a55458
	val = strtoul(arg, &next, 0);
Packit a55458
	if (next == arg || *next != '\0' || val > 0xffff)
Packit a55458
	{
Packit a55458
		fprintf(stderr, "Invalid handle number: %s\n", arg);
Packit a55458
		return ~0;
Packit a55458
	}
Packit a55458
	return val;
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * Command line options handling
Packit a55458
 */
Packit a55458
Packit a55458
/* Return -1 on error, 0 on success */
Packit a55458
int parse_command_line(int argc, char * const argv[])
Packit a55458
{
Packit a55458
	int option;
Packit a55458
	const char *optstring = "d:hqs:t:uH:V";
Packit a55458
	struct option longopts[] = {
Packit a55458
		{ "dev-mem", required_argument, NULL, 'd' },
Packit a55458
		{ "help", no_argument, NULL, 'h' },
Packit a55458
		{ "quiet", no_argument, NULL, 'q' },
Packit a55458
		{ "string", required_argument, NULL, 's' },
Packit a55458
		{ "type", required_argument, NULL, 't' },
Packit a55458
		{ "dump", no_argument, NULL, 'u' },
Packit a55458
		{ "dump-bin", required_argument, NULL, 'B' },
Packit a55458
		{ "from-dump", required_argument, NULL, 'F' },
Packit a55458
		{ "handle", required_argument, NULL, 'H' },
Packit a55458
		{ "oem-string", required_argument, NULL, 'O' },
Packit a55458
		{ "no-sysfs", no_argument, NULL, 'S' },
Packit a55458
		{ "version", no_argument, NULL, 'V' },
Packit a55458
		{ NULL, 0, NULL, 0 }
Packit a55458
	};
Packit a55458
Packit a55458
	while ((option = getopt_long(argc, argv, optstring, longopts, NULL)) != -1)
Packit a55458
		switch (option)
Packit a55458
		{
Packit a55458
			case 'B':
Packit a55458
				opt.flags |= FLAG_DUMP_BIN;
Packit a55458
				opt.dumpfile = optarg;
Packit a55458
				break;
Packit a55458
			case 'F':
Packit a55458
				opt.flags |= FLAG_FROM_DUMP;
Packit a55458
				opt.dumpfile = optarg;
Packit a55458
				break;
Packit a55458
			case 'd':
Packit a55458
				opt.devmem = optarg;
Packit a55458
				break;
Packit a55458
			case 'h':
Packit a55458
				opt.flags |= FLAG_HELP;
Packit a55458
				break;
Packit a55458
			case 'q':
Packit a55458
				opt.flags |= FLAG_QUIET;
Packit a55458
				break;
Packit a55458
			case 's':
Packit a55458
				if (parse_opt_string(optarg) < 0)
Packit a55458
					return -1;
Packit a55458
				opt.flags |= FLAG_QUIET;
Packit a55458
				break;
Packit a55458
			case 'O':
Packit a55458
				if (parse_opt_oem_string(optarg) < 0)
Packit a55458
					return -1;
Packit a55458
				opt.flags |= FLAG_QUIET;
Packit a55458
				break;
Packit a55458
			case 't':
Packit a55458
				opt.type = parse_opt_type(opt.type, optarg);
Packit a55458
				if (opt.type == NULL)
Packit a55458
					return -1;
Packit a55458
				break;
Packit a55458
			case 'H':
Packit a55458
				opt.handle = parse_opt_handle(optarg);
Packit a55458
				if (opt.handle  == ~0U)
Packit a55458
					return -1;
Packit a55458
				break;
Packit a55458
			case 'u':
Packit a55458
				opt.flags |= FLAG_DUMP;
Packit a55458
				break;
Packit a55458
			case 'S':
Packit a55458
				opt.flags |= FLAG_NO_SYSFS;
Packit a55458
				break;
Packit a55458
			case 'V':
Packit a55458
				opt.flags |= FLAG_VERSION;
Packit a55458
				break;
Packit a55458
			case '?':
Packit a55458
				switch (optopt)
Packit a55458
				{
Packit a55458
					case 's':
Packit a55458
						fprintf(stderr, "String keyword expected\n");
Packit a55458
						print_opt_string_list();
Packit a55458
						break;
Packit a55458
					case 't':
Packit a55458
						fprintf(stderr, "Type number or keyword expected\n");
Packit a55458
						print_opt_type_list();
Packit a55458
						break;
Packit a55458
				}
Packit a55458
				return -1;
Packit a55458
		}
Packit a55458
Packit a55458
	/* Check for mutually exclusive output format options */
Packit a55458
	if ((opt.string != NULL) + (opt.type != NULL)
Packit a55458
	  + !!(opt.flags & FLAG_DUMP_BIN) + (opt.handle != ~0U) > 1)
Packit a55458
	{
Packit a55458
		fprintf(stderr, "Options --string, --type, --handle and --dump-bin are mutually exclusive\n");
Packit a55458
		return -1;
Packit a55458
	}
Packit a55458
Packit a55458
	if ((opt.flags & FLAG_FROM_DUMP) && (opt.flags & FLAG_DUMP_BIN))
Packit a55458
	{
Packit a55458
		fprintf(stderr, "Options --from-dump and --dump-bin are mutually exclusive\n");
Packit a55458
		return -1;
Packit a55458
	}
Packit a55458
Packit a55458
	return 0;
Packit a55458
}
Packit a55458
Packit a55458
void print_help(void)
Packit a55458
{
Packit a55458
	static const char *help =
Packit a55458
		"Usage: dmidecode [OPTIONS]\n"
Packit a55458
		"Options are:\n"
Packit a55458
		" -d, --dev-mem FILE     Read memory from device FILE (default: " DEFAULT_MEM_DEV ")\n"
Packit a55458
		" -h, --help             Display this help text and exit\n"
Packit a55458
		" -q, --quiet            Less verbose output\n"
Packit a55458
		" -s, --string KEYWORD   Only display the value of the given DMI string\n"
Packit a55458
		" -t, --type TYPE        Only display the entries of given type\n"
Packit a55458
		" -H, --handle HANDLE    Only display the entry of given handle\n"
Packit a55458
		" -u, --dump             Do not decode the entries\n"
Packit a55458
		"     --dump-bin FILE    Dump the DMI data to a binary file\n"
Packit a55458
		"     --from-dump FILE   Read the DMI data from a binary file\n"
Packit a55458
		"     --no-sysfs         Do not attempt to read DMI data from sysfs files\n"
Packit a55458
		"     --oem-string N     Only display the value of the given OEM string\n"
Packit a55458
		" -V, --version          Display the version and exit\n";
Packit a55458
Packit a55458
	printf("%s", help);
Packit a55458
}