Blame dmiopt.c

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