Blame dmidecode.c

Packit a55458
/*
Packit a55458
 * DMI Decode
Packit a55458
 *
Packit a55458
 *   Copyright (C) 2000-2002 Alan Cox <alan@redhat.com>
Packit a55458
 *   Copyright (C) 2002-2018 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
 *   For the avoidance of doubt the "preferred form" of this code is one which
Packit a55458
 *   is in an open unpatent encumbered format. Where cryptographic key signing
Packit a55458
 *   forms part of the process of creating an executable the information
Packit a55458
 *   including keys needed to generate an equivalently functional executable
Packit a55458
 *   are deemed to be part of the source code.
Packit a55458
 *
Packit a55458
 * Unless specified otherwise, all references are aimed at the "System
Packit a55458
 * Management BIOS Reference Specification, Version 3.2.0" document,
Packit a55458
 * available from http://www.dmtf.org/standards/smbios.
Packit a55458
 *
Packit a55458
 * Note to contributors:
Packit a55458
 * Please reference every value you add or modify, especially if the
Packit a55458
 * information does not come from the above mentioned specification.
Packit a55458
 *
Packit a55458
 * Additional references:
Packit a55458
 *  - Intel AP-485 revision 36
Packit a55458
 *    "Intel Processor Identification and the CPUID Instruction"
Packit a55458
 *    http://www.intel.com/support/processors/sb/cs-009861.htm
Packit a55458
 *  - DMTF Common Information Model
Packit a55458
 *    CIM Schema version 2.19.1
Packit a55458
 *    http://www.dmtf.org/standards/cim/
Packit a55458
 *  - IPMI 2.0 revision 1.0
Packit a55458
 *    "Intelligent Platform Management Interface Specification"
Packit a55458
 *    http://developer.intel.com/design/servers/ipmi/spec.htm
Packit a55458
 *  - AMD publication #25481 revision 2.28
Packit a55458
 *    "CPUID Specification"
Packit a55458
 *    http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/25481.pdf
Packit a55458
 *  - BIOS Integrity Services Application Programming Interface version 1.0
Packit a55458
 *    http://www.intel.com/design/archives/wfm/downloads/bisspec.htm
Packit a55458
 *  - DMTF DSP0239 version 1.1.0
Packit a55458
 *    "Management Component Transport Protocol (MCTP) IDs and Codes"
Packit a55458
 *    http://www.dmtf.org/standards/pmci
Packit a55458
 *  - "TPM Main, Part 2 TPM Structures"
Packit a55458
 *    Specification version 1.2, level 2, revision 116
Packit a55458
 *    https://trustedcomputinggroup.org/tpm-main-specification/
Packit a55458
 *  - "PC Client Platform TPM Profile (PTP) Specification"
Packit a55458
 *    Family "2.0", Level 00, Revision 00.43, January 26, 2015
Packit a55458
 *    https://trustedcomputinggroup.org/pc-client-platform-tpm-profile-ptp-specification/
Packit a55458
 *  - "RedFish Host Interface Specification" (DMTF DSP0270)
Packit a55458
 *    https://www.dmtf.org/sites/default/files/DSP0270_1.0.1.pdf
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 <unistd.h>
Packit a55458
#include <arpa/inet.h>
Packit a55458
Packit a55458
#ifdef __FreeBSD__
Packit a55458
#include <errno.h>
Packit a55458
#include <kenv.h>
Packit a55458
#endif
Packit a55458
Packit a55458
#include "version.h"
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
#include "dmioem.h"
Packit a55458
Packit a55458
#define out_of_spec "<OUT OF SPEC>"
Packit a55458
static const char *bad_index = "<BAD INDEX>";
Packit a55458
Packit a55458
#define SUPPORTED_SMBIOS_VER 0x030200
Packit a55458
Packit a55458
#define FLAG_NO_FILE_OFFSET     (1 << 0)
Packit a55458
#define FLAG_STOP_AT_EOT        (1 << 1)
Packit a55458
Packit a55458
#define SYS_FIRMWARE_DIR "/sys/firmware/dmi/tables"
Packit a55458
#define SYS_ENTRY_FILE SYS_FIRMWARE_DIR "/smbios_entry_point"
Packit a55458
#define SYS_TABLE_FILE SYS_FIRMWARE_DIR "/DMI"
Packit a55458
Packit a55458
/*
Packit a55458
 * Type-independant Stuff
Packit a55458
 */
Packit a55458
Packit a55458
/* Returns 1 if the buffer contains only printable ASCII characters */
Packit a55458
int is_printable(const u8 *data, int len)
Packit a55458
{
Packit a55458
	int i;
Packit a55458
Packit a55458
	for (i = 0; i < len; i++)
Packit a55458
		if (data[i] < 32 || data[i] >= 127)
Packit a55458
			return 0;
Packit a55458
Packit a55458
	return 1;
Packit a55458
}
Packit a55458
Packit a55458
const char *dmi_string(const struct dmi_header *dm, u8 s)
Packit a55458
{
Packit a55458
	char *bp = (char *)dm->data;
Packit a55458
	size_t i, len;
Packit a55458
Packit a55458
	if (s == 0)
Packit a55458
		return "Not Specified";
Packit a55458
Packit a55458
	bp += dm->length;
Packit a55458
	while (s > 1 && *bp)
Packit a55458
	{
Packit a55458
		bp += strlen(bp);
Packit a55458
		bp++;
Packit a55458
		s--;
Packit a55458
	}
Packit a55458
Packit a55458
	if (!*bp)
Packit a55458
		return bad_index;
Packit a55458
Packit a55458
	if (!(opt.flags & FLAG_DUMP))
Packit a55458
	{
Packit a55458
		/* ASCII filtering */
Packit a55458
		len = strlen(bp);
Packit a55458
		for (i = 0; i < len; i++)
Packit a55458
			if (bp[i] < 32 || bp[i] == 127)
Packit a55458
				bp[i] = '.';
Packit a55458
	}
Packit a55458
Packit a55458
	return bp;
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_smbios_structure_type(u8 code)
Packit a55458
{
Packit a55458
	static const char *type[] = {
Packit a55458
		"BIOS", /* 0 */
Packit a55458
		"System",
Packit a55458
		"Base Board",
Packit a55458
		"Chassis",
Packit a55458
		"Processor",
Packit a55458
		"Memory Controller",
Packit a55458
		"Memory Module",
Packit a55458
		"Cache",
Packit a55458
		"Port Connector",
Packit a55458
		"System Slots",
Packit a55458
		"On Board Devices",
Packit a55458
		"OEM Strings",
Packit a55458
		"System Configuration Options",
Packit a55458
		"BIOS Language",
Packit a55458
		"Group Associations",
Packit a55458
		"System Event Log",
Packit a55458
		"Physical Memory Array",
Packit a55458
		"Memory Device",
Packit a55458
		"32-bit Memory Error",
Packit a55458
		"Memory Array Mapped Address",
Packit a55458
		"Memory Device Mapped Address",
Packit a55458
		"Built-in Pointing Device",
Packit a55458
		"Portable Battery",
Packit a55458
		"System Reset",
Packit a55458
		"Hardware Security",
Packit a55458
		"System Power Controls",
Packit a55458
		"Voltage Probe",
Packit a55458
		"Cooling Device",
Packit a55458
		"Temperature Probe",
Packit a55458
		"Electrical Current Probe",
Packit a55458
		"Out-of-band Remote Access",
Packit a55458
		"Boot Integrity Services",
Packit a55458
		"System Boot",
Packit a55458
		"64-bit Memory Error",
Packit a55458
		"Management Device",
Packit a55458
		"Management Device Component",
Packit a55458
		"Management Device Threshold Data",
Packit a55458
		"Memory Channel",
Packit a55458
		"IPMI Device",
Packit a55458
		"Power Supply",
Packit a55458
		"Additional Information",
Packit a55458
		"Onboard Device",
Packit a55458
		"Management Controller Host Interface",
Packit a55458
		"TPM Device", /* 43 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 128)
Packit a55458
		return "OEM-specific";
Packit a55458
	if (code <= 43)
Packit a55458
		return type[code];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static int dmi_bcd_range(u8 value, u8 low, u8 high)
Packit a55458
{
Packit a55458
	if (value > 0x99 || (value & 0x0F) > 0x09)
Packit a55458
		return 0;
Packit a55458
	if (value < low || value > high)
Packit a55458
		return 0;
Packit a55458
	return 1;
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_dump(const struct dmi_header *h, const char *prefix)
Packit a55458
{
Packit a55458
	int row, i;
Packit a55458
	const char *s;
Packit a55458
Packit a55458
	printf("%sHeader and Data:\n", prefix);
Packit a55458
	for (row = 0; row < ((h->length - 1) >> 4) + 1; row++)
Packit a55458
	{
Packit a55458
		printf("%s\t", prefix);
Packit a55458
		for (i = 0; i < 16 && i < h->length - (row << 4); i++)
Packit a55458
			printf("%s%02X", i ? " " : "",
Packit a55458
			       (h->data)[(row << 4) + i]);
Packit a55458
		printf("\n");
Packit a55458
	}
Packit a55458
Packit a55458
	if ((h->data)[h->length] || (h->data)[h->length + 1])
Packit a55458
	{
Packit a55458
		printf("%sStrings:\n", prefix);
Packit a55458
		i = 1;
Packit a55458
		while ((s = dmi_string(h, i++)) != bad_index)
Packit a55458
		{
Packit a55458
			if (opt.flags & FLAG_DUMP)
Packit a55458
			{
Packit a55458
				int j, l = strlen(s) + 1;
Packit a55458
				for (row = 0; row < ((l - 1) >> 4) + 1; row++)
Packit a55458
				{
Packit a55458
					printf("%s\t", prefix);
Packit a55458
					for (j = 0; j < 16 && j < l - (row << 4); j++)
Packit a55458
						printf("%s%02X", j ? " " : "",
Packit a55458
						       (unsigned char)s[(row << 4) + j]);
Packit a55458
					printf("\n");
Packit a55458
				}
Packit a55458
				/* String isn't filtered yet so do it now */
Packit a55458
				printf("%s\t\"", prefix);
Packit a55458
				while (*s)
Packit a55458
				{
Packit a55458
					if (*s < 32 || *s == 127)
Packit a55458
						fputc('.', stdout);
Packit a55458
					else
Packit a55458
						fputc(*s, stdout);
Packit a55458
					s++;
Packit a55458
				}
Packit a55458
				printf("\"\n");
Packit a55458
			}
Packit a55458
			else
Packit a55458
				printf("%s\t%s\n", prefix, s);
Packit a55458
		}
Packit a55458
	}
Packit a55458
}
Packit a55458
Packit a55458
/* shift is 0 if the value is in bytes, 1 if it is in kilobytes */
Packit a55458
static void dmi_print_memory_size(u64 code, int shift)
Packit a55458
{
Packit a55458
	unsigned long capacity;
Packit a55458
	u16 split[7];
Packit a55458
	static const char *unit[8] = {
Packit a55458
		"bytes", "kB", "MB", "GB", "TB", "PB", "EB", "ZB"
Packit a55458
	};
Packit a55458
	int i;
Packit a55458
Packit a55458
	/*
Packit a55458
	 * We split the overall size in powers of thousand: EB, PB, TB, GB,
Packit a55458
	 * MB, kB and B. In practice, it is expected that only one or two
Packit a55458
	 * (consecutive) of these will be non-zero.
Packit a55458
	 */
Packit a55458
	split[0] = code.l & 0x3FFUL;
Packit a55458
	split[1] = (code.l >> 10) & 0x3FFUL;
Packit a55458
	split[2] = (code.l >> 20) & 0x3FFUL;
Packit a55458
	split[3] = ((code.h << 2) & 0x3FCUL) | (code.l >> 30);
Packit a55458
	split[4] = (code.h >> 8) & 0x3FFUL;
Packit a55458
	split[5] = (code.h >> 18) & 0x3FFUL;
Packit a55458
	split[6] = code.h >> 28;
Packit a55458
Packit a55458
	/*
Packit a55458
	 * Now we find the highest unit with a non-zero value. If the following
Packit a55458
	 * is also non-zero, we use that as our base. If the following is zero,
Packit a55458
	 * we simply display the highest unit.
Packit a55458
	 */
Packit a55458
	for (i = 6; i > 0; i--)
Packit a55458
	{
Packit a55458
		if (split[i])
Packit a55458
			break;
Packit a55458
	}
Packit a55458
	if (i > 0 && split[i - 1])
Packit a55458
	{
Packit a55458
		i--;
Packit a55458
		capacity = split[i] + (split[i + 1] << 10);
Packit a55458
	}
Packit a55458
	else
Packit a55458
		capacity = split[i];
Packit a55458
Packit a55458
	printf(" %lu %s", capacity, unit[i + shift]);
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.1 BIOS Information (Type 0)
Packit a55458
 */
Packit a55458
Packit a55458
static void dmi_bios_runtime_size(u32 code)
Packit a55458
{
Packit a55458
	if (code & 0x000003FF)
Packit a55458
		printf(" %u bytes", code);
Packit a55458
	else
Packit a55458
		printf(" %u kB", code >> 10);
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_bios_rom_size(u8 code1, u16 code2)
Packit a55458
{
Packit a55458
	static const char *unit[4] = {
Packit a55458
		"MB", "GB", out_of_spec, out_of_spec
Packit a55458
	};
Packit a55458
Packit a55458
	if (code1 != 0xFF)
Packit a55458
		printf(" %u kB", (code1 + 1) << 6);
Packit a55458
	else
Packit a55458
		printf(" %u %s", code2 & 0x3FFF, unit[code2 >> 14]);
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_bios_characteristics(u64 code, const char *prefix)
Packit a55458
{
Packit a55458
	/* 7.1.1 */
Packit a55458
	static const char *characteristics[] = {
Packit a55458
		"BIOS characteristics not supported", /* 3 */
Packit a55458
		"ISA is supported",
Packit a55458
		"MCA is supported",
Packit a55458
		"EISA is supported",
Packit a55458
		"PCI is supported",
Packit a55458
		"PC Card (PCMCIA) is supported",
Packit a55458
		"PNP is supported",
Packit a55458
		"APM is supported",
Packit a55458
		"BIOS is upgradeable",
Packit a55458
		"BIOS shadowing is allowed",
Packit a55458
		"VLB is supported",
Packit a55458
		"ESCD support is available",
Packit a55458
		"Boot from CD is supported",
Packit a55458
		"Selectable boot is supported",
Packit a55458
		"BIOS ROM is socketed",
Packit a55458
		"Boot from PC Card (PCMCIA) is supported",
Packit a55458
		"EDD is supported",
Packit a55458
		"Japanese floppy for NEC 9800 1.2 MB is supported (int 13h)",
Packit a55458
		"Japanese floppy for Toshiba 1.2 MB is supported (int 13h)",
Packit a55458
		"5.25\"/360 kB floppy services are supported (int 13h)",
Packit a55458
		"5.25\"/1.2 MB floppy services are supported (int 13h)",
Packit a55458
		"3.5\"/720 kB floppy services are supported (int 13h)",
Packit a55458
		"3.5\"/2.88 MB floppy services are supported (int 13h)",
Packit a55458
		"Print screen service is supported (int 5h)",
Packit a55458
		"8042 keyboard services are supported (int 9h)",
Packit a55458
		"Serial services are supported (int 14h)",
Packit a55458
		"Printer services are supported (int 17h)",
Packit a55458
		"CGA/mono video services are supported (int 10h)",
Packit a55458
		"NEC PC-98" /* 31 */
Packit a55458
	};
Packit a55458
	int i;
Packit a55458
Packit a55458
	/*
Packit a55458
	 * This isn't very clear what this bit is supposed to mean
Packit a55458
	 */
Packit a55458
	if (code.l & (1 << 3))
Packit a55458
	{
Packit a55458
		printf("%s%s\n",
Packit a55458
			prefix, characteristics[0]);
Packit a55458
		return;
Packit a55458
	}
Packit a55458
Packit a55458
	for (i = 4; i <= 31; i++)
Packit a55458
		if (code.l & (1 << i))
Packit a55458
			printf("%s%s\n",
Packit a55458
				prefix, characteristics[i - 3]);
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_bios_characteristics_x1(u8 code, const char *prefix)
Packit a55458
{
Packit a55458
	/* 7.1.2.1 */
Packit a55458
	static const char *characteristics[] = {
Packit a55458
		"ACPI is supported", /* 0 */
Packit a55458
		"USB legacy is supported",
Packit a55458
		"AGP is supported",
Packit a55458
		"I2O boot is supported",
Packit a55458
		"LS-120 boot is supported",
Packit a55458
		"ATAPI Zip drive boot is supported",
Packit a55458
		"IEEE 1394 boot is supported",
Packit a55458
		"Smart battery is supported" /* 7 */
Packit a55458
	};
Packit a55458
	int i;
Packit a55458
Packit a55458
	for (i = 0; i <= 7; i++)
Packit a55458
		if (code & (1 << i))
Packit a55458
			printf("%s%s\n",
Packit a55458
				prefix, characteristics[i]);
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_bios_characteristics_x2(u8 code, const char *prefix)
Packit a55458
{
Packit a55458
	/* 37.1.2.2 */
Packit a55458
	static const char *characteristics[] = {
Packit a55458
		"BIOS boot specification is supported", /* 0 */
Packit a55458
		"Function key-initiated network boot is supported",
Packit a55458
		"Targeted content distribution is supported",
Packit a55458
		"UEFI is supported",
Packit a55458
		"System is a virtual machine" /* 4 */
Packit a55458
	};
Packit a55458
	int i;
Packit a55458
Packit a55458
	for (i = 0; i <= 4; i++)
Packit a55458
		if (code & (1 << i))
Packit a55458
			printf("%s%s\n",
Packit a55458
				prefix, characteristics[i]);
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.2 System Information (Type 1)
Packit a55458
 */
Packit a55458
Packit a55458
static void dmi_system_uuid(const u8 *p, u16 ver)
Packit a55458
{
Packit a55458
	int only0xFF = 1, only0x00 = 1;
Packit a55458
	int i;
Packit a55458
Packit a55458
	for (i = 0; i < 16 && (only0x00 || only0xFF); i++)
Packit a55458
	{
Packit a55458
		if (p[i] != 0x00) only0x00 = 0;
Packit a55458
		if (p[i] != 0xFF) only0xFF = 0;
Packit a55458
	}
Packit a55458
Packit a55458
	if (only0xFF)
Packit a55458
	{
Packit a55458
		printf("Not Present");
Packit a55458
		return;
Packit a55458
	}
Packit a55458
	if (only0x00)
Packit a55458
	{
Packit a55458
		printf("Not Settable");
Packit a55458
		return;
Packit a55458
	}
Packit a55458
Packit a55458
	/*
Packit a55458
	 * As of version 2.6 of the SMBIOS specification, the first 3
Packit a55458
	 * fields of the UUID are supposed to be encoded on little-endian.
Packit a55458
	 * The specification says that this is the defacto standard,
Packit a55458
	 * however I've seen systems following RFC 4122 instead and use
Packit a55458
	 * network byte order, so I am reluctant to apply the byte-swapping
Packit a55458
	 * for older versions.
Packit a55458
	 */
Packit a55458
	if (ver >= 0x0206)
Packit a55458
		printf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
Packit a55458
			p[3], p[2], p[1], p[0], p[5], p[4], p[7], p[6],
Packit a55458
			p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
Packit a55458
	else
Packit a55458
		printf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
Packit a55458
			p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
Packit a55458
			p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_system_wake_up_type(u8 code)
Packit a55458
{
Packit a55458
	/* 7.2.2 */
Packit a55458
	static const char *type[] = {
Packit a55458
		"Reserved", /* 0x00 */
Packit a55458
		"Other",
Packit a55458
		"Unknown",
Packit a55458
		"APM Timer",
Packit a55458
		"Modem Ring",
Packit a55458
		"LAN Remote",
Packit a55458
		"Power Switch",
Packit a55458
		"PCI PME#",
Packit a55458
		"AC Power Restored" /* 0x08 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code <= 0x08)
Packit a55458
		return type[code];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.3 Base Board Information (Type 2)
Packit a55458
 */
Packit a55458
Packit a55458
static void dmi_base_board_features(u8 code, const char *prefix)
Packit a55458
{
Packit a55458
	/* 7.3.1 */
Packit a55458
	static const char *features[] = {
Packit a55458
		"Board is a hosting board", /* 0 */
Packit a55458
		"Board requires at least one daughter board",
Packit a55458
		"Board is removable",
Packit a55458
		"Board is replaceable",
Packit a55458
		"Board is hot swappable" /* 4 */
Packit a55458
	};
Packit a55458
Packit a55458
	if ((code & 0x1F) == 0)
Packit a55458
		printf(" None\n");
Packit a55458
	else
Packit a55458
	{
Packit a55458
		int i;
Packit a55458
Packit a55458
		printf("\n");
Packit a55458
		for (i = 0; i <= 4; i++)
Packit a55458
			if (code & (1 << i))
Packit a55458
				printf("%s%s\n",
Packit a55458
					prefix, features[i]);
Packit a55458
	}
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_base_board_type(u8 code)
Packit a55458
{
Packit a55458
	/* 7.3.2 */
Packit a55458
	static const char *type[] = {
Packit a55458
		"Unknown", /* 0x01 */
Packit a55458
		"Other",
Packit a55458
		"Server Blade",
Packit a55458
		"Connectivity Switch",
Packit a55458
		"System Management Module",
Packit a55458
		"Processor Module",
Packit a55458
		"I/O Module",
Packit a55458
		"Memory Module",
Packit a55458
		"Daughter Board",
Packit a55458
		"Motherboard",
Packit a55458
		"Processor+Memory Module",
Packit a55458
		"Processor+I/O Module",
Packit a55458
		"Interconnect Board" /* 0x0D */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x0D)
Packit a55458
		return type[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_base_board_handles(u8 count, const u8 *p, const char *prefix)
Packit a55458
{
Packit a55458
	int i;
Packit a55458
Packit a55458
	printf("%sContained Object Handles: %u\n",
Packit a55458
		prefix, count);
Packit a55458
	for (i = 0; i < count; i++)
Packit a55458
		printf("%s\t0x%04X\n",
Packit a55458
			prefix, WORD(p + sizeof(u16) * i));
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.4 Chassis Information (Type 3)
Packit a55458
 */
Packit a55458
Packit a55458
static const char *dmi_chassis_type(u8 code)
Packit a55458
{
Packit a55458
	/* 7.4.1 */
Packit a55458
	static const char *type[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"Desktop",
Packit a55458
		"Low Profile Desktop",
Packit a55458
		"Pizza Box",
Packit a55458
		"Mini Tower",
Packit a55458
		"Tower",
Packit a55458
		"Portable",
Packit a55458
		"Laptop",
Packit a55458
		"Notebook",
Packit a55458
		"Hand Held",
Packit a55458
		"Docking Station",
Packit a55458
		"All In One",
Packit a55458
		"Sub Notebook",
Packit a55458
		"Space-saving",
Packit a55458
		"Lunch Box",
Packit a55458
		"Main Server Chassis", /* CIM_Chassis.ChassisPackageType says "Main System Chassis" */
Packit a55458
		"Expansion Chassis",
Packit a55458
		"Sub Chassis",
Packit a55458
		"Bus Expansion Chassis",
Packit a55458
		"Peripheral Chassis",
Packit a55458
		"RAID Chassis",
Packit a55458
		"Rack Mount Chassis",
Packit a55458
		"Sealed-case PC",
Packit a55458
		"Multi-system",
Packit a55458
		"CompactPCI",
Packit a55458
		"AdvancedTCA",
Packit a55458
		"Blade",
Packit a55458
		"Blade Enclosing",
Packit a55458
		"Tablet",
Packit a55458
		"Convertible",
Packit a55458
		"Detachable",
Packit a55458
		"IoT Gateway",
Packit a55458
		"Embedded PC",
Packit a55458
		"Mini PC",
Packit a55458
		"Stick PC" /* 0x24 */
Packit a55458
	};
Packit a55458
Packit a55458
	code &= 0x7F; /* bits 6:0 are chassis type, 7th bit is the lock bit */
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x24)
Packit a55458
		return type[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_chassis_lock(u8 code)
Packit a55458
{
Packit a55458
	static const char *lock[] = {
Packit a55458
		"Not Present", /* 0x00 */
Packit a55458
		"Present" /* 0x01 */
Packit a55458
	};
Packit a55458
Packit a55458
	return lock[code];
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_chassis_state(u8 code)
Packit a55458
{
Packit a55458
	/* 7.4.2 */
Packit a55458
	static const char *state[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"Safe",
Packit a55458
		"Warning",
Packit a55458
		"Critical",
Packit a55458
		"Non-recoverable" /* 0x06 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x06)
Packit a55458
		return state[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_chassis_security_status(u8 code)
Packit a55458
{
Packit a55458
	/* 7.4.3 */
Packit a55458
	static const char *status[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"None",
Packit a55458
		"External Interface Locked Out",
Packit a55458
		"External Interface Enabled" /* 0x05 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x05)
Packit a55458
		return status[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_chassis_height(u8 code)
Packit a55458
{
Packit a55458
	if (code == 0x00)
Packit a55458
		printf(" Unspecified");
Packit a55458
	else
Packit a55458
		printf(" %u U", code);
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_chassis_power_cords(u8 code)
Packit a55458
{
Packit a55458
	if (code == 0x00)
Packit a55458
		printf(" Unspecified");
Packit a55458
	else
Packit a55458
		printf(" %u", code);
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_chassis_elements(u8 count, u8 len, const u8 *p, const char *prefix)
Packit a55458
{
Packit a55458
	int i;
Packit a55458
Packit a55458
	printf("%sContained Elements: %u\n",
Packit a55458
		prefix, count);
Packit a55458
	for (i = 0; i < count; i++)
Packit a55458
	{
Packit a55458
		if (len >= 0x03)
Packit a55458
		{
Packit a55458
			printf("%s\t%s (",
Packit a55458
				prefix, p[i * len] & 0x80 ?
Packit a55458
				dmi_smbios_structure_type(p[i * len] & 0x7F) :
Packit a55458
				dmi_base_board_type(p[i * len] & 0x7F));
Packit a55458
			if (p[1 + i * len] == p[2 + i * len])
Packit a55458
				printf("%u", p[1 + i * len]);
Packit a55458
			else
Packit a55458
				printf("%u-%u", p[1 + i * len], p[2 + i * len]);
Packit a55458
			printf(")\n");
Packit a55458
		}
Packit a55458
	}
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.5 Processor Information (Type 4)
Packit a55458
 */
Packit a55458
Packit a55458
static const char *dmi_processor_type(u8 code)
Packit a55458
{
Packit a55458
	/* 7.5.1 */
Packit a55458
	static const char *type[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"Central Processor",
Packit a55458
		"Math Processor",
Packit a55458
		"DSP Processor",
Packit a55458
		"Video Processor" /* 0x06 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x06)
Packit a55458
		return type[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_processor_family(const struct dmi_header *h, u16 ver)
Packit a55458
{
Packit a55458
	const u8 *data = h->data;
Packit a55458
	unsigned int i, low, high;
Packit a55458
	u16 code;
Packit a55458
Packit a55458
	/* 7.5.2 */
Packit a55458
	static struct {
Packit a55458
		int value;
Packit a55458
		const char *name;
Packit a55458
	} family2[] = {
Packit a55458
		{ 0x01, "Other" },
Packit a55458
		{ 0x02, "Unknown" },
Packit a55458
		{ 0x03, "8086" },
Packit a55458
		{ 0x04, "80286" },
Packit a55458
		{ 0x05, "80386" },
Packit a55458
		{ 0x06, "80486" },
Packit a55458
		{ 0x07, "8087" },
Packit a55458
		{ 0x08, "80287" },
Packit a55458
		{ 0x09, "80387" },
Packit a55458
		{ 0x0A, "80487" },
Packit a55458
		{ 0x0B, "Pentium" },
Packit a55458
		{ 0x0C, "Pentium Pro" },
Packit a55458
		{ 0x0D, "Pentium II" },
Packit a55458
		{ 0x0E, "Pentium MMX" },
Packit a55458
		{ 0x0F, "Celeron" },
Packit a55458
		{ 0x10, "Pentium II Xeon" },
Packit a55458
		{ 0x11, "Pentium III" },
Packit a55458
		{ 0x12, "M1" },
Packit a55458
		{ 0x13, "M2" },
Packit a55458
		{ 0x14, "Celeron M" },
Packit a55458
		{ 0x15, "Pentium 4 HT" },
Packit a55458
Packit a55458
		{ 0x18, "Duron" },
Packit a55458
		{ 0x19, "K5" },
Packit a55458
		{ 0x1A, "K6" },
Packit a55458
		{ 0x1B, "K6-2" },
Packit a55458
		{ 0x1C, "K6-3" },
Packit a55458
		{ 0x1D, "Athlon" },
Packit a55458
		{ 0x1E, "AMD29000" },
Packit a55458
		{ 0x1F, "K6-2+" },
Packit a55458
		{ 0x20, "Power PC" },
Packit a55458
		{ 0x21, "Power PC 601" },
Packit a55458
		{ 0x22, "Power PC 603" },
Packit a55458
		{ 0x23, "Power PC 603+" },
Packit a55458
		{ 0x24, "Power PC 604" },
Packit a55458
		{ 0x25, "Power PC 620" },
Packit a55458
		{ 0x26, "Power PC x704" },
Packit a55458
		{ 0x27, "Power PC 750" },
Packit a55458
		{ 0x28, "Core Duo" },
Packit a55458
		{ 0x29, "Core Duo Mobile" },
Packit a55458
		{ 0x2A, "Core Solo Mobile" },
Packit a55458
		{ 0x2B, "Atom" },
Packit a55458
		{ 0x2C, "Core M" },
Packit a55458
		{ 0x2D, "Core m3" },
Packit a55458
		{ 0x2E, "Core m5" },
Packit a55458
		{ 0x2F, "Core m7" },
Packit a55458
		{ 0x30, "Alpha" },
Packit a55458
		{ 0x31, "Alpha 21064" },
Packit a55458
		{ 0x32, "Alpha 21066" },
Packit a55458
		{ 0x33, "Alpha 21164" },
Packit a55458
		{ 0x34, "Alpha 21164PC" },
Packit a55458
		{ 0x35, "Alpha 21164a" },
Packit a55458
		{ 0x36, "Alpha 21264" },
Packit a55458
		{ 0x37, "Alpha 21364" },
Packit a55458
		{ 0x38, "Turion II Ultra Dual-Core Mobile M" },
Packit a55458
		{ 0x39, "Turion II Dual-Core Mobile M" },
Packit a55458
		{ 0x3A, "Athlon II Dual-Core M" },
Packit a55458
		{ 0x3B, "Opteron 6100" },
Packit a55458
		{ 0x3C, "Opteron 4100" },
Packit a55458
		{ 0x3D, "Opteron 6200" },
Packit a55458
		{ 0x3E, "Opteron 4200" },
Packit a55458
		{ 0x3F, "FX" },
Packit a55458
		{ 0x40, "MIPS" },
Packit a55458
		{ 0x41, "MIPS R4000" },
Packit a55458
		{ 0x42, "MIPS R4200" },
Packit a55458
		{ 0x43, "MIPS R4400" },
Packit a55458
		{ 0x44, "MIPS R4600" },
Packit a55458
		{ 0x45, "MIPS R10000" },
Packit a55458
		{ 0x46, "C-Series" },
Packit a55458
		{ 0x47, "E-Series" },
Packit a55458
		{ 0x48, "A-Series" },
Packit a55458
		{ 0x49, "G-Series" },
Packit a55458
		{ 0x4A, "Z-Series" },
Packit a55458
		{ 0x4B, "R-Series" },
Packit a55458
		{ 0x4C, "Opteron 4300" },
Packit a55458
		{ 0x4D, "Opteron 6300" },
Packit a55458
		{ 0x4E, "Opteron 3300" },
Packit a55458
		{ 0x4F, "FirePro" },
Packit a55458
		{ 0x50, "SPARC" },
Packit a55458
		{ 0x51, "SuperSPARC" },
Packit a55458
		{ 0x52, "MicroSPARC II" },
Packit a55458
		{ 0x53, "MicroSPARC IIep" },
Packit a55458
		{ 0x54, "UltraSPARC" },
Packit a55458
		{ 0x55, "UltraSPARC II" },
Packit a55458
		{ 0x56, "UltraSPARC IIi" },
Packit a55458
		{ 0x57, "UltraSPARC III" },
Packit a55458
		{ 0x58, "UltraSPARC IIIi" },
Packit a55458
Packit a55458
		{ 0x60, "68040" },
Packit a55458
		{ 0x61, "68xxx" },
Packit a55458
		{ 0x62, "68000" },
Packit a55458
		{ 0x63, "68010" },
Packit a55458
		{ 0x64, "68020" },
Packit a55458
		{ 0x65, "68030" },
Packit a55458
		{ 0x66, "Athlon X4" },
Packit a55458
		{ 0x67, "Opteron X1000" },
Packit a55458
		{ 0x68, "Opteron X2000" },
Packit a55458
		{ 0x69, "Opteron A-Series" },
Packit a55458
		{ 0x6A, "Opteron X3000" },
Packit a55458
		{ 0x6B, "Zen" },
Packit a55458
Packit a55458
		{ 0x70, "Hobbit" },
Packit a55458
Packit a55458
		{ 0x78, "Crusoe TM5000" },
Packit a55458
		{ 0x79, "Crusoe TM3000" },
Packit a55458
		{ 0x7A, "Efficeon TM8000" },
Packit a55458
Packit a55458
		{ 0x80, "Weitek" },
Packit a55458
Packit a55458
		{ 0x82, "Itanium" },
Packit a55458
		{ 0x83, "Athlon 64" },
Packit a55458
		{ 0x84, "Opteron" },
Packit a55458
		{ 0x85, "Sempron" },
Packit a55458
		{ 0x86, "Turion 64" },
Packit a55458
		{ 0x87, "Dual-Core Opteron" },
Packit a55458
		{ 0x88, "Athlon 64 X2" },
Packit a55458
		{ 0x89, "Turion 64 X2" },
Packit a55458
		{ 0x8A, "Quad-Core Opteron" },
Packit a55458
		{ 0x8B, "Third-Generation Opteron" },
Packit a55458
		{ 0x8C, "Phenom FX" },
Packit a55458
		{ 0x8D, "Phenom X4" },
Packit a55458
		{ 0x8E, "Phenom X2" },
Packit a55458
		{ 0x8F, "Athlon X2" },
Packit a55458
		{ 0x90, "PA-RISC" },
Packit a55458
		{ 0x91, "PA-RISC 8500" },
Packit a55458
		{ 0x92, "PA-RISC 8000" },
Packit a55458
		{ 0x93, "PA-RISC 7300LC" },
Packit a55458
		{ 0x94, "PA-RISC 7200" },
Packit a55458
		{ 0x95, "PA-RISC 7100LC" },
Packit a55458
		{ 0x96, "PA-RISC 7100" },
Packit a55458
Packit a55458
		{ 0xA0, "V30" },
Packit a55458
		{ 0xA1, "Quad-Core Xeon 3200" },
Packit a55458
		{ 0xA2, "Dual-Core Xeon 3000" },
Packit a55458
		{ 0xA3, "Quad-Core Xeon 5300" },
Packit a55458
		{ 0xA4, "Dual-Core Xeon 5100" },
Packit a55458
		{ 0xA5, "Dual-Core Xeon 5000" },
Packit a55458
		{ 0xA6, "Dual-Core Xeon LV" },
Packit a55458
		{ 0xA7, "Dual-Core Xeon ULV" },
Packit a55458
		{ 0xA8, "Dual-Core Xeon 7100" },
Packit a55458
		{ 0xA9, "Quad-Core Xeon 5400" },
Packit a55458
		{ 0xAA, "Quad-Core Xeon" },
Packit a55458
		{ 0xAB, "Dual-Core Xeon 5200" },
Packit a55458
		{ 0xAC, "Dual-Core Xeon 7200" },
Packit a55458
		{ 0xAD, "Quad-Core Xeon 7300" },
Packit a55458
		{ 0xAE, "Quad-Core Xeon 7400" },
Packit a55458
		{ 0xAF, "Multi-Core Xeon 7400" },
Packit a55458
		{ 0xB0, "Pentium III Xeon" },
Packit a55458
		{ 0xB1, "Pentium III Speedstep" },
Packit a55458
		{ 0xB2, "Pentium 4" },
Packit a55458
		{ 0xB3, "Xeon" },
Packit a55458
		{ 0xB4, "AS400" },
Packit a55458
		{ 0xB5, "Xeon MP" },
Packit a55458
		{ 0xB6, "Athlon XP" },
Packit a55458
		{ 0xB7, "Athlon MP" },
Packit a55458
		{ 0xB8, "Itanium 2" },
Packit a55458
		{ 0xB9, "Pentium M" },
Packit a55458
		{ 0xBA, "Celeron D" },
Packit a55458
		{ 0xBB, "Pentium D" },
Packit a55458
		{ 0xBC, "Pentium EE" },
Packit a55458
		{ 0xBD, "Core Solo" },
Packit a55458
		/* 0xBE handled as a special case */
Packit a55458
		{ 0xBF, "Core 2 Duo" },
Packit a55458
		{ 0xC0, "Core 2 Solo" },
Packit a55458
		{ 0xC1, "Core 2 Extreme" },
Packit a55458
		{ 0xC2, "Core 2 Quad" },
Packit a55458
		{ 0xC3, "Core 2 Extreme Mobile" },
Packit a55458
		{ 0xC4, "Core 2 Duo Mobile" },
Packit a55458
		{ 0xC5, "Core 2 Solo Mobile" },
Packit a55458
		{ 0xC6, "Core i7" },
Packit a55458
		{ 0xC7, "Dual-Core Celeron" },
Packit a55458
		{ 0xC8, "IBM390" },
Packit a55458
		{ 0xC9, "G4" },
Packit a55458
		{ 0xCA, "G5" },
Packit a55458
		{ 0xCB, "ESA/390 G6" },
Packit a55458
		{ 0xCC, "z/Architecture" },
Packit a55458
		{ 0xCD, "Core i5" },
Packit a55458
		{ 0xCE, "Core i3" },
Packit a55458
		{ 0xCF, "Core i9" },
Packit a55458
Packit a55458
		{ 0xD2, "C7-M" },
Packit a55458
		{ 0xD3, "C7-D" },
Packit a55458
		{ 0xD4, "C7" },
Packit a55458
		{ 0xD5, "Eden" },
Packit a55458
		{ 0xD6, "Multi-Core Xeon" },
Packit a55458
		{ 0xD7, "Dual-Core Xeon 3xxx" },
Packit a55458
		{ 0xD8, "Quad-Core Xeon 3xxx" },
Packit a55458
		{ 0xD9, "Nano" },
Packit a55458
		{ 0xDA, "Dual-Core Xeon 5xxx" },
Packit a55458
		{ 0xDB, "Quad-Core Xeon 5xxx" },
Packit a55458
Packit a55458
		{ 0xDD, "Dual-Core Xeon 7xxx" },
Packit a55458
		{ 0xDE, "Quad-Core Xeon 7xxx" },
Packit a55458
		{ 0xDF, "Multi-Core Xeon 7xxx" },
Packit a55458
		{ 0xE0, "Multi-Core Xeon 3400" },
Packit a55458
Packit a55458
		{ 0xE4, "Opteron 3000" },
Packit a55458
		{ 0xE5, "Sempron II" },
Packit a55458
		{ 0xE6, "Embedded Opteron Quad-Core" },
Packit a55458
		{ 0xE7, "Phenom Triple-Core" },
Packit a55458
		{ 0xE8, "Turion Ultra Dual-Core Mobile" },
Packit a55458
		{ 0xE9, "Turion Dual-Core Mobile" },
Packit a55458
		{ 0xEA, "Athlon Dual-Core" },
Packit a55458
		{ 0xEB, "Sempron SI" },
Packit a55458
		{ 0xEC, "Phenom II" },
Packit a55458
		{ 0xED, "Athlon II" },
Packit a55458
		{ 0xEE, "Six-Core Opteron" },
Packit a55458
		{ 0xEF, "Sempron M" },
Packit a55458
Packit a55458
		{ 0xFA, "i860" },
Packit a55458
		{ 0xFB, "i960" },
Packit a55458
Packit a55458
		{ 0x100, "ARMv7" },
Packit a55458
		{ 0x101, "ARMv8" },
Packit a55458
		{ 0x104, "SH-3" },
Packit a55458
		{ 0x105, "SH-4" },
Packit a55458
		{ 0x118, "ARM" },
Packit a55458
		{ 0x119, "StrongARM" },
Packit a55458
		{ 0x12C, "6x86" },
Packit a55458
		{ 0x12D, "MediaGX" },
Packit a55458
		{ 0x12E, "MII" },
Packit a55458
		{ 0x140, "WinChip" },
Packit a55458
		{ 0x15E, "DSP" },
Packit a55458
		{ 0x1F4, "Video Processor" },
Packit a55458
	};
Packit a55458
	/*
Packit a55458
	 * Note to developers: when adding entries to this list, check if
Packit a55458
	 * function dmi_processor_id below needs updating too.
Packit a55458
	 */
Packit a55458
Packit a55458
	/* Special case for ambiguous value 0x30 (SMBIOS 2.0 only) */
Packit a55458
	if (ver == 0x0200 && data[0x06] == 0x30 && h->length >= 0x08)
Packit a55458
	{
Packit a55458
		const char *manufacturer = dmi_string(h, data[0x07]);
Packit a55458
Packit a55458
		if (strstr(manufacturer, "Intel") != NULL
Packit a55458
		 || strncasecmp(manufacturer, "Intel", 5) == 0)
Packit a55458
			return "Pentium Pro";
Packit a55458
	}
Packit a55458
Packit a55458
	code = (data[0x06] == 0xFE && h->length >= 0x2A) ?
Packit a55458
		WORD(data + 0x28) : data[0x06];
Packit a55458
Packit a55458
	/* Special case for ambiguous value 0xBE */
Packit a55458
	if (code == 0xBE)
Packit a55458
	{
Packit a55458
		if (h->length >= 0x08)
Packit a55458
		{
Packit a55458
			const char *manufacturer = dmi_string(h, data[0x07]);
Packit a55458
Packit a55458
			/* Best bet based on manufacturer string */
Packit a55458
			if (strstr(manufacturer, "Intel") != NULL
Packit a55458
			 || strncasecmp(manufacturer, "Intel", 5) == 0)
Packit a55458
				return "Core 2";
Packit a55458
			if (strstr(manufacturer, "AMD") != NULL
Packit a55458
			 || strncasecmp(manufacturer, "AMD", 3) == 0)
Packit a55458
				return "K7";
Packit a55458
		}
Packit a55458
Packit a55458
		return "Core 2 or K7";
Packit a55458
	}
Packit a55458
Packit a55458
	/* Perform a binary search */
Packit a55458
	low = 0;
Packit a55458
	high = ARRAY_SIZE(family2) - 1;
Packit a55458
Packit a55458
	while (1)
Packit a55458
	{
Packit a55458
		i = (low + high) / 2;
Packit a55458
		if (family2[i].value == code)
Packit a55458
			return family2[i].name;
Packit a55458
		if (low == high) /* Not found */
Packit a55458
			return out_of_spec;
Packit a55458
Packit a55458
		if (code < family2[i].value)
Packit a55458
			high = i;
Packit a55458
		else
Packit a55458
			low = i + 1;
Packit a55458
	}
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_processor_id(const struct dmi_header *h, const char *prefix)
Packit a55458
{
Packit a55458
	/* Intel AP-485 revision 36, table 2-4 */
Packit a55458
	static const char *flags[32] = {
Packit a55458
		"FPU (Floating-point unit on-chip)", /* 0 */
Packit a55458
		"VME (Virtual mode extension)",
Packit a55458
		"DE (Debugging extension)",
Packit a55458
		"PSE (Page size extension)",
Packit a55458
		"TSC (Time stamp counter)",
Packit a55458
		"MSR (Model specific registers)",
Packit a55458
		"PAE (Physical address extension)",
Packit a55458
		"MCE (Machine check exception)",
Packit a55458
		"CX8 (CMPXCHG8 instruction supported)",
Packit a55458
		"APIC (On-chip APIC hardware supported)",
Packit a55458
		NULL, /* 10 */
Packit a55458
		"SEP (Fast system call)",
Packit a55458
		"MTRR (Memory type range registers)",
Packit a55458
		"PGE (Page global enable)",
Packit a55458
		"MCA (Machine check architecture)",
Packit a55458
		"CMOV (Conditional move instruction supported)",
Packit a55458
		"PAT (Page attribute table)",
Packit a55458
		"PSE-36 (36-bit page size extension)",
Packit a55458
		"PSN (Processor serial number present and enabled)",
Packit a55458
		"CLFSH (CLFLUSH instruction supported)",
Packit a55458
		NULL, /* 20 */
Packit a55458
		"DS (Debug store)",
Packit a55458
		"ACPI (ACPI supported)",
Packit a55458
		"MMX (MMX technology supported)",
Packit a55458
		"FXSR (FXSAVE and FXSTOR instructions supported)",
Packit a55458
		"SSE (Streaming SIMD extensions)",
Packit a55458
		"SSE2 (Streaming SIMD extensions 2)",
Packit a55458
		"SS (Self-snoop)",
Packit a55458
		"HTT (Multi-threading)",
Packit a55458
		"TM (Thermal monitor supported)",
Packit a55458
		NULL, /* 30 */
Packit a55458
		"PBE (Pending break enabled)" /* 31 */
Packit a55458
	};
Packit a55458
	const u8 *data = h->data;
Packit a55458
	const u8 *p = data + 0x08;
Packit a55458
	u32 eax, edx;
Packit a55458
	int sig = 0;
Packit a55458
	u16 type;
Packit a55458
Packit a55458
	type = (data[0x06] == 0xFE && h->length >= 0x2A) ?
Packit a55458
		WORD(data + 0x28) : data[0x06];
Packit a55458
Packit a55458
	/*
Packit a55458
	 * This might help learn about new processors supporting the
Packit a55458
	 * CPUID instruction or another form of identification.
Packit a55458
	 */
Packit a55458
	printf("%sID: %02X %02X %02X %02X %02X %02X %02X %02X\n",
Packit a55458
		prefix, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
Packit a55458
Packit a55458
	if (type == 0x05) /* 80386 */
Packit a55458
	{
Packit a55458
		u16 dx = WORD(p);
Packit a55458
		/*
Packit a55458
		 * 80386 have a different signature.
Packit a55458
		 */
Packit a55458
		printf("%sSignature: Type %u, Family %u, Major Stepping %u, Minor Stepping %u\n",
Packit a55458
			prefix, dx >> 12, (dx >> 8) & 0xF,
Packit a55458
			(dx >> 4) & 0xF, dx & 0xF);
Packit a55458
		return;
Packit a55458
	}
Packit a55458
	if (type == 0x06) /* 80486 */
Packit a55458
	{
Packit a55458
		u16 dx = WORD(p);
Packit a55458
		/*
Packit a55458
		 * Not all 80486 CPU support the CPUID instruction, we have to find
Packit a55458
		 * wether the one we have here does or not. Note that this trick
Packit a55458
		 * works only because we know that 80486 must be little-endian.
Packit a55458
		 */
Packit a55458
		if ((dx & 0x0F00) == 0x0400
Packit a55458
		 && ((dx & 0x00F0) == 0x0040 || (dx & 0x00F0) >= 0x0070)
Packit a55458
		 && ((dx & 0x000F) >= 0x0003))
Packit a55458
			sig = 1;
Packit a55458
		else
Packit a55458
		{
Packit a55458
			printf("%sSignature: Type %u, Family %u, Model %u, Stepping %u\n",
Packit a55458
				prefix, (dx >> 12) & 0x3, (dx >> 8) & 0xF,
Packit a55458
				(dx >> 4) & 0xF, dx & 0xF);
Packit a55458
			return;
Packit a55458
		}
Packit a55458
	}
Packit a55458
	else if ((type >= 0x100 && type <= 0x101) /* ARM */
Packit a55458
	      || (type >= 0x118 && type <= 0x119)) /* ARM */
Packit a55458
	{
Packit a55458
		u32 midr = DWORD(p);
Packit a55458
		/*
Packit a55458
		 * The format of this field was not defined for ARM processors
Packit a55458
		 * before version 3.1.0 of the SMBIOS specification, so we
Packit a55458
		 * silently skip it if it reads all zeroes.
Packit a55458
		 */
Packit a55458
		if (midr == 0)
Packit a55458
			return;
Packit a55458
		printf("%sSignature: Implementor 0x%02x, Variant 0x%x, Architecture %u, Part 0x%03x, Revision %u\n",
Packit a55458
			prefix, midr >> 24, (midr >> 20) & 0xF,
Packit a55458
			(midr >> 16) & 0xF, (midr >> 4) & 0xFFF, midr & 0xF);
Packit a55458
		return;
Packit a55458
	}
Packit a55458
	else if ((type >= 0x0B && type <= 0x15) /* Intel, Cyrix */
Packit a55458
	      || (type >= 0x28 && type <= 0x2F) /* Intel */
Packit a55458
	      || (type >= 0xA1 && type <= 0xB3) /* Intel */
Packit a55458
	      || type == 0xB5 /* Intel */
Packit a55458
	      || (type >= 0xB9 && type <= 0xC7) /* Intel */
Packit a55458
	      || (type >= 0xCD && type <= 0xCF) /* Intel */
Packit a55458
	      || (type >= 0xD2 && type <= 0xDB) /* VIA, Intel */
Packit a55458
	      || (type >= 0xDD && type <= 0xE0)) /* Intel */
Packit a55458
		sig = 1;
Packit a55458
	else if ((type >= 0x18 && type <= 0x1D) /* AMD */
Packit a55458
	      || type == 0x1F /* AMD */
Packit a55458
	      || (type >= 0x38 && type <= 0x3F) /* AMD */
Packit a55458
	      || (type >= 0x46 && type <= 0x4F) /* AMD */
Packit a55458
	      || (type >= 0x66 && type <= 0x6B) /* AMD */
Packit a55458
	      || (type >= 0x83 && type <= 0x8F) /* AMD */
Packit a55458
	      || (type >= 0xB6 && type <= 0xB7) /* AMD */
Packit a55458
	      || (type >= 0xE4 && type <= 0xEF)) /* AMD */
Packit a55458
		sig = 2;
Packit a55458
	else if (type == 0x01 || type == 0x02)
Packit a55458
	{
Packit a55458
		const char *version = dmi_string(h, data[0x10]);
Packit a55458
		/*
Packit a55458
		 * Some X86-class CPU have family "Other" or "Unknown". In this case,
Packit a55458
		 * we use the version string to determine if they are known to
Packit a55458
		 * support the CPUID instruction.
Packit a55458
		 */
Packit a55458
		if (strncmp(version, "Pentium III MMX", 15) == 0
Packit a55458
		 || strncmp(version, "Intel(R) Core(TM)2", 18) == 0
Packit a55458
		 || strncmp(version, "Intel(R) Pentium(R)", 19) == 0
Packit a55458
		 || strcmp(version, "Genuine Intel(R) CPU U1400") == 0)
Packit a55458
			sig = 1;
Packit a55458
		else if (strncmp(version, "AMD Athlon(TM)", 14) == 0
Packit a55458
		      || strncmp(version, "AMD Opteron(tm)", 15) == 0
Packit a55458
		      || strncmp(version, "Dual-Core AMD Opteron(tm)", 25) == 0)
Packit a55458
			sig = 2;
Packit a55458
		else
Packit a55458
			return;
Packit a55458
	}
Packit a55458
	else /* neither X86 nor ARM */
Packit a55458
		return;
Packit a55458
Packit a55458
	/*
Packit a55458
	 * Extra flags are now returned in the ECX register when one calls
Packit a55458
	 * the CPUID instruction. Their meaning is explained in table 3-5, but
Packit a55458
	 * DMI doesn't support this yet.
Packit a55458
	 */
Packit a55458
	eax = DWORD(p);
Packit a55458
	edx = DWORD(p + 4);
Packit a55458
	switch (sig)
Packit a55458
	{
Packit a55458
		case 1: /* Intel */
Packit a55458
			printf("%sSignature: Type %u, Family %u, Model %u, Stepping %u\n",
Packit a55458
				prefix, (eax >> 12) & 0x3,
Packit a55458
				((eax >> 20) & 0xFF) + ((eax >> 8) & 0x0F),
Packit a55458
				((eax >> 12) & 0xF0) + ((eax >> 4) & 0x0F),
Packit a55458
				eax & 0xF);
Packit a55458
			break;
Packit a55458
		case 2: /* AMD, publication #25481 revision 2.28 */
Packit a55458
			printf("%sSignature: Family %u, Model %u, Stepping %u\n",
Packit a55458
				prefix,
Packit a55458
				((eax >> 8) & 0xF) + (((eax >> 8) & 0xF) == 0xF ? (eax >> 20) & 0xFF : 0),
Packit a55458
				((eax >> 4) & 0xF) | (((eax >> 8) & 0xF) == 0xF ? (eax >> 12) & 0xF0 : 0),
Packit a55458
				eax & 0xF);
Packit a55458
			break;
Packit a55458
	}
Packit a55458
Packit a55458
	edx = DWORD(p + 4);
Packit a55458
	printf("%sFlags:", prefix);
Packit a55458
	if ((edx & 0xBFEFFBFF) == 0)
Packit a55458
		printf(" None\n");
Packit a55458
	else
Packit a55458
	{
Packit a55458
		int i;
Packit a55458
Packit a55458
		printf("\n");
Packit a55458
		for (i = 0; i <= 31; i++)
Packit a55458
			if (flags[i] != NULL && edx & (1 << i))
Packit a55458
				printf("%s\t%s\n", prefix, flags[i]);
Packit a55458
	}
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_processor_voltage(u8 code)
Packit a55458
{
Packit a55458
	/* 7.5.4 */
Packit a55458
	static const char *voltage[] = {
Packit a55458
		"5.0 V", /* 0 */
Packit a55458
		"3.3 V",
Packit a55458
		"2.9 V" /* 2 */
Packit a55458
	};
Packit a55458
	int i;
Packit a55458
Packit a55458
	if (code & 0x80)
Packit a55458
		printf(" %.1f V", (float)(code & 0x7f) / 10);
Packit a55458
	else
Packit a55458
	{
Packit a55458
		for (i = 0; i <= 2; i++)
Packit a55458
			if (code & (1 << i))
Packit a55458
				printf(" %s", voltage[i]);
Packit a55458
		if (code == 0x00)
Packit a55458
			printf(" Unknown");
Packit a55458
	}
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_processor_frequency(const u8 *p)
Packit a55458
{
Packit a55458
	u16 code = WORD(p);
Packit a55458
Packit a55458
	if (code)
Packit a55458
		printf("%u MHz", code);
Packit a55458
	else
Packit a55458
		printf("Unknown");
Packit a55458
}
Packit a55458
Packit a55458
/* code is assumed to be a 3-bit value */
Packit a55458
static const char *dmi_processor_status(u8 code)
Packit a55458
{
Packit a55458
	static const char *status[] = {
Packit a55458
		"Unknown", /* 0x00 */
Packit a55458
		"Enabled",
Packit a55458
		"Disabled By User",
Packit a55458
		"Disabled By BIOS",
Packit a55458
		"Idle", /* 0x04 */
Packit a55458
		out_of_spec,
Packit a55458
		out_of_spec,
Packit a55458
		"Other" /* 0x07 */
Packit a55458
	};
Packit a55458
Packit a55458
	return status[code];
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_processor_upgrade(u8 code)
Packit a55458
{
Packit a55458
	/* 7.5.5 */
Packit a55458
	static const char *upgrade[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"Daughter Board",
Packit a55458
		"ZIF Socket",
Packit a55458
		"Replaceable Piggy Back",
Packit a55458
		"None",
Packit a55458
		"LIF Socket",
Packit a55458
		"Slot 1",
Packit a55458
		"Slot 2",
Packit a55458
		"370-pin Socket",
Packit a55458
		"Slot A",
Packit a55458
		"Slot M",
Packit a55458
		"Socket 423",
Packit a55458
		"Socket A (Socket 462)",
Packit a55458
		"Socket 478",
Packit a55458
		"Socket 754",
Packit a55458
		"Socket 940",
Packit a55458
		"Socket 939",
Packit a55458
		"Socket mPGA604",
Packit a55458
		"Socket LGA771",
Packit a55458
		"Socket LGA775",
Packit a55458
		"Socket S1",
Packit a55458
		"Socket AM2",
Packit a55458
		"Socket F (1207)",
Packit a55458
		"Socket LGA1366",
Packit a55458
		"Socket G34",
Packit a55458
		"Socket AM3",
Packit a55458
		"Socket C32",
Packit a55458
		"Socket LGA1156",
Packit a55458
		"Socket LGA1567",
Packit a55458
		"Socket PGA988A",
Packit a55458
		"Socket BGA1288",
Packit a55458
		"Socket rPGA988B",
Packit a55458
		"Socket BGA1023",
Packit a55458
		"Socket BGA1224",
Packit a55458
		"Socket BGA1155",
Packit a55458
		"Socket LGA1356",
Packit a55458
		"Socket LGA2011",
Packit a55458
		"Socket FS1",
Packit a55458
		"Socket FS2",
Packit a55458
		"Socket FM1",
Packit a55458
		"Socket FM2",
Packit a55458
		"Socket LGA2011-3",
Packit a55458
		"Socket LGA1356-3",
Packit a55458
		"Socket LGA1150",
Packit a55458
		"Socket BGA1168",
Packit a55458
		"Socket BGA1234",
Packit a55458
		"Socket BGA1364",
Packit a55458
		"Socket AM4",
Packit a55458
		"Socket LGA1151",
Packit a55458
		"Socket BGA1356",
Packit a55458
		"Socket BGA1440",
Packit a55458
		"Socket BGA1515",
Packit a55458
		"Socket LGA3647-1",
Packit a55458
		"Socket SP3",
Packit a55458
		"Socket SP3r2",
Packit a55458
		"Socket LGA2066",
Packit a55458
		"Socket BGA1392",
Packit a55458
		"Socket BGA1510",
Packit a55458
		"Socket BGA1528" /* 0x3C */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x3C)
Packit a55458
		return upgrade[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_processor_cache(u16 code, const char *level, u16 ver)
Packit a55458
{
Packit a55458
	if (code == 0xFFFF)
Packit a55458
	{
Packit a55458
		if (ver >= 0x0203)
Packit a55458
			printf(" Not Provided");
Packit a55458
		else
Packit a55458
			printf(" No %s Cache", level);
Packit a55458
	}
Packit a55458
	else
Packit a55458
		printf(" 0x%04X", code);
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_processor_characteristics(u16 code, const char *prefix)
Packit a55458
{
Packit a55458
	/* 7.5.9 */
Packit a55458
	static const char *characteristics[] = {
Packit a55458
		"64-bit capable", /* 2 */
Packit a55458
		"Multi-Core",
Packit a55458
		"Hardware Thread",
Packit a55458
		"Execute Protection",
Packit a55458
		"Enhanced Virtualization",
Packit a55458
		"Power/Performance Control" /* 7 */
Packit a55458
	};
Packit a55458
Packit a55458
	if ((code & 0x00FC) == 0)
Packit a55458
		printf(" None\n");
Packit a55458
	else
Packit a55458
	{
Packit a55458
		int i;
Packit a55458
Packit a55458
		printf("\n");
Packit a55458
		for (i = 2; i <= 7; i++)
Packit a55458
			if (code & (1 << i))
Packit a55458
				printf("%s%s\n", prefix, characteristics[i - 2]);
Packit a55458
	}
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.6 Memory Controller Information (Type 5)
Packit a55458
 */
Packit a55458
Packit a55458
static const char *dmi_memory_controller_ed_method(u8 code)
Packit a55458
{
Packit a55458
	/* 7.6.1 */
Packit a55458
	static const char *method[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"None",
Packit a55458
		"8-bit Parity",
Packit a55458
		"32-bit ECC",
Packit a55458
		"64-bit ECC",
Packit a55458
		"128-bit ECC",
Packit a55458
		"CRC" /* 0x08 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x08)
Packit a55458
		return method[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_memory_controller_ec_capabilities(u8 code, const char *prefix)
Packit a55458
{
Packit a55458
	/* 7.6.2 */
Packit a55458
	static const char *capabilities[] = {
Packit a55458
		"Other", /* 0 */
Packit a55458
		"Unknown",
Packit a55458
		"None",
Packit a55458
		"Single-bit Error Correcting",
Packit a55458
		"Double-bit Error Correcting",
Packit a55458
		"Error Scrubbing" /* 5 */
Packit a55458
	};
Packit a55458
Packit a55458
	if ((code & 0x3F) == 0)
Packit a55458
		printf(" None\n");
Packit a55458
	else
Packit a55458
	{
Packit a55458
		int i;
Packit a55458
Packit a55458
		printf("\n");
Packit a55458
		for (i = 0; i <= 5; i++)
Packit a55458
			if (code & (1 << i))
Packit a55458
				printf("%s%s\n", prefix, capabilities[i]);
Packit a55458
	}
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_memory_controller_interleave(u8 code)
Packit a55458
{
Packit a55458
	/* 7.6.3 */
Packit a55458
	static const char *interleave[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"One-way Interleave",
Packit a55458
		"Two-way Interleave",
Packit a55458
		"Four-way Interleave",
Packit a55458
		"Eight-way Interleave",
Packit a55458
		"Sixteen-way Interleave" /* 0x07 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x07)
Packit a55458
		return interleave[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_memory_controller_speeds(u16 code, const char *prefix)
Packit a55458
{
Packit a55458
	/* 7.6.4 */
Packit a55458
	const char *speeds[] = {
Packit a55458
		"Other", /* 0 */
Packit a55458
		"Unknown",
Packit a55458
		"70 ns",
Packit a55458
		"60 ns",
Packit a55458
		"50 ns" /* 4 */
Packit a55458
	};
Packit a55458
Packit a55458
	if ((code & 0x001F) == 0)
Packit a55458
		printf(" None\n");
Packit a55458
	else
Packit a55458
	{
Packit a55458
		int i;
Packit a55458
Packit a55458
		printf("\n");
Packit a55458
		for (i = 0; i <= 4; i++)
Packit a55458
			if (code & (1 << i))
Packit a55458
				printf("%s%s\n", prefix, speeds[i]);
Packit a55458
	}
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_memory_controller_slots(u8 count, const u8 *p, const char *prefix)
Packit a55458
{
Packit a55458
	int i;
Packit a55458
Packit a55458
	printf("%sAssociated Memory Slots: %u\n",
Packit a55458
		prefix, count);
Packit a55458
	for (i = 0; i < count; i++)
Packit a55458
		printf("%s\t0x%04X\n",
Packit a55458
			prefix, WORD(p + sizeof(u16) * i));
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.7 Memory Module Information (Type 6)
Packit a55458
 */
Packit a55458
Packit a55458
static void dmi_memory_module_types(u16 code, const char *sep)
Packit a55458
{
Packit a55458
	/* 7.7.1 */
Packit a55458
	static const char *types[] = {
Packit a55458
		"Other", /* 0 */
Packit a55458
		"Unknown",
Packit a55458
		"Standard",
Packit a55458
		"FPM",
Packit a55458
		"EDO",
Packit a55458
		"Parity",
Packit a55458
		"ECC",
Packit a55458
		"SIMM",
Packit a55458
		"DIMM",
Packit a55458
		"Burst EDO",
Packit a55458
		"SDRAM" /* 10 */
Packit a55458
	};
Packit a55458
Packit a55458
	if ((code & 0x07FF) == 0)
Packit a55458
		printf(" None");
Packit a55458
	else
Packit a55458
	{
Packit a55458
		int i;
Packit a55458
Packit a55458
		for (i = 0; i <= 10; i++)
Packit a55458
			if (code & (1 << i))
Packit a55458
				printf("%s%s", sep, types[i]);
Packit a55458
	}
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_memory_module_connections(u8 code)
Packit a55458
{
Packit a55458
	if (code == 0xFF)
Packit a55458
		printf(" None");
Packit a55458
	else
Packit a55458
	{
Packit a55458
		if ((code & 0xF0) != 0xF0)
Packit a55458
			printf(" %u", code >> 4);
Packit a55458
		if ((code & 0x0F) != 0x0F)
Packit a55458
			printf(" %u", code & 0x0F);
Packit a55458
	}
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_memory_module_speed(u8 code)
Packit a55458
{
Packit a55458
	if (code == 0)
Packit a55458
		printf(" Unknown");
Packit a55458
	else
Packit a55458
		printf(" %u ns", code);
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_memory_module_size(u8 code)
Packit a55458
{
Packit a55458
	/* 7.7.2 */
Packit a55458
	switch (code & 0x7F)
Packit a55458
	{
Packit a55458
		case 0x7D:
Packit a55458
			printf(" Not Determinable");
Packit a55458
			break;
Packit a55458
		case 0x7E:
Packit a55458
			printf(" Disabled");
Packit a55458
			break;
Packit a55458
		case 0x7F:
Packit a55458
			printf(" Not Installed");
Packit a55458
			return;
Packit a55458
		default:
Packit a55458
			printf(" %u MB", 1 << (code & 0x7F));
Packit a55458
	}
Packit a55458
Packit a55458
	if (code & 0x80)
Packit a55458
		printf(" (Double-bank Connection)");
Packit a55458
	else
Packit a55458
		printf(" (Single-bank Connection)");
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_memory_module_error(u8 code, const char *prefix)
Packit a55458
{
Packit a55458
	if (code & (1 << 2))
Packit a55458
		printf(" See Event Log\n");
Packit a55458
	else
Packit a55458
	{	if ((code & 0x03) == 0)
Packit a55458
			printf(" OK\n");
Packit a55458
		if (code & (1 << 0))
Packit a55458
			printf("%sUncorrectable Errors\n", prefix);
Packit a55458
		if (code & (1 << 1))
Packit a55458
			printf("%sCorrectable Errors\n", prefix);
Packit a55458
	}
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.8 Cache Information (Type 7)
Packit a55458
 */
Packit a55458
Packit a55458
static const char *dmi_cache_mode(u8 code)
Packit a55458
{
Packit a55458
	static const char *mode[] = {
Packit a55458
		"Write Through", /* 0x00 */
Packit a55458
		"Write Back",
Packit a55458
		"Varies With Memory Address",
Packit a55458
		"Unknown" /* 0x03 */
Packit a55458
	};
Packit a55458
Packit a55458
	return mode[code];
Packit a55458
}
Packit a55458
Packit a55458
/* code is assumed to be a 2-bit value */
Packit a55458
static const char *dmi_cache_location(u8 code)
Packit a55458
{
Packit a55458
	static const char *location[4] = {
Packit a55458
		"Internal", /* 0x00 */
Packit a55458
		"External",
Packit a55458
		out_of_spec, /* 0x02 */
Packit a55458
		"Unknown" /* 0x03 */
Packit a55458
	};
Packit a55458
Packit a55458
	return location[code];
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_cache_size(u16 code)
Packit a55458
{
Packit a55458
	if (code & 0x8000)
Packit a55458
		printf(" %u kB", (code & 0x7FFF) << 6);
Packit a55458
	else
Packit a55458
		printf(" %u kB", code);
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_cache_size_2(u32 code)
Packit a55458
{
Packit a55458
	if (code & 0x80000000)
Packit a55458
	{
Packit a55458
		code &= 0x7FFFFFFFLU;
Packit a55458
		/* Use a more convenient unit for large cache size */
Packit a55458
		if (code >= 0x8000)
Packit a55458
			printf(" %u MB", code >> 4);
Packit a55458
		else
Packit a55458
			printf(" %u kB", code << 6);
Packit a55458
	}
Packit a55458
	else
Packit a55458
		printf(" %u kB", code);
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_cache_types(u16 code, const char *sep)
Packit a55458
{
Packit a55458
	/* 7.8.2 */
Packit a55458
	static const char *types[] = {
Packit a55458
		"Other", /* 0 */
Packit a55458
		"Unknown",
Packit a55458
		"Non-burst",
Packit a55458
		"Burst",
Packit a55458
		"Pipeline Burst",
Packit a55458
		"Synchronous",
Packit a55458
		"Asynchronous" /* 6 */
Packit a55458
	};
Packit a55458
Packit a55458
	if ((code & 0x007F) == 0)
Packit a55458
		printf(" None");
Packit a55458
	else
Packit a55458
	{
Packit a55458
		int i;
Packit a55458
Packit a55458
		for (i = 0; i <= 6; i++)
Packit a55458
			if (code & (1 << i))
Packit a55458
				printf("%s%s", sep, types[i]);
Packit a55458
	}
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_cache_ec_type(u8 code)
Packit a55458
{
Packit a55458
	/* 7.8.3 */
Packit a55458
	static const char *type[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"None",
Packit a55458
		"Parity",
Packit a55458
		"Single-bit ECC",
Packit a55458
		"Multi-bit ECC" /* 0x06 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x06)
Packit a55458
		return type[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_cache_type(u8 code)
Packit a55458
{
Packit a55458
	/* 7.8.4 */
Packit a55458
	static const char *type[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"Instruction",
Packit a55458
		"Data",
Packit a55458
		"Unified" /* 0x05 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x05)
Packit a55458
		return type[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_cache_associativity(u8 code)
Packit a55458
{
Packit a55458
	/* 7.8.5 */
Packit a55458
	static const char *type[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"Direct Mapped",
Packit a55458
		"2-way Set-associative",
Packit a55458
		"4-way Set-associative",
Packit a55458
		"Fully Associative",
Packit a55458
		"8-way Set-associative",
Packit a55458
		"16-way Set-associative",
Packit a55458
		"12-way Set-associative",
Packit a55458
		"24-way Set-associative",
Packit a55458
		"32-way Set-associative",
Packit a55458
		"48-way Set-associative",
Packit a55458
		"64-way Set-associative",
Packit a55458
		"20-way Set-associative" /* 0x0E */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x0E)
Packit a55458
		return type[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.9 Port Connector Information (Type 8)
Packit a55458
 */
Packit a55458
Packit a55458
static const char *dmi_port_connector_type(u8 code)
Packit a55458
{
Packit a55458
	/* 7.9.2 */
Packit a55458
	static const char *type[] = {
Packit a55458
		"None", /* 0x00 */
Packit a55458
		"Centronics",
Packit a55458
		"Mini Centronics",
Packit a55458
		"Proprietary",
Packit a55458
		"DB-25 male",
Packit a55458
		"DB-25 female",
Packit a55458
		"DB-15 male",
Packit a55458
		"DB-15 female",
Packit a55458
		"DB-9 male",
Packit a55458
		"DB-9 female",
Packit a55458
		"RJ-11",
Packit a55458
		"RJ-45",
Packit a55458
		"50 Pin MiniSCSI",
Packit a55458
		"Mini DIN",
Packit a55458
		"Micro DIN",
Packit a55458
		"PS/2",
Packit a55458
		"Infrared",
Packit a55458
		"HP-HIL",
Packit a55458
		"Access Bus (USB)",
Packit a55458
		"SSA SCSI",
Packit a55458
		"Circular DIN-8 male",
Packit a55458
		"Circular DIN-8 female",
Packit a55458
		"On Board IDE",
Packit a55458
		"On Board Floppy",
Packit a55458
		"9 Pin Dual Inline (pin 10 cut)",
Packit a55458
		"25 Pin Dual Inline (pin 26 cut)",
Packit a55458
		"50 Pin Dual Inline",
Packit a55458
		"68 Pin Dual Inline",
Packit a55458
		"On Board Sound Input From CD-ROM",
Packit a55458
		"Mini Centronics Type-14",
Packit a55458
		"Mini Centronics Type-26",
Packit a55458
		"Mini Jack (headphones)",
Packit a55458
		"BNC",
Packit a55458
		"IEEE 1394",
Packit a55458
		"SAS/SATA Plug Receptacle",
Packit a55458
		"USB Type-C Receptacle" /* 0x23 */
Packit a55458
	};
Packit a55458
	static const char *type_0xA0[] = {
Packit a55458
		"PC-98", /* 0xA0 */
Packit a55458
		"PC-98 Hireso",
Packit a55458
		"PC-H98",
Packit a55458
		"PC-98 Note",
Packit a55458
		"PC-98 Full" /* 0xA4 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code <= 0x23)
Packit a55458
		return type[code];
Packit a55458
	if (code >= 0xA0 && code <= 0xA4)
Packit a55458
		return type_0xA0[code - 0xA0];
Packit a55458
	if (code == 0xFF)
Packit a55458
		return "Other";
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_port_type(u8 code)
Packit a55458
{
Packit a55458
	/* 7.9.3 */
Packit a55458
	static const char *type[] = {
Packit a55458
		"None", /* 0x00 */
Packit a55458
		"Parallel Port XT/AT Compatible",
Packit a55458
		"Parallel Port PS/2",
Packit a55458
		"Parallel Port ECP",
Packit a55458
		"Parallel Port EPP",
Packit a55458
		"Parallel Port ECP/EPP",
Packit a55458
		"Serial Port XT/AT Compatible",
Packit a55458
		"Serial Port 16450 Compatible",
Packit a55458
		"Serial Port 16550 Compatible",
Packit a55458
		"Serial Port 16550A Compatible",
Packit a55458
		"SCSI Port",
Packit a55458
		"MIDI Port",
Packit a55458
		"Joystick Port",
Packit a55458
		"Keyboard Port",
Packit a55458
		"Mouse Port",
Packit a55458
		"SSA SCSI",
Packit a55458
		"USB",
Packit a55458
		"Firewire (IEEE P1394)",
Packit a55458
		"PCMCIA Type I",
Packit a55458
		"PCMCIA Type II",
Packit a55458
		"PCMCIA Type III",
Packit a55458
		"Cardbus",
Packit a55458
		"Access Bus Port",
Packit a55458
		"SCSI II",
Packit a55458
		"SCSI Wide",
Packit a55458
		"PC-98",
Packit a55458
		"PC-98 Hireso",
Packit a55458
		"PC-H98",
Packit a55458
		"Video Port",
Packit a55458
		"Audio Port",
Packit a55458
		"Modem Port",
Packit a55458
		"Network Port",
Packit a55458
		"SATA",
Packit a55458
		"SAS" /* 0x21 */
Packit a55458
	};
Packit a55458
	static const char *type_0xA0[] = {
Packit a55458
		"8251 Compatible", /* 0xA0 */
Packit a55458
		"8251 FIFO Compatible" /* 0xA1 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code <= 0x21)
Packit a55458
		return type[code];
Packit a55458
	if (code >= 0xA0 && code <= 0xA1)
Packit a55458
		return type_0xA0[code - 0xA0];
Packit a55458
	if (code == 0xFF)
Packit a55458
		return "Other";
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.10 System Slots (Type 9)
Packit a55458
 */
Packit a55458
Packit a55458
static const char *dmi_slot_type(u8 code)
Packit a55458
{
Packit a55458
	/* 7.10.1 */
Packit a55458
	static const char *type[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"ISA",
Packit a55458
		"MCA",
Packit a55458
		"EISA",
Packit a55458
		"PCI",
Packit a55458
		"PC Card (PCMCIA)",
Packit a55458
		"VLB",
Packit a55458
		"Proprietary",
Packit a55458
		"Processor Card",
Packit a55458
		"Proprietary Memory Card",
Packit a55458
		"I/O Riser Card",
Packit a55458
		"NuBus",
Packit a55458
		"PCI-66",
Packit a55458
		"AGP",
Packit a55458
		"AGP 2x",
Packit a55458
		"AGP 4x",
Packit a55458
		"PCI-X",
Packit a55458
		"AGP 8x",
Packit a55458
		"M.2 Socket 1-DP",
Packit a55458
		"M.2 Socket 1-SD",
Packit a55458
		"M.2 Socket 2",
Packit a55458
		"M.2 Socket 3",
Packit a55458
		"MXM Type I",
Packit a55458
		"MXM Type II",
Packit a55458
		"MXM Type III",
Packit a55458
		"MXM Type III-HE",
Packit a55458
		"MXM Type IV",
Packit a55458
		"MXM 3.0 Type A",
Packit a55458
		"MXM 3.0 Type B",
Packit a55458
		"PCI Express 2 SFF-8639",
Packit a55458
		"PCI Express 3 SFF-8639",
Packit a55458
		"PCI Express Mini 52-pin with bottom-side keep-outs",
Packit a55458
		"PCI Express Mini 52-pin without bottom-side keep-outs",
Packit a55458
		"PCI Express Mini 76-pin" /* 0x23 */
Packit a55458
	};
Packit a55458
	static const char *type_0xA0[] = {
Packit a55458
		"PC-98/C20", /* 0xA0 */
Packit a55458
		"PC-98/C24",
Packit a55458
		"PC-98/E",
Packit a55458
		"PC-98/Local Bus",
Packit a55458
		"PC-98/Card",
Packit a55458
		"PCI Express",
Packit a55458
		"PCI Express x1",
Packit a55458
		"PCI Express x2",
Packit a55458
		"PCI Express x4",
Packit a55458
		"PCI Express x8",
Packit a55458
		"PCI Express x16",
Packit a55458
		"PCI Express 2",
Packit a55458
		"PCI Express 2 x1",
Packit a55458
		"PCI Express 2 x2",
Packit a55458
		"PCI Express 2 x4",
Packit a55458
		"PCI Express 2 x8",
Packit a55458
		"PCI Express 2 x16",
Packit a55458
		"PCI Express 3",
Packit a55458
		"PCI Express 3 x1",
Packit a55458
		"PCI Express 3 x2",
Packit a55458
		"PCI Express 3 x4",
Packit a55458
		"PCI Express 3 x8",
Packit a55458
		"PCI Express 3 x16" /* 0xB6 */
Packit a55458
	};
Packit a55458
	/*
Packit a55458
	 * Note to developers: when adding entries to these lists, check if
Packit a55458
	 * function dmi_slot_id below needs updating too.
Packit a55458
	 */
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x23)
Packit a55458
		return type[code - 0x01];
Packit a55458
	if (code >= 0xA0 && code <= 0xB6)
Packit a55458
		return type_0xA0[code - 0xA0];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_slot_bus_width(u8 code)
Packit a55458
{
Packit a55458
	/* 7.10.2 */
Packit a55458
	static const char *width[] = {
Packit a55458
		"", /* 0x01, "Other" */
Packit a55458
		"", /* "Unknown" */
Packit a55458
		"8-bit ",
Packit a55458
		"16-bit ",
Packit a55458
		"32-bit ",
Packit a55458
		"64-bit ",
Packit a55458
		"128-bit ",
Packit a55458
		"x1 ",
Packit a55458
		"x2 ",
Packit a55458
		"x4 ",
Packit a55458
		"x8 ",
Packit a55458
		"x12 ",
Packit a55458
		"x16 ",
Packit a55458
		"x32 " /* 0x0E */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x0E)
Packit a55458
		return width[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_slot_current_usage(u8 code)
Packit a55458
{
Packit a55458
	/* 7.10.3 */
Packit a55458
	static const char *usage[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"Available",
Packit a55458
		"In Use",
Packit a55458
		"Unavailable" /* 0x05 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x05)
Packit a55458
		return usage[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_slot_length(u8 code)
Packit a55458
{
Packit a55458
	/* 7.1O.4 */
Packit a55458
	static const char *length[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"Short",
Packit a55458
		"Long" /* 0x04 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x04)
Packit a55458
		return length[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_slot_id(u8 code1, u8 code2, u8 type, const char *prefix)
Packit a55458
{
Packit a55458
	/* 7.10.5 */
Packit a55458
	switch (type)
Packit a55458
	{
Packit a55458
		case 0x04: /* MCA */
Packit a55458
			printf("%sID: %u\n", prefix, code1);
Packit a55458
			break;
Packit a55458
		case 0x05: /* EISA */
Packit a55458
			printf("%sID: %u\n", prefix, code1);
Packit a55458
			break;
Packit a55458
		case 0x06: /* PCI */
Packit a55458
		case 0x0E: /* PCI */
Packit a55458
		case 0x0F: /* AGP */
Packit a55458
		case 0x10: /* AGP */
Packit a55458
		case 0x11: /* AGP */
Packit a55458
		case 0x12: /* PCI-X */
Packit a55458
		case 0x13: /* AGP */
Packit a55458
		case 0x1F: /* PCI Express 2 */
Packit a55458
		case 0x20: /* PCI Express 3 */
Packit a55458
		case 0x21: /* PCI Express Mini */
Packit a55458
		case 0x22: /* PCI Express Mini */
Packit a55458
		case 0x23: /* PCI Express Mini */
Packit a55458
		case 0xA5: /* PCI Express */
Packit a55458
		case 0xA6: /* PCI Express */
Packit a55458
		case 0xA7: /* PCI Express */
Packit a55458
		case 0xA8: /* PCI Express */
Packit a55458
		case 0xA9: /* PCI Express */
Packit a55458
		case 0xAA: /* PCI Express */
Packit a55458
		case 0xAB: /* PCI Express 2 */
Packit a55458
		case 0xAC: /* PCI Express 2 */
Packit a55458
		case 0xAD: /* PCI Express 2 */
Packit a55458
		case 0xAE: /* PCI Express 2 */
Packit a55458
		case 0xAF: /* PCI Express 2 */
Packit a55458
		case 0xB0: /* PCI Express 2 */
Packit a55458
		case 0xB1: /* PCI Express 3 */
Packit a55458
		case 0xB2: /* PCI Express 3 */
Packit a55458
		case 0xB3: /* PCI Express 3 */
Packit a55458
		case 0xB4: /* PCI Express 3 */
Packit a55458
		case 0xB5: /* PCI Express 3 */
Packit a55458
		case 0xB6: /* PCI Express 3 */
Packit a55458
			printf("%sID: %u\n", prefix, code1);
Packit a55458
			break;
Packit a55458
		case 0x07: /* PCMCIA */
Packit a55458
			printf("%sID: Adapter %u, Socket %u\n", prefix, code1, code2);
Packit a55458
			break;
Packit a55458
	}
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_slot_characteristics(u8 code1, u8 code2, const char *prefix)
Packit a55458
{
Packit a55458
	/* 7.10.6 */
Packit a55458
	static const char *characteristics1[] = {
Packit a55458
		"5.0 V is provided", /* 1 */
Packit a55458
		"3.3 V is provided",
Packit a55458
		"Opening is shared",
Packit a55458
		"PC Card-16 is supported",
Packit a55458
		"Cardbus is supported",
Packit a55458
		"Zoom Video is supported",
Packit a55458
		"Modem ring resume is supported" /* 7 */
Packit a55458
	};
Packit a55458
	/* 7.10.7 */
Packit a55458
	static const char *characteristics2[] = {
Packit a55458
		"PME signal is supported", /* 0 */
Packit a55458
		"Hot-plug devices are supported",
Packit a55458
		"SMBus signal is supported",
Packit a55458
		"PCIe slot bifurcation is supported" /* 3 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code1 & (1 << 0))
Packit a55458
		printf(" Unknown\n");
Packit a55458
	else if ((code1 & 0xFE) == 0 && (code2 & 0x07) == 0)
Packit a55458
		printf(" None\n");
Packit a55458
	else
Packit a55458
	{
Packit a55458
		int i;
Packit a55458
Packit a55458
		printf("\n");
Packit a55458
		for (i = 1; i <= 7; i++)
Packit a55458
			if (code1 & (1 << i))
Packit a55458
				printf("%s%s\n", prefix, characteristics1[i - 1]);
Packit a55458
		for (i = 0; i <= 3; i++)
Packit a55458
			if (code2 & (1 << i))
Packit a55458
				printf("%s%s\n", prefix, characteristics2[i]);
Packit a55458
	}
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_slot_segment_bus_func(u16 code1, u8 code2, u8 code3, const char *prefix)
Packit a55458
{
Packit a55458
	/* 7.10.8 */
Packit a55458
	if (!(code1 == 0xFFFF && code2 == 0xFF && code3 == 0xFF))
Packit a55458
		printf("%sBus Address: %04x:%02x:%02x.%x\n",
Packit a55458
		       prefix, code1, code2, code3 >> 3, code3 & 0x7);
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.11 On Board Devices Information (Type 10)
Packit a55458
 */
Packit a55458
Packit a55458
static const char *dmi_on_board_devices_type(u8 code)
Packit a55458
{
Packit a55458
	/* 7.11.1 and 7.42.2 */
Packit a55458
	static const char *type[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"Video",
Packit a55458
		"SCSI Controller",
Packit a55458
		"Ethernet",
Packit a55458
		"Token Ring",
Packit a55458
		"Sound",
Packit a55458
		"PATA Controller",
Packit a55458
		"SATA Controller",
Packit a55458
		"SAS Controller" /* 0x0A */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x0A)
Packit a55458
		return type[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_on_board_devices(const struct dmi_header *h, const char *prefix)
Packit a55458
{
Packit a55458
	u8 *p = h->data + 4;
Packit a55458
	u8 count = (h->length - 0x04) / 2;
Packit a55458
	int i;
Packit a55458
Packit a55458
	for (i = 0; i < count; i++)
Packit a55458
	{
Packit a55458
		if (count == 1)
Packit a55458
			printf("%sOn Board Device Information\n",
Packit a55458
				prefix);
Packit a55458
		else
Packit a55458
			printf("%sOn Board Device %d Information\n",
Packit a55458
				prefix, i + 1);
Packit a55458
		printf("%s\tType: %s\n",
Packit a55458
			prefix, dmi_on_board_devices_type(p[2 * i] & 0x7F));
Packit a55458
		printf("%s\tStatus: %s\n",
Packit a55458
			prefix, p[2 * i] & 0x80 ? "Enabled" : "Disabled");
Packit a55458
		printf("%s\tDescription: %s\n",
Packit a55458
			prefix, dmi_string(h, p[2 * i + 1]));
Packit a55458
	}
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.12 OEM Strings (Type 11)
Packit a55458
 */
Packit a55458
Packit a55458
static void dmi_oem_strings(const struct dmi_header *h, const char *prefix)
Packit a55458
{
Packit a55458
	u8 *p = h->data + 4;
Packit a55458
	u8 count = p[0x00];
Packit a55458
	int i;
Packit a55458
Packit a55458
	for (i = 1; i <= count; i++)
Packit a55458
		printf("%sString %d: %s\n",
Packit a55458
			prefix, i, dmi_string(h, i));
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.13 System Configuration Options (Type 12)
Packit a55458
 */
Packit a55458
Packit a55458
static void dmi_system_configuration_options(const struct dmi_header *h, const char *prefix)
Packit a55458
{
Packit a55458
	u8 *p = h->data + 4;
Packit a55458
	u8 count = p[0x00];
Packit a55458
	int i;
Packit a55458
Packit a55458
	for (i = 1; i <= count; i++)
Packit a55458
		printf("%sOption %d: %s\n",
Packit a55458
			prefix, i, dmi_string(h, i));
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.14 BIOS Language Information (Type 13)
Packit a55458
 */
Packit a55458
Packit a55458
static void dmi_bios_languages(const struct dmi_header *h, const char *prefix)
Packit a55458
{
Packit a55458
	u8 *p = h->data + 4;
Packit a55458
	u8 count = p[0x00];
Packit a55458
	int i;
Packit a55458
Packit a55458
	for (i = 1; i <= count; i++)
Packit a55458
		printf("%s%s\n",
Packit a55458
			prefix, dmi_string(h, i));
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_bios_language_format(u8 code)
Packit a55458
{
Packit a55458
	if (code & 0x01)
Packit a55458
		return "Abbreviated";
Packit a55458
	else
Packit a55458
		return "Long";
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.15 Group Associations (Type 14)
Packit a55458
 */
Packit a55458
Packit a55458
static void dmi_group_associations_items(u8 count, const u8 *p, const char *prefix)
Packit a55458
{
Packit a55458
	int i;
Packit a55458
Packit a55458
	for (i = 0; i < count; i++)
Packit a55458
	{
Packit a55458
		printf("%s0x%04X (%s)\n",
Packit a55458
			prefix, WORD(p + 3 * i + 1),
Packit a55458
			dmi_smbios_structure_type(p[3 * i]));
Packit a55458
	}
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.16 System Event Log (Type 15)
Packit a55458
 */
Packit a55458
Packit a55458
static const char *dmi_event_log_method(u8 code)
Packit a55458
{
Packit a55458
	static const char *method[] = {
Packit a55458
		"Indexed I/O, one 8-bit index port, one 8-bit data port", /* 0x00 */
Packit a55458
		"Indexed I/O, two 8-bit index ports, one 8-bit data port",
Packit a55458
		"Indexed I/O, one 16-bit index port, one 8-bit data port",
Packit a55458
		"Memory-mapped physical 32-bit address",
Packit a55458
		"General-purpose non-volatile data functions" /* 0x04 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code <= 0x04)
Packit a55458
		return method[code];
Packit a55458
	if (code >= 0x80)
Packit a55458
		return "OEM-specific";
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_event_log_status(u8 code)
Packit a55458
{
Packit a55458
	static const char *valid[] = {
Packit a55458
		"Invalid", /* 0 */
Packit a55458
		"Valid" /* 1 */
Packit a55458
	};
Packit a55458
	static const char *full[] = {
Packit a55458
		"Not Full", /* 0 */
Packit a55458
		"Full" /* 1 */
Packit a55458
	};
Packit a55458
Packit a55458
	printf(" %s, %s",
Packit a55458
		valid[(code >> 0) & 1], full[(code >> 1) & 1]);
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_event_log_address(u8 method, const u8 *p)
Packit a55458
{
Packit a55458
	/* 7.16.3 */
Packit a55458
	switch (method)
Packit a55458
	{
Packit a55458
		case 0x00:
Packit a55458
		case 0x01:
Packit a55458
		case 0x02:
Packit a55458
			printf(" Index 0x%04X, Data 0x%04X", WORD(p), WORD(p + 2));
Packit a55458
			break;
Packit a55458
		case 0x03:
Packit a55458
			printf(" 0x%08X", DWORD(p));
Packit a55458
			break;
Packit a55458
		case 0x04:
Packit a55458
			printf(" 0x%04X", WORD(p));
Packit a55458
			break;
Packit a55458
		default:
Packit a55458
			printf(" Unknown");
Packit a55458
	}
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_event_log_header_type(u8 code)
Packit a55458
{
Packit a55458
	static const char *type[] = {
Packit a55458
		"No Header", /* 0x00 */
Packit a55458
		"Type 1" /* 0x01 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code <= 0x01)
Packit a55458
		return type[code];
Packit a55458
	if (code >= 0x80)
Packit a55458
		return "OEM-specific";
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_event_log_descriptor_type(u8 code)
Packit a55458
{
Packit a55458
	/* 7.16.6.1 */
Packit a55458
	static const char *type[] = {
Packit a55458
		NULL, /* 0x00 */
Packit a55458
		"Single-bit ECC memory error",
Packit a55458
		"Multi-bit ECC memory error",
Packit a55458
		"Parity memory error",
Packit a55458
		"Bus timeout",
Packit a55458
		"I/O channel block",
Packit a55458
		"Software NMI",
Packit a55458
		"POST memory resize",
Packit a55458
		"POST error",
Packit a55458
		"PCI parity error",
Packit a55458
		"PCI system error",
Packit a55458
		"CPU failure",
Packit a55458
		"EISA failsafe timer timeout",
Packit a55458
		"Correctable memory log disabled",
Packit a55458
		"Logging disabled",
Packit a55458
		NULL, /* 0x0F */
Packit a55458
		"System limit exceeded",
Packit a55458
		"Asynchronous hardware timer expired",
Packit a55458
		"System configuration information",
Packit a55458
		"Hard disk information",
Packit a55458
		"System reconfigured",
Packit a55458
		"Uncorrectable CPU-complex error",
Packit a55458
		"Log area reset/cleared",
Packit a55458
		"System boot" /* 0x17 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code <= 0x17 && type[code] != NULL)
Packit a55458
		return type[code];
Packit a55458
	if (code >= 0x80 && code <= 0xFE)
Packit a55458
		return "OEM-specific";
Packit a55458
	if (code == 0xFF)
Packit a55458
		return "End of log";
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_event_log_descriptor_format(u8 code)
Packit a55458
{
Packit a55458
	/* 7.16.6.2 */
Packit a55458
	static const char *format[] = {
Packit a55458
		"None", /* 0x00 */
Packit a55458
		"Handle",
Packit a55458
		"Multiple-event",
Packit a55458
		"Multiple-event handle",
Packit a55458
		"POST results bitmap",
Packit a55458
		"System management",
Packit a55458
		"Multiple-event system management" /* 0x06 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code <= 0x06)
Packit a55458
		return format[code];
Packit a55458
	if (code >= 0x80)
Packit a55458
		return "OEM-specific";
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_event_log_descriptors(u8 count, u8 len, const u8 *p, const char *prefix)
Packit a55458
{
Packit a55458
	/* 7.16.1 */
Packit a55458
	int i;
Packit a55458
Packit a55458
	for (i = 0; i < count; i++)
Packit a55458
	{
Packit a55458
		if (len >= 0x02)
Packit a55458
		{
Packit a55458
			printf("%sDescriptor %u: %s\n",
Packit a55458
				prefix, i + 1, dmi_event_log_descriptor_type(p[i * len]));
Packit a55458
			printf("%sData Format %u: %s\n",
Packit a55458
				prefix, i + 1, dmi_event_log_descriptor_format(p[i * len + 1]));
Packit a55458
		}
Packit a55458
	}
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.17 Physical Memory Array (Type 16)
Packit a55458
 */
Packit a55458
Packit a55458
static const char *dmi_memory_array_location(u8 code)
Packit a55458
{
Packit a55458
	/* 7.17.1 */
Packit a55458
	static const char *location[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"System Board Or Motherboard",
Packit a55458
		"ISA Add-on Card",
Packit a55458
		"EISA Add-on Card",
Packit a55458
		"PCI Add-on Card",
Packit a55458
		"MCA Add-on Card",
Packit a55458
		"PCMCIA Add-on Card",
Packit a55458
		"Proprietary Add-on Card",
Packit a55458
		"NuBus" /* 0x0A */
Packit a55458
	};
Packit a55458
	static const char *location_0xA0[] = {
Packit a55458
		"PC-98/C20 Add-on Card", /* 0xA0 */
Packit a55458
		"PC-98/C24 Add-on Card",
Packit a55458
		"PC-98/E Add-on Card",
Packit a55458
		"PC-98/Local Bus Add-on Card" /* 0xA3 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x0A)
Packit a55458
		return location[code - 0x01];
Packit a55458
	if (code >= 0xA0 && code <= 0xA3)
Packit a55458
		return location_0xA0[code - 0xA0];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_memory_array_use(u8 code)
Packit a55458
{
Packit a55458
	/* 7.17.2 */
Packit a55458
	static const char *use[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"System Memory",
Packit a55458
		"Video Memory",
Packit a55458
		"Flash Memory",
Packit a55458
		"Non-volatile RAM",
Packit a55458
		"Cache Memory" /* 0x07 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x07)
Packit a55458
		return use[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_memory_array_ec_type(u8 code)
Packit a55458
{
Packit a55458
	/* 7.17.3 */
Packit a55458
	static const char *type[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"None",
Packit a55458
		"Parity",
Packit a55458
		"Single-bit ECC",
Packit a55458
		"Multi-bit ECC",
Packit a55458
		"CRC" /* 0x07 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x07)
Packit a55458
		return type[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_memory_array_error_handle(u16 code)
Packit a55458
{
Packit a55458
	if (code == 0xFFFE)
Packit a55458
		printf(" Not Provided");
Packit a55458
	else if (code == 0xFFFF)
Packit a55458
		printf(" No Error");
Packit a55458
	else
Packit a55458
		printf(" 0x%04X", code);
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.18 Memory Device (Type 17)
Packit a55458
 */
Packit a55458
Packit a55458
static void dmi_memory_device_width(u16 code)
Packit a55458
{
Packit a55458
	/*
Packit a55458
	 * If no memory module is present, width may be 0
Packit a55458
	 */
Packit a55458
	if (code == 0xFFFF || code == 0)
Packit a55458
		printf(" Unknown");
Packit a55458
	else
Packit a55458
		printf(" %u bits", code);
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_memory_device_size(u16 code)
Packit a55458
{
Packit a55458
	if (code == 0)
Packit a55458
		printf(" No Module Installed");
Packit a55458
	else if (code == 0xFFFF)
Packit a55458
		printf(" Unknown");
Packit a55458
	else
Packit a55458
	{
Packit a55458
		if (code & 0x8000)
Packit a55458
			printf(" %u kB", code & 0x7FFF);
Packit a55458
		else
Packit a55458
			printf(" %u MB", code);
Packit a55458
	}
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_memory_device_extended_size(u32 code)
Packit a55458
{
Packit a55458
	code &= 0x7FFFFFFFUL;
Packit a55458
Packit a55458
	/*
Packit a55458
	 * Use the greatest unit for which the exact value can be displayed
Packit a55458
	 * as an integer without rounding
Packit a55458
	 */
Packit a55458
	if (code & 0x3FFUL)
Packit a55458
		printf(" %lu MB", (unsigned long)code);
Packit a55458
	else if (code & 0xFFC00UL)
Packit a55458
		printf(" %lu GB", (unsigned long)code >> 10);
Packit a55458
	else
Packit a55458
		printf(" %lu TB", (unsigned long)code >> 20);
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_memory_voltage_value(u16 code)
Packit a55458
{
Packit a55458
	if (code == 0)
Packit a55458
		printf(" Unknown");
Packit a55458
	else
Packit a55458
		printf(code % 100 ? " %g V" : " %.1f V", (float)code / 1000);
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_memory_device_form_factor(u8 code)
Packit a55458
{
Packit a55458
	/* 7.18.1 */
Packit a55458
	static const char *form_factor[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"SIMM",
Packit a55458
		"SIP",
Packit a55458
		"Chip",
Packit a55458
		"DIP",
Packit a55458
		"ZIP",
Packit a55458
		"Proprietary Card",
Packit a55458
		"DIMM",
Packit a55458
		"TSOP",
Packit a55458
		"Row Of Chips",
Packit a55458
		"RIMM",
Packit a55458
		"SODIMM",
Packit a55458
		"SRIMM",
Packit a55458
		"FB-DIMM" /* 0x0F */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x0F)
Packit a55458
		return form_factor[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_memory_device_set(u8 code)
Packit a55458
{
Packit a55458
	if (code == 0)
Packit a55458
		printf(" None");
Packit a55458
	else if (code == 0xFF)
Packit a55458
		printf(" Unknown");
Packit a55458
	else
Packit a55458
		printf(" %u", code);
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_memory_device_type(u8 code)
Packit a55458
{
Packit a55458
	/* 7.18.2 */
Packit a55458
	static const char *type[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"DRAM",
Packit a55458
		"EDRAM",
Packit a55458
		"VRAM",
Packit a55458
		"SRAM",
Packit a55458
		"RAM",
Packit a55458
		"ROM",
Packit a55458
		"Flash",
Packit a55458
		"EEPROM",
Packit a55458
		"FEPROM",
Packit a55458
		"EPROM",
Packit a55458
		"CDRAM",
Packit a55458
		"3DRAM",
Packit a55458
		"SDRAM",
Packit a55458
		"SGRAM",
Packit a55458
		"RDRAM",
Packit a55458
		"DDR",
Packit a55458
		"DDR2",
Packit a55458
		"DDR2 FB-DIMM",
Packit a55458
		"Reserved",
Packit a55458
		"Reserved",
Packit a55458
		"Reserved",
Packit a55458
		"DDR3",
Packit a55458
		"FBD2",
Packit a55458
		"DDR4",
Packit a55458
		"LPDDR",
Packit a55458
		"LPDDR2",
Packit a55458
		"LPDDR3",
Packit a55458
		"LPDDR4" /* 0x1E */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x1E)
Packit a55458
		return type[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_memory_device_type_detail(u16 code)
Packit a55458
{
Packit a55458
	/* 7.18.3 */
Packit a55458
	static const char *detail[] = {
Packit a55458
		"Other", /* 1 */
Packit a55458
		"Unknown",
Packit a55458
		"Fast-paged",
Packit a55458
		"Static Column",
Packit a55458
		"Pseudo-static",
Packit a55458
		"RAMBus",
Packit a55458
		"Synchronous",
Packit a55458
		"CMOS",
Packit a55458
		"EDO",
Packit a55458
		"Window DRAM",
Packit a55458
		"Cache DRAM",
Packit a55458
		"Non-Volatile",
Packit a55458
		"Registered (Buffered)",
Packit a55458
		"Unbuffered (Unregistered)",
Packit a55458
		"LRDIMM"  /* 15 */
Packit a55458
	};
Packit a55458
Packit a55458
	if ((code & 0xFFFE) == 0)
Packit a55458
		printf(" None");
Packit a55458
	else
Packit a55458
	{
Packit a55458
		int i;
Packit a55458
Packit a55458
		for (i = 1; i <= 15; i++)
Packit a55458
			if (code & (1 << i))
Packit a55458
				printf(" %s", detail[i - 1]);
Packit a55458
	}
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_memory_device_speed(u16 code)
Packit a55458
{
Packit a55458
	if (code == 0)
Packit a55458
		printf(" Unknown");
Packit a55458
	else
Packit a55458
		printf(" %u MT/s", code);
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_memory_technology(u8 code)
Packit a55458
{
Packit a55458
	/* 7.18.6 */
Packit a55458
	static const char * const technology[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"DRAM",
Packit a55458
		"NVDIMM-N",
Packit a55458
		"NVDIMM-F",
Packit a55458
		"NVDIMM-P",
Packit a55458
		"Intel persistent memory" /* 0x07 */
Packit a55458
	};
Packit a55458
	if (code >= 0x01 && code <= 0x07)
Packit a55458
		printf(" %s", technology[code - 0x01]);
Packit a55458
	else
Packit a55458
		printf(" %s", out_of_spec);
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_memory_operating_mode_capability(u16 code)
Packit a55458
{
Packit a55458
	/* 7.18.7 */
Packit a55458
	static const char * const mode[] = {
Packit a55458
		"Other", /* 1 */
Packit a55458
		"Unknown",
Packit a55458
		"Volatile memory",
Packit a55458
		"Byte-accessible persistent memory",
Packit a55458
		"Block-accessible persistent memory" /* 5 */
Packit a55458
	};
Packit a55458
Packit a55458
	if ((code & 0xFFFE) == 0)
Packit a55458
		printf(" None");
Packit a55458
	else {
Packit a55458
		int i;
Packit a55458
Packit a55458
		for (i = 1; i <= 5; i++)
Packit a55458
			if (code & (1 << i))
Packit a55458
				printf(" %s", mode[i - 1]);
Packit a55458
	}
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_memory_manufacturer_id(u16 code)
Packit a55458
{
Packit a55458
	/* 7.18.8 */
Packit a55458
	/* 7.18.10 */
Packit a55458
	/* LSB is 7-bit Odd Parity number of continuation codes */
Packit a55458
	if (code == 0)
Packit a55458
		printf(" Unknown");
Packit a55458
	else
Packit a55458
		printf(" Bank %d, Hex 0x%02X", (code & 0x7F) + 1, code >> 8);
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_memory_product_id(u16 code)
Packit a55458
{
Packit a55458
	/* 7.18.9 */
Packit a55458
	/* 7.18.11 */
Packit a55458
	if (code == 0)
Packit a55458
		printf(" Unknown");
Packit a55458
	else
Packit a55458
		printf(" 0x%04X", code);
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_memory_size(u64 code)
Packit a55458
{
Packit a55458
	/* 7.18.12 */
Packit a55458
	/* 7.18.13 */
Packit a55458
	if (code.h == 0xFFFFFFFF && code.l == 0xFFFFFFFF)
Packit a55458
		printf(" Unknown");
Packit a55458
	else if (code.h == 0x0 && code.l == 0x0)
Packit a55458
		printf(" None");
Packit a55458
	else
Packit a55458
		dmi_print_memory_size(code, 0);
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.19 32-bit Memory Error Information (Type 18)
Packit a55458
 */
Packit a55458
Packit a55458
static const char *dmi_memory_error_type(u8 code)
Packit a55458
{
Packit a55458
	/* 7.19.1 */
Packit a55458
	static const char *type[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"OK",
Packit a55458
		"Bad Read",
Packit a55458
		"Parity Error",
Packit a55458
		"Single-bit Error",
Packit a55458
		"Double-bit Error",
Packit a55458
		"Multi-bit Error",
Packit a55458
		"Nibble Error",
Packit a55458
		"Checksum Error",
Packit a55458
		"CRC Error",
Packit a55458
		"Corrected Single-bit Error",
Packit a55458
		"Corrected Error",
Packit a55458
		"Uncorrectable Error" /* 0x0E */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x0E)
Packit a55458
		return type[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_memory_error_granularity(u8 code)
Packit a55458
{
Packit a55458
	/* 7.19.2 */
Packit a55458
	static const char *granularity[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"Device Level",
Packit a55458
		"Memory Partition Level" /* 0x04 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x04)
Packit a55458
		return granularity[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_memory_error_operation(u8 code)
Packit a55458
{
Packit a55458
	/* 7.19.3 */
Packit a55458
	static const char *operation[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"Read",
Packit a55458
		"Write",
Packit a55458
		"Partial Write" /* 0x05 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x05)
Packit a55458
		return operation[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_memory_error_syndrome(u32 code)
Packit a55458
{
Packit a55458
	if (code == 0x00000000)
Packit a55458
		printf(" Unknown");
Packit a55458
	else
Packit a55458
		printf(" 0x%08X", code);
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_32bit_memory_error_address(u32 code)
Packit a55458
{
Packit a55458
	if (code == 0x80000000)
Packit a55458
		printf(" Unknown");
Packit a55458
	else
Packit a55458
		printf(" 0x%08X", code);
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.20 Memory Array Mapped Address (Type 19)
Packit a55458
 */
Packit a55458
Packit a55458
static void dmi_mapped_address_size(u32 code)
Packit a55458
{
Packit a55458
	if (code == 0)
Packit a55458
		printf(" Invalid");
Packit a55458
	else
Packit a55458
	{
Packit a55458
		u64 size;
Packit a55458
Packit a55458
		size.h = 0;
Packit a55458
		size.l = code;
Packit a55458
		dmi_print_memory_size(size, 1);
Packit a55458
	}
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_mapped_address_extended_size(u64 start, u64 end)
Packit a55458
{
Packit a55458
	if (start.h == end.h && start.l == end.l)
Packit a55458
		printf(" Invalid");
Packit a55458
	else
Packit a55458
		dmi_print_memory_size(u64_range(start, end), 0);
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.21 Memory Device Mapped Address (Type 20)
Packit a55458
 */
Packit a55458
Packit a55458
static void dmi_mapped_address_row_position(u8 code)
Packit a55458
{
Packit a55458
	if (code == 0)
Packit a55458
		printf(" %s", out_of_spec);
Packit a55458
	else if (code == 0xFF)
Packit a55458
		printf(" Unknown");
Packit a55458
	else
Packit a55458
		printf(" %u", code);
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_mapped_address_interleave_position(u8 code, const char *prefix)
Packit a55458
{
Packit a55458
	if (code != 0)
Packit a55458
	{
Packit a55458
		printf("%sInterleave Position:", prefix);
Packit a55458
		if (code == 0xFF)
Packit a55458
			printf(" Unknown");
Packit a55458
		else
Packit a55458
			printf(" %u", code);
Packit a55458
		printf("\n");
Packit a55458
	}
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_mapped_address_interleaved_data_depth(u8 code, const char *prefix)
Packit a55458
{
Packit a55458
	if (code != 0)
Packit a55458
	{
Packit a55458
		printf("%sInterleaved Data Depth:", prefix);
Packit a55458
		if (code == 0xFF)
Packit a55458
			printf(" Unknown");
Packit a55458
		else
Packit a55458
			printf(" %u", code);
Packit a55458
		printf("\n");
Packit a55458
	}
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.22 Built-in Pointing Device (Type 21)
Packit a55458
 */
Packit a55458
Packit a55458
static const char *dmi_pointing_device_type(u8 code)
Packit a55458
{
Packit a55458
	/* 7.22.1 */
Packit a55458
	static const char *type[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"Mouse",
Packit a55458
		"Track Ball",
Packit a55458
		"Track Point",
Packit a55458
		"Glide Point",
Packit a55458
		"Touch Pad",
Packit a55458
		"Touch Screen",
Packit a55458
		"Optical Sensor" /* 0x09 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x09)
Packit a55458
		return type[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_pointing_device_interface(u8 code)
Packit a55458
{
Packit a55458
	/* 7.22.2 */
Packit a55458
	static const char *interface[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"Serial",
Packit a55458
		"PS/2",
Packit a55458
		"Infrared",
Packit a55458
		"HIP-HIL",
Packit a55458
		"Bus Mouse",
Packit a55458
		"ADB (Apple Desktop Bus)" /* 0x08 */
Packit a55458
	};
Packit a55458
	static const char *interface_0xA0[] = {
Packit a55458
		"Bus Mouse DB-9", /* 0xA0 */
Packit a55458
		"Bus Mouse Micro DIN",
Packit a55458
		"USB" /* 0xA2 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x08)
Packit a55458
		return interface[code - 0x01];
Packit a55458
	if (code >= 0xA0 && code <= 0xA2)
Packit a55458
		return interface_0xA0[code - 0xA0];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.23 Portable Battery (Type 22)
Packit a55458
 */
Packit a55458
Packit a55458
static const char *dmi_battery_chemistry(u8 code)
Packit a55458
{
Packit a55458
	/* 7.23.1 */
Packit a55458
	static const char *chemistry[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"Lead Acid",
Packit a55458
		"Nickel Cadmium",
Packit a55458
		"Nickel Metal Hydride",
Packit a55458
		"Lithium Ion",
Packit a55458
		"Zinc Air",
Packit a55458
		"Lithium Polymer" /* 0x08 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x08)
Packit a55458
		return chemistry[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_battery_capacity(u16 code, u8 multiplier)
Packit a55458
{
Packit a55458
	if (code == 0)
Packit a55458
		printf(" Unknown");
Packit a55458
	else
Packit a55458
		printf(" %u mWh", code * multiplier);
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_battery_voltage(u16 code)
Packit a55458
{
Packit a55458
	if (code == 0)
Packit a55458
		printf(" Unknown");
Packit a55458
	else
Packit a55458
		printf(" %u mV", code);
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_battery_maximum_error(u8 code)
Packit a55458
{
Packit a55458
	if (code == 0xFF)
Packit a55458
		printf(" Unknown");
Packit a55458
	else
Packit a55458
		printf(" %u%%", code);
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.24 System Reset (Type 23)
Packit a55458
 */
Packit a55458
Packit a55458
/* code is assumed to be a 2-bit value */
Packit a55458
static const char *dmi_system_reset_boot_option(u8 code)
Packit a55458
{
Packit a55458
	static const char *option[] = {
Packit a55458
		out_of_spec, /* 0x0 */
Packit a55458
		"Operating System", /* 0x1 */
Packit a55458
		"System Utilities",
Packit a55458
		"Do Not Reboot" /* 0x3 */
Packit a55458
	};
Packit a55458
Packit a55458
	return option[code];
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_system_reset_count(u16 code)
Packit a55458
{
Packit a55458
	if (code == 0xFFFF)
Packit a55458
		printf(" Unknown");
Packit a55458
	else
Packit a55458
		printf(" %u", code);
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_system_reset_timer(u16 code)
Packit a55458
{
Packit a55458
	if (code == 0xFFFF)
Packit a55458
		printf(" Unknown");
Packit a55458
	else
Packit a55458
		printf(" %u min", code);
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.25 Hardware Security (Type 24)
Packit a55458
 */
Packit a55458
Packit a55458
static const char *dmi_hardware_security_status(u8 code)
Packit a55458
{
Packit a55458
	static const char *status[] = {
Packit a55458
		"Disabled", /* 0x00 */
Packit a55458
		"Enabled",
Packit a55458
		"Not Implemented",
Packit a55458
		"Unknown" /* 0x03 */
Packit a55458
	};
Packit a55458
Packit a55458
	return status[code];
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.26 System Power Controls (Type 25)
Packit a55458
 */
Packit a55458
Packit a55458
static void dmi_power_controls_power_on(const u8 *p)
Packit a55458
{
Packit a55458
	/* 7.26.1 */
Packit a55458
	if (dmi_bcd_range(p[0], 0x01, 0x12))
Packit a55458
		printf(" %02X", p[0]);
Packit a55458
	else
Packit a55458
		printf(" *");
Packit a55458
	if (dmi_bcd_range(p[1], 0x01, 0x31))
Packit a55458
		printf("-%02X", p[1]);
Packit a55458
	else
Packit a55458
		printf("-*");
Packit a55458
	if (dmi_bcd_range(p[2], 0x00, 0x23))
Packit a55458
		printf(" %02X", p[2]);
Packit a55458
	else
Packit a55458
		printf(" *");
Packit a55458
	if (dmi_bcd_range(p[3], 0x00, 0x59))
Packit a55458
		printf(":%02X", p[3]);
Packit a55458
	else
Packit a55458
		printf(":*");
Packit a55458
	if (dmi_bcd_range(p[4], 0x00, 0x59))
Packit a55458
		printf(":%02X", p[4]);
Packit a55458
	else
Packit a55458
		printf(":*");
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.27 Voltage Probe (Type 26)
Packit a55458
 */
Packit a55458
Packit a55458
static const char *dmi_voltage_probe_location(u8 code)
Packit a55458
{
Packit a55458
	/* 7.27.1 */
Packit a55458
	static const char *location[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"Processor",
Packit a55458
		"Disk",
Packit a55458
		"Peripheral Bay",
Packit a55458
		"System Management Module",
Packit a55458
		"Motherboard",
Packit a55458
		"Memory Module",
Packit a55458
		"Processor Module",
Packit a55458
		"Power Unit",
Packit a55458
		"Add-in Card" /* 0x0B */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x0B)
Packit a55458
		return location[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_probe_status(u8 code)
Packit a55458
{
Packit a55458
	/* 7.27.1 */
Packit a55458
	static const char *status[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"OK",
Packit a55458
		"Non-critical",
Packit a55458
		"Critical",
Packit a55458
		"Non-recoverable" /* 0x06 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x06)
Packit a55458
		return status[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_voltage_probe_value(u16 code)
Packit a55458
{
Packit a55458
	if (code == 0x8000)
Packit a55458
		printf(" Unknown");
Packit a55458
	else
Packit a55458
		printf(" %.3f V", (float)(i16)code / 1000);
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_voltage_probe_resolution(u16 code)
Packit a55458
{
Packit a55458
	if (code == 0x8000)
Packit a55458
		printf(" Unknown");
Packit a55458
	else
Packit a55458
		printf(" %.1f mV", (float)code / 10);
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_probe_accuracy(u16 code)
Packit a55458
{
Packit a55458
	if (code == 0x8000)
Packit a55458
		printf(" Unknown");
Packit a55458
	else
Packit a55458
		printf(" %.2f%%", (float)code / 100);
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.28 Cooling Device (Type 27)
Packit a55458
 */
Packit a55458
Packit a55458
static const char *dmi_cooling_device_type(u8 code)
Packit a55458
{
Packit a55458
	/* 7.28.1 */
Packit a55458
	static const char *type[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"Fan",
Packit a55458
		"Centrifugal Blower",
Packit a55458
		"Chip Fan",
Packit a55458
		"Cabinet Fan",
Packit a55458
		"Power Supply Fan",
Packit a55458
		"Heat Pipe",
Packit a55458
		"Integrated Refrigeration" /* 0x09 */
Packit a55458
	};
Packit a55458
	static const char *type_0x10[] = {
Packit a55458
		"Active Cooling", /* 0x10 */
Packit a55458
		"Passive Cooling" /* 0x11 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x09)
Packit a55458
		return type[code - 0x01];
Packit a55458
	if (code >= 0x10 && code <= 0x11)
Packit a55458
		return type_0x10[code - 0x10];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_cooling_device_speed(u16 code)
Packit a55458
{
Packit a55458
	if (code == 0x8000)
Packit a55458
		printf(" Unknown Or Non-rotating");
Packit a55458
	else
Packit a55458
		printf(" %u rpm", code);
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.29 Temperature Probe (Type 28)
Packit a55458
 */
Packit a55458
Packit a55458
static const char *dmi_temperature_probe_location(u8 code)
Packit a55458
{
Packit a55458
	/* 7.29.1 */
Packit a55458
	static const char *location[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"Processor",
Packit a55458
		"Disk",
Packit a55458
		"Peripheral Bay",
Packit a55458
		"System Management Module",
Packit a55458
		"Motherboard",
Packit a55458
		"Memory Module",
Packit a55458
		"Processor Module",
Packit a55458
		"Power Unit",
Packit a55458
		"Add-in Card",
Packit a55458
		"Front Panel Board",
Packit a55458
		"Back Panel Board",
Packit a55458
		"Power System Board",
Packit a55458
		"Drive Back Plane" /* 0x0F */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x0F)
Packit a55458
		return location[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_temperature_probe_value(u16 code)
Packit a55458
{
Packit a55458
	if (code == 0x8000)
Packit a55458
		printf(" Unknown");
Packit a55458
	else
Packit a55458
		printf(" %.1f deg C", (float)(i16)code / 10);
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_temperature_probe_resolution(u16 code)
Packit a55458
{
Packit a55458
	if (code == 0x8000)
Packit a55458
		printf(" Unknown");
Packit a55458
	else
Packit a55458
		printf(" %.3f deg C", (float)code / 1000);
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.30 Electrical Current Probe (Type 29)
Packit a55458
 */
Packit a55458
Packit a55458
static void dmi_current_probe_value(u16 code)
Packit a55458
{
Packit a55458
	if (code == 0x8000)
Packit a55458
		printf(" Unknown");
Packit a55458
	else
Packit a55458
		printf(" %.3f A", (float)(i16)code / 1000);
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_current_probe_resolution(u16 code)
Packit a55458
{
Packit a55458
	if (code == 0x8000)
Packit a55458
		printf(" Unknown");
Packit a55458
	else
Packit a55458
		printf(" %.1f mA", (float)code / 10);
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.33 System Boot Information (Type 32)
Packit a55458
 */
Packit a55458
Packit a55458
static const char *dmi_system_boot_status(u8 code)
Packit a55458
{
Packit a55458
	static const char *status[] = {
Packit a55458
		"No errors detected", /* 0 */
Packit a55458
		"No bootable media",
Packit a55458
		"Operating system failed to load",
Packit a55458
		"Firmware-detected hardware failure",
Packit a55458
		"Operating system-detected hardware failure",
Packit a55458
		"User-requested boot",
Packit a55458
		"System security violation",
Packit a55458
		"Previously-requested image",
Packit a55458
		"System watchdog timer expired" /* 8 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code <= 8)
Packit a55458
		return status[code];
Packit a55458
	if (code >= 128 && code <= 191)
Packit a55458
		return "OEM-specific";
Packit a55458
	if (code >= 192)
Packit a55458
		return "Product-specific";
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.34 64-bit Memory Error Information (Type 33)
Packit a55458
 */
Packit a55458
Packit a55458
static void dmi_64bit_memory_error_address(u64 code)
Packit a55458
{
Packit a55458
	if (code.h == 0x80000000 && code.l == 0x00000000)
Packit a55458
		printf(" Unknown");
Packit a55458
	else
Packit a55458
		printf(" 0x%08X%08X", code.h, code.l);
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.35 Management Device (Type 34)
Packit a55458
 */
Packit a55458
Packit a55458
/*
Packit a55458
 * Several boards have a bug where some type 34 structures have their
Packit a55458
 * length incorrectly set to 0x10 instead of 0x0B. This causes the
Packit a55458
 * first 5 characters of the device name to be trimmed. It's easy to
Packit a55458
 * check and fix, so do it, but warn.
Packit a55458
 */
Packit a55458
static void dmi_fixup_type_34(struct dmi_header *h, int display)
Packit a55458
{
Packit a55458
	u8 *p = h->data;
Packit a55458
Packit a55458
 	/* Make sure the hidden data is ASCII only */
Packit a55458
	if (h->length == 0x10
Packit a55458
	 && is_printable(p + 0x0B, 0x10 - 0x0B))
Packit a55458
	{
Packit a55458
		if (!(opt.flags & FLAG_QUIET) && display)
Packit a55458
			fprintf(stderr,
Packit a55458
				"Invalid entry length (%u). Fixed up to %u.\n",
Packit a55458
				0x10, 0x0B);
Packit a55458
		h->length = 0x0B;
Packit a55458
	}
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_management_device_type(u8 code)
Packit a55458
{
Packit a55458
	/* 7.35.1 */
Packit a55458
	static const char *type[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"LM75",
Packit a55458
		"LM78",
Packit a55458
		"LM79",
Packit a55458
		"LM80",
Packit a55458
		"LM81",
Packit a55458
		"ADM9240",
Packit a55458
		"DS1780",
Packit a55458
		"MAX1617",
Packit a55458
		"GL518SM",
Packit a55458
		"W83781D",
Packit a55458
		"HT82H791" /* 0x0D */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x0D)
Packit a55458
		return type[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_management_device_address_type(u8 code)
Packit a55458
{
Packit a55458
	/* 7.35.2 */
Packit a55458
	static const char *type[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"I/O Port",
Packit a55458
		"Memory",
Packit a55458
		"SMBus" /* 0x05 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x05)
Packit a55458
		return type[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.38 Memory Channel (Type 37)
Packit a55458
 */
Packit a55458
Packit a55458
static const char *dmi_memory_channel_type(u8 code)
Packit a55458
{
Packit a55458
	/* 7.38.1 */
Packit a55458
	static const char *type[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"RamBus",
Packit a55458
		"SyncLink" /* 0x04 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x04)
Packit a55458
		return type[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_memory_channel_devices(u8 count, const u8 *p, const char *prefix)
Packit a55458
{
Packit a55458
	int i;
Packit a55458
Packit a55458
	for (i = 1; i <= count; i++)
Packit a55458
	{
Packit a55458
		printf("%sDevice %u Load: %u\n",
Packit a55458
			prefix, i, p[3 * i]);
Packit a55458
		if (!(opt.flags & FLAG_QUIET))
Packit a55458
			printf("%sDevice %u Handle: 0x%04X\n",
Packit a55458
				prefix, i, WORD(p + 3 * i + 1));
Packit a55458
	}
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.39 IPMI Device Information (Type 38)
Packit a55458
 */
Packit a55458
Packit a55458
static const char *dmi_ipmi_interface_type(u8 code)
Packit a55458
{
Packit a55458
	/* 7.39.1 and IPMI 2.0, appendix C1, table C1-2 */
Packit a55458
	static const char *type[] = {
Packit a55458
		"Unknown", /* 0x00 */
Packit a55458
		"KCS (Keyboard Control Style)",
Packit a55458
		"SMIC (Server Management Interface Chip)",
Packit a55458
		"BT (Block Transfer)",
Packit a55458
		"SSIF (SMBus System Interface)" /* 0x04 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code <= 0x04)
Packit a55458
		return type[code];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static void dmi_ipmi_base_address(u8 type, const u8 *p, u8 lsb)
Packit a55458
{
Packit a55458
	if (type == 0x04) /* SSIF */
Packit a55458
	{
Packit a55458
		printf("0x%02X (SMBus)", (*p) >> 1);
Packit a55458
	}
Packit a55458
	else
Packit a55458
	{
Packit a55458
		u64 address = QWORD(p);
Packit a55458
		printf("0x%08X%08X (%s)", address.h, (address.l & ~1) | lsb,
Packit a55458
			address.l & 1 ? "I/O" : "Memory-mapped");
Packit a55458
	}
Packit a55458
}
Packit a55458
Packit a55458
/* code is assumed to be a 2-bit value */
Packit a55458
static const char *dmi_ipmi_register_spacing(u8 code)
Packit a55458
{
Packit a55458
	/* IPMI 2.0, appendix C1, table C1-1 */
Packit a55458
	static const char *spacing[] = {
Packit a55458
		"Successive Byte Boundaries", /* 0x00 */
Packit a55458
		"32-bit Boundaries",
Packit a55458
		"16-byte Boundaries", /* 0x02 */
Packit a55458
		out_of_spec /* 0x03 */
Packit a55458
	};
Packit a55458
Packit a55458
	return spacing[code];
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.40 System Power Supply (Type 39)
Packit a55458
 */
Packit a55458
Packit a55458
static void dmi_power_supply_power(u16 code)
Packit a55458
{
Packit a55458
	if (code == 0x8000)
Packit a55458
		printf(" Unknown");
Packit a55458
	else
Packit a55458
		printf(" %u W", (unsigned int)code);
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_power_supply_type(u8 code)
Packit a55458
{
Packit a55458
	/* 7.40.1 */
Packit a55458
	static const char *type[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"Linear",
Packit a55458
		"Switching",
Packit a55458
		"Battery",
Packit a55458
		"UPS",
Packit a55458
		"Converter",
Packit a55458
		"Regulator" /* 0x08 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x08)
Packit a55458
		return type[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_power_supply_status(u8 code)
Packit a55458
{
Packit a55458
	/* 7.40.1 */
Packit a55458
	static const char *status[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"OK",
Packit a55458
		"Non-critical",
Packit a55458
		"Critical" /* 0x05 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x05)
Packit a55458
		return status[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
static const char *dmi_power_supply_range_switching(u8 code)
Packit a55458
{
Packit a55458
	/* 7.40.1 */
Packit a55458
	static const char *switching[] = {
Packit a55458
		"Other", /* 0x01 */
Packit a55458
		"Unknown",
Packit a55458
		"Manual",
Packit a55458
		"Auto-switch",
Packit a55458
		"Wide Range",
Packit a55458
		"N/A" /* 0x06 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x01 && code <= 0x06)
Packit a55458
		return switching[code - 0x01];
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.41 Additional Information (Type 40)
Packit a55458
 *
Packit a55458
 * Proper support of this entry type would require redesigning a large part of
Packit a55458
 * the code, so I am waiting to see actual implementations of it to decide
Packit a55458
 * whether it's worth the effort.
Packit a55458
 */
Packit a55458
Packit a55458
static void dmi_additional_info(const struct dmi_header *h, const char *prefix)
Packit a55458
{
Packit a55458
	u8 *p = h->data + 4;
Packit a55458
	u8 count = *p++;
Packit a55458
	u8 length;
Packit a55458
	int i, offset = 5;
Packit a55458
Packit a55458
	for (i = 0; i < count; i++)
Packit a55458
	{
Packit a55458
		printf("%sAdditional Information %d\n", prefix, i + 1);
Packit a55458
Packit a55458
		/* Check for short entries */
Packit a55458
		if (h->length < offset + 1) break;
Packit a55458
		length = p[0x00];
Packit a55458
		if (length < 0x05 || h->length < offset + length) break;
Packit a55458
Packit a55458
		printf("%s\tReferenced Handle: 0x%04x\n",
Packit a55458
			prefix, WORD(p + 0x01));
Packit a55458
		printf("%s\tReferenced Offset: 0x%02x\n",
Packit a55458
			prefix, p[0x03]);
Packit a55458
		printf("%s\tString: %s\n",
Packit a55458
			prefix, dmi_string(h, p[0x04]));
Packit a55458
Packit a55458
		printf("%s\tValue: ", prefix);
Packit a55458
		switch (length - 0x05)
Packit a55458
		{
Packit a55458
			case 1:
Packit a55458
				printf("0x%02x", p[0x05]);
Packit a55458
				break;
Packit a55458
			case 2:
Packit a55458
				printf("0x%04x", WORD(p + 0x05));
Packit a55458
				break;
Packit a55458
			case 4:
Packit a55458
				printf("0x%08x", DWORD(p + 0x05));
Packit a55458
				break;
Packit a55458
			default:
Packit a55458
				printf("Unexpected size");
Packit a55458
				break;
Packit a55458
		}
Packit a55458
		printf("\n");
Packit a55458
Packit a55458
		p += length;
Packit a55458
		offset += length;
Packit a55458
	}
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.43 Management Controller Host Interface (Type 42)
Packit a55458
 */
Packit a55458
Packit a55458
static const char *dmi_management_controller_host_type(u8 code)
Packit a55458
{
Packit a55458
	/* DMTF DSP0239 (MCTP) version 1.1.0 */
Packit a55458
	static const char *type[] = {
Packit a55458
		"KCS: Keyboard Controller Style", /* 0x02 */
Packit a55458
		"8250 UART Register Compatible",
Packit a55458
		"16450 UART Register Compatible",
Packit a55458
		"16550/16550A UART Register Compatible",
Packit a55458
		"16650/16650A UART Register Compatible",
Packit a55458
		"16750/16750A UART Register Compatible",
Packit a55458
		"16850/16850A UART Register Compatible" /* 0x08 */
Packit a55458
	};
Packit a55458
Packit a55458
	if (code >= 0x02 && code <= 0x08)
Packit a55458
		return type[code - 0x02];
Packit a55458
	if (code <= 0x3F)
Packit a55458
		return "MCTP";
Packit a55458
	if (code == 0x40)
Packit a55458
		return "Network";
Packit a55458
	if (code == 0xF0)
Packit a55458
		return "OEM";
Packit a55458
	return out_of_spec;
Packit a55458
}
Packit a55458
Packit a55458
/*
Packit a55458
 * 7.43.2: Protocol Record Types
Packit a55458
 */
Packit a55458
static const char *dmi_protocol_record_type(u8 type)
Packit a55458
{
Packit a55458
	const char *protocol[] = {