Blame dmidecode.c

Packit Service e18529
/*
Packit Service e18529
 * DMI Decode
Packit Service e18529
 *
Packit Service e18529
 *   Copyright (C) 2000-2002 Alan Cox <alan@redhat.com>
Packit Service 25e533
 *   Copyright (C) 2002-2019 Jean Delvare <jdelvare@suse.de>
Packit Service e18529
 *
Packit Service e18529
 *   This program is free software; you can redistribute it and/or modify
Packit Service e18529
 *   it under the terms of the GNU General Public License as published by
Packit Service e18529
 *   the Free Software Foundation; either version 2 of the License, or
Packit Service e18529
 *   (at your option) any later version.
Packit Service e18529
 *
Packit Service e18529
 *   This program is distributed in the hope that it will be useful,
Packit Service e18529
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service e18529
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service e18529
 *   GNU General Public License for more details.
Packit Service e18529
 *
Packit Service e18529
 *   You should have received a copy of the GNU General Public License
Packit Service e18529
 *   along with this program; if not, write to the Free Software
Packit Service e18529
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
Packit Service e18529
 *
Packit Service e18529
 *   For the avoidance of doubt the "preferred form" of this code is one which
Packit Service e18529
 *   is in an open unpatent encumbered format. Where cryptographic key signing
Packit Service e18529
 *   forms part of the process of creating an executable the information
Packit Service e18529
 *   including keys needed to generate an equivalently functional executable
Packit Service e18529
 *   are deemed to be part of the source code.
Packit Service e18529
 *
Packit Service e18529
 * Unless specified otherwise, all references are aimed at the "System
Packit Service e18529
 * Management BIOS Reference Specification, Version 3.2.0" document,
Packit Service e18529
 * available from http://www.dmtf.org/standards/smbios.
Packit Service e18529
 *
Packit Service e18529
 * Note to contributors:
Packit Service e18529
 * Please reference every value you add or modify, especially if the
Packit Service e18529
 * information does not come from the above mentioned specification.
Packit Service e18529
 *
Packit Service e18529
 * Additional references:
Packit Service e18529
 *  - Intel AP-485 revision 36
Packit Service e18529
 *    "Intel Processor Identification and the CPUID Instruction"
Packit Service e18529
 *    http://www.intel.com/support/processors/sb/cs-009861.htm
Packit Service e18529
 *  - DMTF Common Information Model
Packit Service e18529
 *    CIM Schema version 2.19.1
Packit Service e18529
 *    http://www.dmtf.org/standards/cim/
Packit Service e18529
 *  - IPMI 2.0 revision 1.0
Packit Service e18529
 *    "Intelligent Platform Management Interface Specification"
Packit Service e18529
 *    http://developer.intel.com/design/servers/ipmi/spec.htm
Packit Service e18529
 *  - AMD publication #25481 revision 2.28
Packit Service e18529
 *    "CPUID Specification"
Packit Service e18529
 *    http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/25481.pdf
Packit Service e18529
 *  - BIOS Integrity Services Application Programming Interface version 1.0
Packit Service e18529
 *    http://www.intel.com/design/archives/wfm/downloads/bisspec.htm
Packit Service e18529
 *  - DMTF DSP0239 version 1.1.0
Packit Service e18529
 *    "Management Component Transport Protocol (MCTP) IDs and Codes"
Packit Service e18529
 *    http://www.dmtf.org/standards/pmci
Packit Service e18529
 *  - "TPM Main, Part 2 TPM Structures"
Packit Service e18529
 *    Specification version 1.2, level 2, revision 116
Packit Service e18529
 *    https://trustedcomputinggroup.org/tpm-main-specification/
Packit Service e18529
 *  - "PC Client Platform TPM Profile (PTP) Specification"
Packit Service e18529
 *    Family "2.0", Level 00, Revision 00.43, January 26, 2015
Packit Service e18529
 *    https://trustedcomputinggroup.org/pc-client-platform-tpm-profile-ptp-specification/
Packit Service e18529
 *  - "RedFish Host Interface Specification" (DMTF DSP0270)
Packit Service e18529
 *    https://www.dmtf.org/sites/default/files/DSP0270_1.0.1.pdf
Packit Service e18529
 */
Packit Service e18529
Packit Service e18529
#include <stdio.h>
Packit Service e18529
#include <string.h>
Packit Service e18529
#include <strings.h>
Packit Service e18529
#include <stdlib.h>
Packit Service e18529
#include <unistd.h>
Packit Service e18529
#include <arpa/inet.h>
Packit Service 3418b0
#include <sys/socket.h>
Packit Service e18529
Packit Service e18529
#ifdef __FreeBSD__
Packit Service e18529
#include <errno.h>
Packit Service e18529
#include <kenv.h>
Packit Service e18529
#endif
Packit Service e18529
Packit Service e18529
#include "version.h"
Packit Service e18529
#include "config.h"
Packit Service e18529
#include "types.h"
Packit Service e18529
#include "util.h"
Packit Service e18529
#include "dmidecode.h"
Packit Service e18529
#include "dmiopt.h"
Packit Service e18529
#include "dmioem.h"
Packit Service e18529
Packit Service e18529
#define out_of_spec "<OUT OF SPEC>"
Packit Service e18529
static const char *bad_index = "<BAD INDEX>";
Packit Service e18529
Packit Service e18529
#define SUPPORTED_SMBIOS_VER 0x030200
Packit Service e18529
Packit Service e18529
#define FLAG_NO_FILE_OFFSET     (1 << 0)
Packit Service e18529
#define FLAG_STOP_AT_EOT        (1 << 1)
Packit Service e18529
Packit Service e18529
#define SYS_FIRMWARE_DIR "/sys/firmware/dmi/tables"
Packit Service e18529
#define SYS_ENTRY_FILE SYS_FIRMWARE_DIR "/smbios_entry_point"
Packit Service e18529
#define SYS_TABLE_FILE SYS_FIRMWARE_DIR "/DMI"
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * Type-independant Stuff
Packit Service e18529
 */
Packit Service e18529
Packit Service e18529
/* Returns 1 if the buffer contains only printable ASCII characters */
Packit Service e18529
int is_printable(const u8 *data, int len)
Packit Service e18529
{
Packit Service e18529
	int i;
Packit Service e18529
Packit Service e18529
	for (i = 0; i < len; i++)
Packit Service e18529
		if (data[i] < 32 || data[i] >= 127)
Packit Service e18529
			return 0;
Packit Service e18529
Packit Service e18529
	return 1;
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
const char *dmi_string(const struct dmi_header *dm, u8 s)
Packit Service 21d128
{
Packit Service 21d128
	char *bp = (char *)dm->data;
Packit Service 622062
	size_t i, len;
Packit Service 622062
Packit Service 622062
	if (s == 0)
Packit Service 622062
		return "Not Specified";
Packit Service e18529
Packit Service e18529
	bp += dm->length;
Packit Service e18529
	while (s > 1 && *bp)
Packit Service e18529
	{
Packit Service e18529
		bp += strlen(bp);
Packit Service e18529
		bp++;
Packit Service e18529
		s--;
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	if (!*bp)
Packit Service 21d128
		return bad_index;
Packit Service e18529
Packit Service 622062
	if (!(opt.flags & FLAG_DUMP))
Packit Service 622062
	{
Packit Service 622062
		/* ASCII filtering */
Packit Service 622062
		len = strlen(bp);
Packit Service 622062
		for (i = 0; i < len; i++)
Packit Service 622062
			if (bp[i] < 32 || bp[i] == 127)
Packit Service 622062
				bp[i] = '.';
Packit Service 622062
	}
Packit Service 622062
Packit Service e18529
	return bp;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_smbios_structure_type(u8 code)
Packit Service e18529
{
Packit Service e18529
	static const char *type[] = {
Packit Service e18529
		"BIOS", /* 0 */
Packit Service e18529
		"System",
Packit Service e18529
		"Base Board",
Packit Service e18529
		"Chassis",
Packit Service e18529
		"Processor",
Packit Service e18529
		"Memory Controller",
Packit Service e18529
		"Memory Module",
Packit Service e18529
		"Cache",
Packit Service e18529
		"Port Connector",
Packit Service e18529
		"System Slots",
Packit Service e18529
		"On Board Devices",
Packit Service e18529
		"OEM Strings",
Packit Service e18529
		"System Configuration Options",
Packit Service e18529
		"BIOS Language",
Packit Service e18529
		"Group Associations",
Packit Service e18529
		"System Event Log",
Packit Service e18529
		"Physical Memory Array",
Packit Service e18529
		"Memory Device",
Packit Service e18529
		"32-bit Memory Error",
Packit Service e18529
		"Memory Array Mapped Address",
Packit Service e18529
		"Memory Device Mapped Address",
Packit Service e18529
		"Built-in Pointing Device",
Packit Service e18529
		"Portable Battery",
Packit Service e18529
		"System Reset",
Packit Service e18529
		"Hardware Security",
Packit Service e18529
		"System Power Controls",
Packit Service e18529
		"Voltage Probe",
Packit Service e18529
		"Cooling Device",
Packit Service e18529
		"Temperature Probe",
Packit Service e18529
		"Electrical Current Probe",
Packit Service e18529
		"Out-of-band Remote Access",
Packit Service e18529
		"Boot Integrity Services",
Packit Service e18529
		"System Boot",
Packit Service e18529
		"64-bit Memory Error",
Packit Service e18529
		"Management Device",
Packit Service e18529
		"Management Device Component",
Packit Service e18529
		"Management Device Threshold Data",
Packit Service e18529
		"Memory Channel",
Packit Service e18529
		"IPMI Device",
Packit Service e18529
		"Power Supply",
Packit Service e18529
		"Additional Information",
Packit Service e18529
		"Onboard Device",
Packit Service e18529
		"Management Controller Host Interface",
Packit Service e18529
		"TPM Device", /* 43 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 128)
Packit Service e18529
		return "OEM-specific";
Packit Service e18529
	if (code <= 43)
Packit Service e18529
		return type[code];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static int dmi_bcd_range(u8 value, u8 low, u8 high)
Packit Service e18529
{
Packit Service e18529
	if (value > 0x99 || (value & 0x0F) > 0x09)
Packit Service e18529
		return 0;
Packit Service e18529
	if (value < low || value > high)
Packit Service e18529
		return 0;
Packit Service e18529
	return 1;
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_dump(const struct dmi_header *h, const char *prefix)
Packit Service e18529
{
Packit Service e18529
	int row, i;
Packit Service 622062
	const char *s;
Packit Service e18529
Packit Service 622062
	printf("%sHeader and Data:\n", prefix);
Packit Service e18529
	for (row = 0; row < ((h->length - 1) >> 4) + 1; row++)
Packit Service e18529
	{
Packit Service 622062
		printf("%s\t", prefix);
Packit Service e18529
		for (i = 0; i < 16 && i < h->length - (row << 4); i++)
Packit Service 622062
			printf("%s%02X", i ? " " : "",
Packit Service e18529
			       (h->data)[(row << 4) + i]);
Packit Service 622062
		printf("\n");
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	if ((h->data)[h->length] || (h->data)[h->length + 1])
Packit Service e18529
	{
Packit Service 622062
		printf("%sStrings:\n", prefix);
Packit Service e18529
		i = 1;
Packit Service 622062
		while ((s = dmi_string(h, i++)) != bad_index)
Packit Service e18529
		{
Packit Service e18529
			if (opt.flags & FLAG_DUMP)
Packit Service e18529
			{
Packit Service e18529
				int j, l = strlen(s) + 1;
Packit Service e18529
				for (row = 0; row < ((l - 1) >> 4) + 1; row++)
Packit Service e18529
				{
Packit Service 622062
					printf("%s\t", prefix);
Packit Service e18529
					for (j = 0; j < 16 && j < l - (row << 4); j++)
Packit Service 622062
						printf("%s%02X", j ? " " : "",
Packit Service e18529
						       (unsigned char)s[(row << 4) + j]);
Packit Service 622062
					printf("\n");
Packit Service e18529
				}
Packit Service e18529
				/* String isn't filtered yet so do it now */
Packit Service 622062
				printf("%s\t\"", prefix);
Packit Service 622062
				while (*s)
Packit Service 622062
				{
Packit Service 622062
					if (*s < 32 || *s == 127)
Packit Service 622062
						fputc('.', stdout);
Packit Service 622062
					else
Packit Service 622062
						fputc(*s, stdout);
Packit Service 622062
					s++;
Packit Service 622062
				}
Packit Service 622062
				printf("\"\n");
Packit Service e18529
			}
Packit Service 622062
			else
Packit Service 622062
				printf("%s\t%s\n", prefix, s);
Packit Service e18529
		}
Packit Service e18529
	}
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/* shift is 0 if the value is in bytes, 1 if it is in kilobytes */
Packit Service 622062
static void dmi_print_memory_size(u64 code, int shift)
Packit Service e18529
{
Packit Service e18529
	unsigned long capacity;
Packit Service e18529
	u16 split[7];
Packit Service e18529
	static const char *unit[8] = {
Packit Service e18529
		"bytes", "kB", "MB", "GB", "TB", "PB", "EB", "ZB"
Packit Service e18529
	};
Packit Service e18529
	int i;
Packit Service e18529
Packit Service e18529
	/*
Packit Service e18529
	 * We split the overall size in powers of thousand: EB, PB, TB, GB,
Packit Service e18529
	 * MB, kB and B. In practice, it is expected that only one or two
Packit Service e18529
	 * (consecutive) of these will be non-zero.
Packit Service e18529
	 */
Packit Service e18529
	split[0] = code.l & 0x3FFUL;
Packit Service e18529
	split[1] = (code.l >> 10) & 0x3FFUL;
Packit Service e18529
	split[2] = (code.l >> 20) & 0x3FFUL;
Packit Service e18529
	split[3] = ((code.h << 2) & 0x3FCUL) | (code.l >> 30);
Packit Service e18529
	split[4] = (code.h >> 8) & 0x3FFUL;
Packit Service e18529
	split[5] = (code.h >> 18) & 0x3FFUL;
Packit Service e18529
	split[6] = code.h >> 28;
Packit Service e18529
Packit Service e18529
	/*
Packit Service e18529
	 * Now we find the highest unit with a non-zero value. If the following
Packit Service e18529
	 * is also non-zero, we use that as our base. If the following is zero,
Packit Service e18529
	 * we simply display the highest unit.
Packit Service e18529
	 */
Packit Service e18529
	for (i = 6; i > 0; i--)
Packit Service e18529
	{
Packit Service e18529
		if (split[i])
Packit Service e18529
			break;
Packit Service e18529
	}
Packit Service e18529
	if (i > 0 && split[i - 1])
Packit Service e18529
	{
Packit Service e18529
		i--;
Packit Service e18529
		capacity = split[i] + (split[i + 1] << 10);
Packit Service e18529
	}
Packit Service e18529
	else
Packit Service e18529
		capacity = split[i];
Packit Service e18529
Packit Service 622062
	printf(" %lu %s", capacity, unit[i + shift]);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.1 BIOS Information (Type 0)
Packit Service e18529
 */
Packit Service e18529
Packit Service e18529
static void dmi_bios_runtime_size(u32 code)
Packit Service e18529
{
Packit Service e18529
	if (code & 0x000003FF)
Packit Service 622062
		printf(" %u bytes", code);
Packit Service e18529
	else
Packit Service 622062
		printf(" %u kB", code >> 10);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static void dmi_bios_rom_size(u8 code1, u16 code2)
Packit Service e18529
{
Packit Service e18529
	static const char *unit[4] = {
Packit Service e18529
		"MB", "GB", out_of_spec, out_of_spec
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code1 != 0xFF)
Packit Service 75548d
	{
Packit Service 75548d
		u64 s = { .l = (code1 + 1) << 6 };
Packit Service 75548d
		dmi_print_memory_size(s, 1);
Packit Service 75548d
	}
Packit Service e18529
	else
Packit Service 622062
		printf(" %u %s", code2 & 0x3FFF, unit[code2 >> 14]);
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_bios_characteristics(u64 code, const char *prefix)
Packit Service e18529
{
Packit Service e18529
	/* 7.1.1 */
Packit Service e18529
	static const char *characteristics[] = {
Packit Service e18529
		"BIOS characteristics not supported", /* 3 */
Packit Service e18529
		"ISA is supported",
Packit Service e18529
		"MCA is supported",
Packit Service e18529
		"EISA is supported",
Packit Service e18529
		"PCI is supported",
Packit Service e18529
		"PC Card (PCMCIA) is supported",
Packit Service e18529
		"PNP is supported",
Packit Service e18529
		"APM is supported",
Packit Service e18529
		"BIOS is upgradeable",
Packit Service e18529
		"BIOS shadowing is allowed",
Packit Service e18529
		"VLB is supported",
Packit Service e18529
		"ESCD support is available",
Packit Service e18529
		"Boot from CD is supported",
Packit Service e18529
		"Selectable boot is supported",
Packit Service e18529
		"BIOS ROM is socketed",
Packit Service e18529
		"Boot from PC Card (PCMCIA) is supported",
Packit Service e18529
		"EDD is supported",
Packit Service e18529
		"Japanese floppy for NEC 9800 1.2 MB is supported (int 13h)",
Packit Service e18529
		"Japanese floppy for Toshiba 1.2 MB is supported (int 13h)",
Packit Service e18529
		"5.25\"/360 kB floppy services are supported (int 13h)",
Packit Service e18529
		"5.25\"/1.2 MB floppy services are supported (int 13h)",
Packit Service e18529
		"3.5\"/720 kB floppy services are supported (int 13h)",
Packit Service e18529
		"3.5\"/2.88 MB floppy services are supported (int 13h)",
Packit Service e18529
		"Print screen service is supported (int 5h)",
Packit Service e18529
		"8042 keyboard services are supported (int 9h)",
Packit Service e18529
		"Serial services are supported (int 14h)",
Packit Service e18529
		"Printer services are supported (int 17h)",
Packit Service e18529
		"CGA/mono video services are supported (int 10h)",
Packit Service e18529
		"NEC PC-98" /* 31 */
Packit Service e18529
	};
Packit Service e18529
	int i;
Packit Service e18529
Packit Service e18529
	/*
Packit Service e18529
	 * This isn't very clear what this bit is supposed to mean
Packit Service e18529
	 */
Packit Service e18529
	if (code.l & (1 << 3))
Packit Service e18529
	{
Packit Service 622062
		printf("%s%s\n",
Packit Service 622062
			prefix, characteristics[0]);
Packit Service e18529
		return;
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	for (i = 4; i <= 31; i++)
Packit Service e18529
		if (code.l & (1 << i))
Packit Service 622062
			printf("%s%s\n",
Packit Service 622062
				prefix, characteristics[i - 3]);
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_bios_characteristics_x1(u8 code, const char *prefix)
Packit Service e18529
{
Packit Service e18529
	/* 7.1.2.1 */
Packit Service e18529
	static const char *characteristics[] = {
Packit Service e18529
		"ACPI is supported", /* 0 */
Packit Service e18529
		"USB legacy is supported",
Packit Service e18529
		"AGP is supported",
Packit Service e18529
		"I2O boot is supported",
Packit Service e18529
		"LS-120 boot is supported",
Packit Service e18529
		"ATAPI Zip drive boot is supported",
Packit Service e18529
		"IEEE 1394 boot is supported",
Packit Service e18529
		"Smart battery is supported" /* 7 */
Packit Service e18529
	};
Packit Service e18529
	int i;
Packit Service e18529
Packit Service e18529
	for (i = 0; i <= 7; i++)
Packit Service e18529
		if (code & (1 << i))
Packit Service 622062
			printf("%s%s\n",
Packit Service 622062
				prefix, characteristics[i]);
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_bios_characteristics_x2(u8 code, const char *prefix)
Packit Service e18529
{
Packit Service e18529
	/* 37.1.2.2 */
Packit Service e18529
	static const char *characteristics[] = {
Packit Service e18529
		"BIOS boot specification is supported", /* 0 */
Packit Service e18529
		"Function key-initiated network boot is supported",
Packit Service e18529
		"Targeted content distribution is supported",
Packit Service e18529
		"UEFI is supported",
Packit Service e18529
		"System is a virtual machine" /* 4 */
Packit Service e18529
	};
Packit Service e18529
	int i;
Packit Service e18529
Packit Service e18529
	for (i = 0; i <= 4; i++)
Packit Service e18529
		if (code & (1 << i))
Packit Service 622062
			printf("%s%s\n",
Packit Service 622062
				prefix, characteristics[i]);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.2 System Information (Type 1)
Packit Service e18529
 */
Packit Service e18529
Packit Service 622062
static void dmi_system_uuid(const u8 *p, u16 ver)
Packit Service e18529
{
Packit Service e18529
	int only0xFF = 1, only0x00 = 1;
Packit Service e18529
	int i;
Packit Service e18529
Packit Service e18529
	for (i = 0; i < 16 && (only0x00 || only0xFF); i++)
Packit Service e18529
	{
Packit Service e18529
		if (p[i] != 0x00) only0x00 = 0;
Packit Service e18529
		if (p[i] != 0xFF) only0xFF = 0;
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	if (only0xFF)
Packit Service e18529
	{
Packit Service 622062
		printf("Not Present");
Packit Service e18529
		return;
Packit Service e18529
	}
Packit Service e18529
	if (only0x00)
Packit Service e18529
	{
Packit Service 622062
		printf("Not Settable");
Packit Service e18529
		return;
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	/*
Packit Service e18529
	 * As of version 2.6 of the SMBIOS specification, the first 3
Packit Service e18529
	 * fields of the UUID are supposed to be encoded on little-endian.
Packit Service e18529
	 * The specification says that this is the defacto standard,
Packit Service e18529
	 * however I've seen systems following RFC 4122 instead and use
Packit Service e18529
	 * network byte order, so I am reluctant to apply the byte-swapping
Packit Service e18529
	 * for older versions.
Packit Service e18529
	 */
Packit Service e18529
	if (ver >= 0x0206)
Packit Service 622062
		printf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
Packit Service 622062
			p[3], p[2], p[1], p[0], p[5], p[4], p[7], p[6],
Packit Service 622062
			p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
Packit Service e18529
	else
Packit Service 622062
		printf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
Packit Service 622062
			p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
Packit Service 622062
			p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_system_wake_up_type(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.2.2 */
Packit Service e18529
	static const char *type[] = {
Packit Service e18529
		"Reserved", /* 0x00 */
Packit Service e18529
		"Other",
Packit Service e18529
		"Unknown",
Packit Service e18529
		"APM Timer",
Packit Service e18529
		"Modem Ring",
Packit Service e18529
		"LAN Remote",
Packit Service e18529
		"Power Switch",
Packit Service e18529
		"PCI PME#",
Packit Service e18529
		"AC Power Restored" /* 0x08 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code <= 0x08)
Packit Service e18529
		return type[code];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.3 Base Board Information (Type 2)
Packit Service e18529
 */
Packit Service e18529
Packit Service 622062
static void dmi_base_board_features(u8 code, const char *prefix)
Packit Service e18529
{
Packit Service e18529
	/* 7.3.1 */
Packit Service e18529
	static const char *features[] = {
Packit Service e18529
		"Board is a hosting board", /* 0 */
Packit Service e18529
		"Board requires at least one daughter board",
Packit Service e18529
		"Board is removable",
Packit Service e18529
		"Board is replaceable",
Packit Service e18529
		"Board is hot swappable" /* 4 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if ((code & 0x1F) == 0)
Packit Service 622062
		printf(" None\n");
Packit Service e18529
	else
Packit Service e18529
	{
Packit Service e18529
		int i;
Packit Service e18529
Packit Service 622062
		printf("\n");
Packit Service e18529
		for (i = 0; i <= 4; i++)
Packit Service e18529
			if (code & (1 << i))
Packit Service 622062
				printf("%s%s\n",
Packit Service 622062
					prefix, features[i]);
Packit Service e18529
	}
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_base_board_type(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.3.2 */
Packit Service e18529
	static const char *type[] = {
Packit Service e18529
		"Unknown", /* 0x01 */
Packit Service e18529
		"Other",
Packit Service e18529
		"Server Blade",
Packit Service e18529
		"Connectivity Switch",
Packit Service e18529
		"System Management Module",
Packit Service e18529
		"Processor Module",
Packit Service e18529
		"I/O Module",
Packit Service e18529
		"Memory Module",
Packit Service e18529
		"Daughter Board",
Packit Service e18529
		"Motherboard",
Packit Service e18529
		"Processor+Memory Module",
Packit Service e18529
		"Processor+I/O Module",
Packit Service e18529
		"Interconnect Board" /* 0x0D */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x0D)
Packit Service e18529
		return type[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_base_board_handles(u8 count, const u8 *p, const char *prefix)
Packit Service e18529
{
Packit Service e18529
	int i;
Packit Service e18529
Packit Service 622062
	printf("%sContained Object Handles: %u\n",
Packit Service 622062
		prefix, count);
Packit Service e18529
	for (i = 0; i < count; i++)
Packit Service 622062
		printf("%s\t0x%04X\n",
Packit Service 622062
			prefix, WORD(p + sizeof(u16) * i));
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.4 Chassis Information (Type 3)
Packit Service e18529
 */
Packit Service e18529
Packit Service e18529
static const char *dmi_chassis_type(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.4.1 */
Packit Service e18529
	static const char *type[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"Desktop",
Packit Service e18529
		"Low Profile Desktop",
Packit Service e18529
		"Pizza Box",
Packit Service e18529
		"Mini Tower",
Packit Service e18529
		"Tower",
Packit Service e18529
		"Portable",
Packit Service e18529
		"Laptop",
Packit Service e18529
		"Notebook",
Packit Service e18529
		"Hand Held",
Packit Service e18529
		"Docking Station",
Packit Service e18529
		"All In One",
Packit Service e18529
		"Sub Notebook",
Packit Service e18529
		"Space-saving",
Packit Service e18529
		"Lunch Box",
Packit Service e18529
		"Main Server Chassis", /* CIM_Chassis.ChassisPackageType says "Main System Chassis" */
Packit Service e18529
		"Expansion Chassis",
Packit Service e18529
		"Sub Chassis",
Packit Service e18529
		"Bus Expansion Chassis",
Packit Service e18529
		"Peripheral Chassis",
Packit Service e18529
		"RAID Chassis",
Packit Service e18529
		"Rack Mount Chassis",
Packit Service e18529
		"Sealed-case PC",
Packit Service e18529
		"Multi-system",
Packit Service e18529
		"CompactPCI",
Packit Service e18529
		"AdvancedTCA",
Packit Service e18529
		"Blade",
Packit Service e18529
		"Blade Enclosing",
Packit Service e18529
		"Tablet",
Packit Service e18529
		"Convertible",
Packit Service e18529
		"Detachable",
Packit Service e18529
		"IoT Gateway",
Packit Service e18529
		"Embedded PC",
Packit Service e18529
		"Mini PC",
Packit Service e18529
		"Stick PC" /* 0x24 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	code &= 0x7F; /* bits 6:0 are chassis type, 7th bit is the lock bit */
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x24)
Packit Service e18529
		return type[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_chassis_lock(u8 code)
Packit Service e18529
{
Packit Service e18529
	static const char *lock[] = {
Packit Service e18529
		"Not Present", /* 0x00 */
Packit Service e18529
		"Present" /* 0x01 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	return lock[code];
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_chassis_state(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.4.2 */
Packit Service e18529
	static const char *state[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"Safe",
Packit Service e18529
		"Warning",
Packit Service e18529
		"Critical",
Packit Service e18529
		"Non-recoverable" /* 0x06 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x06)
Packit Service e18529
		return state[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_chassis_security_status(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.4.3 */
Packit Service e18529
	static const char *status[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"None",
Packit Service e18529
		"External Interface Locked Out",
Packit Service e18529
		"External Interface Enabled" /* 0x05 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x05)
Packit Service e18529
		return status[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static void dmi_chassis_height(u8 code)
Packit Service e18529
{
Packit Service e18529
	if (code == 0x00)
Packit Service 622062
		printf(" Unspecified");
Packit Service e18529
	else
Packit Service 622062
		printf(" %u U", code);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static void dmi_chassis_power_cords(u8 code)
Packit Service e18529
{
Packit Service e18529
	if (code == 0x00)
Packit Service 622062
		printf(" Unspecified");
Packit Service e18529
	else
Packit Service 622062
		printf(" %u", code);
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_chassis_elements(u8 count, u8 len, const u8 *p, const char *prefix)
Packit Service e18529
{
Packit Service e18529
	int i;
Packit Service e18529
Packit Service 622062
	printf("%sContained Elements: %u\n",
Packit Service 622062
		prefix, count);
Packit Service e18529
	for (i = 0; i < count; i++)
Packit Service e18529
	{
Packit Service e18529
		if (len >= 0x03)
Packit Service e18529
		{
Packit Service 622062
			printf("%s\t%s (",
Packit Service 622062
				prefix, p[i * len] & 0x80 ?
Packit Service e18529
				dmi_smbios_structure_type(p[i * len] & 0x7F) :
Packit Service 622062
				dmi_base_board_type(p[i * len] & 0x7F));
Packit Service e18529
			if (p[1 + i * len] == p[2 + i * len])
Packit Service 622062
				printf("%u", p[1 + i * len]);
Packit Service e18529
			else
Packit Service 622062
				printf("%u-%u", p[1 + i * len], p[2 + i * len]);
Packit Service 622062
			printf(")\n");
Packit Service e18529
		}
Packit Service e18529
	}
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.5 Processor Information (Type 4)
Packit Service e18529
 */
Packit Service e18529
Packit Service e18529
static const char *dmi_processor_type(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.5.1 */
Packit Service e18529
	static const char *type[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"Central Processor",
Packit Service e18529
		"Math Processor",
Packit Service e18529
		"DSP Processor",
Packit Service e18529
		"Video Processor" /* 0x06 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x06)
Packit Service e18529
		return type[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_processor_family(const struct dmi_header *h, u16 ver)
Packit Service e18529
{
Packit Service e18529
	const u8 *data = h->data;
Packit Service e18529
	unsigned int i, low, high;
Packit Service e18529
	u16 code;
Packit Service e18529
Packit Service e18529
	/* 7.5.2 */
Packit Service e18529
	static struct {
Packit Service e18529
		int value;
Packit Service e18529
		const char *name;
Packit Service e18529
	} family2[] = {
Packit Service e18529
		{ 0x01, "Other" },
Packit Service e18529
		{ 0x02, "Unknown" },
Packit Service e18529
		{ 0x03, "8086" },
Packit Service e18529
		{ 0x04, "80286" },
Packit Service e18529
		{ 0x05, "80386" },
Packit Service e18529
		{ 0x06, "80486" },
Packit Service e18529
		{ 0x07, "8087" },
Packit Service e18529
		{ 0x08, "80287" },
Packit Service e18529
		{ 0x09, "80387" },
Packit Service e18529
		{ 0x0A, "80487" },
Packit Service e18529
		{ 0x0B, "Pentium" },
Packit Service e18529
		{ 0x0C, "Pentium Pro" },
Packit Service e18529
		{ 0x0D, "Pentium II" },
Packit Service e18529
		{ 0x0E, "Pentium MMX" },
Packit Service e18529
		{ 0x0F, "Celeron" },
Packit Service e18529
		{ 0x10, "Pentium II Xeon" },
Packit Service e18529
		{ 0x11, "Pentium III" },
Packit Service e18529
		{ 0x12, "M1" },
Packit Service e18529
		{ 0x13, "M2" },
Packit Service e18529
		{ 0x14, "Celeron M" },
Packit Service e18529
		{ 0x15, "Pentium 4 HT" },
Packit Service e18529
Packit Service e18529
		{ 0x18, "Duron" },
Packit Service e18529
		{ 0x19, "K5" },
Packit Service e18529
		{ 0x1A, "K6" },
Packit Service e18529
		{ 0x1B, "K6-2" },
Packit Service e18529
		{ 0x1C, "K6-3" },
Packit Service e18529
		{ 0x1D, "Athlon" },
Packit Service e18529
		{ 0x1E, "AMD29000" },
Packit Service e18529
		{ 0x1F, "K6-2+" },
Packit Service e18529
		{ 0x20, "Power PC" },
Packit Service e18529
		{ 0x21, "Power PC 601" },
Packit Service e18529
		{ 0x22, "Power PC 603" },
Packit Service e18529
		{ 0x23, "Power PC 603+" },
Packit Service e18529
		{ 0x24, "Power PC 604" },
Packit Service e18529
		{ 0x25, "Power PC 620" },
Packit Service e18529
		{ 0x26, "Power PC x704" },
Packit Service e18529
		{ 0x27, "Power PC 750" },
Packit Service e18529
		{ 0x28, "Core Duo" },
Packit Service e18529
		{ 0x29, "Core Duo Mobile" },
Packit Service e18529
		{ 0x2A, "Core Solo Mobile" },
Packit Service e18529
		{ 0x2B, "Atom" },
Packit Service e18529
		{ 0x2C, "Core M" },
Packit Service e18529
		{ 0x2D, "Core m3" },
Packit Service e18529
		{ 0x2E, "Core m5" },
Packit Service e18529
		{ 0x2F, "Core m7" },
Packit Service e18529
		{ 0x30, "Alpha" },
Packit Service e18529
		{ 0x31, "Alpha 21064" },
Packit Service e18529
		{ 0x32, "Alpha 21066" },
Packit Service e18529
		{ 0x33, "Alpha 21164" },
Packit Service e18529
		{ 0x34, "Alpha 21164PC" },
Packit Service e18529
		{ 0x35, "Alpha 21164a" },
Packit Service e18529
		{ 0x36, "Alpha 21264" },
Packit Service e18529
		{ 0x37, "Alpha 21364" },
Packit Service e18529
		{ 0x38, "Turion II Ultra Dual-Core Mobile M" },
Packit Service e18529
		{ 0x39, "Turion II Dual-Core Mobile M" },
Packit Service e18529
		{ 0x3A, "Athlon II Dual-Core M" },
Packit Service e18529
		{ 0x3B, "Opteron 6100" },
Packit Service e18529
		{ 0x3C, "Opteron 4100" },
Packit Service e18529
		{ 0x3D, "Opteron 6200" },
Packit Service e18529
		{ 0x3E, "Opteron 4200" },
Packit Service e18529
		{ 0x3F, "FX" },
Packit Service e18529
		{ 0x40, "MIPS" },
Packit Service e18529
		{ 0x41, "MIPS R4000" },
Packit Service e18529
		{ 0x42, "MIPS R4200" },
Packit Service e18529
		{ 0x43, "MIPS R4400" },
Packit Service e18529
		{ 0x44, "MIPS R4600" },
Packit Service e18529
		{ 0x45, "MIPS R10000" },
Packit Service e18529
		{ 0x46, "C-Series" },
Packit Service e18529
		{ 0x47, "E-Series" },
Packit Service e18529
		{ 0x48, "A-Series" },
Packit Service e18529
		{ 0x49, "G-Series" },
Packit Service e18529
		{ 0x4A, "Z-Series" },
Packit Service e18529
		{ 0x4B, "R-Series" },
Packit Service e18529
		{ 0x4C, "Opteron 4300" },
Packit Service e18529
		{ 0x4D, "Opteron 6300" },
Packit Service e18529
		{ 0x4E, "Opteron 3300" },
Packit Service e18529
		{ 0x4F, "FirePro" },
Packit Service e18529
		{ 0x50, "SPARC" },
Packit Service e18529
		{ 0x51, "SuperSPARC" },
Packit Service e18529
		{ 0x52, "MicroSPARC II" },
Packit Service e18529
		{ 0x53, "MicroSPARC IIep" },
Packit Service e18529
		{ 0x54, "UltraSPARC" },
Packit Service e18529
		{ 0x55, "UltraSPARC II" },
Packit Service e18529
		{ 0x56, "UltraSPARC IIi" },
Packit Service e18529
		{ 0x57, "UltraSPARC III" },
Packit Service e18529
		{ 0x58, "UltraSPARC IIIi" },
Packit Service e18529
Packit Service e18529
		{ 0x60, "68040" },
Packit Service e18529
		{ 0x61, "68xxx" },
Packit Service e18529
		{ 0x62, "68000" },
Packit Service e18529
		{ 0x63, "68010" },
Packit Service e18529
		{ 0x64, "68020" },
Packit Service e18529
		{ 0x65, "68030" },
Packit Service e18529
		{ 0x66, "Athlon X4" },
Packit Service e18529
		{ 0x67, "Opteron X1000" },
Packit Service e18529
		{ 0x68, "Opteron X2000" },
Packit Service e18529
		{ 0x69, "Opteron A-Series" },
Packit Service e18529
		{ 0x6A, "Opteron X3000" },
Packit Service e18529
		{ 0x6B, "Zen" },
Packit Service e18529
Packit Service e18529
		{ 0x70, "Hobbit" },
Packit Service e18529
Packit Service e18529
		{ 0x78, "Crusoe TM5000" },
Packit Service e18529
		{ 0x79, "Crusoe TM3000" },
Packit Service e18529
		{ 0x7A, "Efficeon TM8000" },
Packit Service e18529
Packit Service e18529
		{ 0x80, "Weitek" },
Packit Service e18529
Packit Service e18529
		{ 0x82, "Itanium" },
Packit Service e18529
		{ 0x83, "Athlon 64" },
Packit Service e18529
		{ 0x84, "Opteron" },
Packit Service e18529
		{ 0x85, "Sempron" },
Packit Service e18529
		{ 0x86, "Turion 64" },
Packit Service e18529
		{ 0x87, "Dual-Core Opteron" },
Packit Service e18529
		{ 0x88, "Athlon 64 X2" },
Packit Service e18529
		{ 0x89, "Turion 64 X2" },
Packit Service e18529
		{ 0x8A, "Quad-Core Opteron" },
Packit Service e18529
		{ 0x8B, "Third-Generation Opteron" },
Packit Service e18529
		{ 0x8C, "Phenom FX" },
Packit Service e18529
		{ 0x8D, "Phenom X4" },
Packit Service e18529
		{ 0x8E, "Phenom X2" },
Packit Service e18529
		{ 0x8F, "Athlon X2" },
Packit Service e18529
		{ 0x90, "PA-RISC" },
Packit Service e18529
		{ 0x91, "PA-RISC 8500" },
Packit Service e18529
		{ 0x92, "PA-RISC 8000" },
Packit Service e18529
		{ 0x93, "PA-RISC 7300LC" },
Packit Service e18529
		{ 0x94, "PA-RISC 7200" },
Packit Service e18529
		{ 0x95, "PA-RISC 7100LC" },
Packit Service e18529
		{ 0x96, "PA-RISC 7100" },
Packit Service e18529
Packit Service e18529
		{ 0xA0, "V30" },
Packit Service e18529
		{ 0xA1, "Quad-Core Xeon 3200" },
Packit Service e18529
		{ 0xA2, "Dual-Core Xeon 3000" },
Packit Service e18529
		{ 0xA3, "Quad-Core Xeon 5300" },
Packit Service e18529
		{ 0xA4, "Dual-Core Xeon 5100" },
Packit Service e18529
		{ 0xA5, "Dual-Core Xeon 5000" },
Packit Service e18529
		{ 0xA6, "Dual-Core Xeon LV" },
Packit Service e18529
		{ 0xA7, "Dual-Core Xeon ULV" },
Packit Service e18529
		{ 0xA8, "Dual-Core Xeon 7100" },
Packit Service e18529
		{ 0xA9, "Quad-Core Xeon 5400" },
Packit Service e18529
		{ 0xAA, "Quad-Core Xeon" },
Packit Service e18529
		{ 0xAB, "Dual-Core Xeon 5200" },
Packit Service e18529
		{ 0xAC, "Dual-Core Xeon 7200" },
Packit Service e18529
		{ 0xAD, "Quad-Core Xeon 7300" },
Packit Service e18529
		{ 0xAE, "Quad-Core Xeon 7400" },
Packit Service e18529
		{ 0xAF, "Multi-Core Xeon 7400" },
Packit Service e18529
		{ 0xB0, "Pentium III Xeon" },
Packit Service e18529
		{ 0xB1, "Pentium III Speedstep" },
Packit Service e18529
		{ 0xB2, "Pentium 4" },
Packit Service e18529
		{ 0xB3, "Xeon" },
Packit Service e18529
		{ 0xB4, "AS400" },
Packit Service e18529
		{ 0xB5, "Xeon MP" },
Packit Service e18529
		{ 0xB6, "Athlon XP" },
Packit Service e18529
		{ 0xB7, "Athlon MP" },
Packit Service e18529
		{ 0xB8, "Itanium 2" },
Packit Service e18529
		{ 0xB9, "Pentium M" },
Packit Service e18529
		{ 0xBA, "Celeron D" },
Packit Service e18529
		{ 0xBB, "Pentium D" },
Packit Service e18529
		{ 0xBC, "Pentium EE" },
Packit Service e18529
		{ 0xBD, "Core Solo" },
Packit Service e18529
		/* 0xBE handled as a special case */
Packit Service e18529
		{ 0xBF, "Core 2 Duo" },
Packit Service e18529
		{ 0xC0, "Core 2 Solo" },
Packit Service e18529
		{ 0xC1, "Core 2 Extreme" },
Packit Service e18529
		{ 0xC2, "Core 2 Quad" },
Packit Service e18529
		{ 0xC3, "Core 2 Extreme Mobile" },
Packit Service e18529
		{ 0xC4, "Core 2 Duo Mobile" },
Packit Service e18529
		{ 0xC5, "Core 2 Solo Mobile" },
Packit Service e18529
		{ 0xC6, "Core i7" },
Packit Service e18529
		{ 0xC7, "Dual-Core Celeron" },
Packit Service e18529
		{ 0xC8, "IBM390" },
Packit Service e18529
		{ 0xC9, "G4" },
Packit Service e18529
		{ 0xCA, "G5" },
Packit Service e18529
		{ 0xCB, "ESA/390 G6" },
Packit Service e18529
		{ 0xCC, "z/Architecture" },
Packit Service e18529
		{ 0xCD, "Core i5" },
Packit Service e18529
		{ 0xCE, "Core i3" },
Packit Service e18529
		{ 0xCF, "Core i9" },
Packit Service e18529
Packit Service e18529
		{ 0xD2, "C7-M" },
Packit Service e18529
		{ 0xD3, "C7-D" },
Packit Service e18529
		{ 0xD4, "C7" },
Packit Service e18529
		{ 0xD5, "Eden" },
Packit Service e18529
		{ 0xD6, "Multi-Core Xeon" },
Packit Service e18529
		{ 0xD7, "Dual-Core Xeon 3xxx" },
Packit Service e18529
		{ 0xD8, "Quad-Core Xeon 3xxx" },
Packit Service e18529
		{ 0xD9, "Nano" },
Packit Service e18529
		{ 0xDA, "Dual-Core Xeon 5xxx" },
Packit Service e18529
		{ 0xDB, "Quad-Core Xeon 5xxx" },
Packit Service e18529
Packit Service e18529
		{ 0xDD, "Dual-Core Xeon 7xxx" },
Packit Service e18529
		{ 0xDE, "Quad-Core Xeon 7xxx" },
Packit Service e18529
		{ 0xDF, "Multi-Core Xeon 7xxx" },
Packit Service e18529
		{ 0xE0, "Multi-Core Xeon 3400" },
Packit Service e18529
Packit Service e18529
		{ 0xE4, "Opteron 3000" },
Packit Service e18529
		{ 0xE5, "Sempron II" },
Packit Service e18529
		{ 0xE6, "Embedded Opteron Quad-Core" },
Packit Service e18529
		{ 0xE7, "Phenom Triple-Core" },
Packit Service e18529
		{ 0xE8, "Turion Ultra Dual-Core Mobile" },
Packit Service e18529
		{ 0xE9, "Turion Dual-Core Mobile" },
Packit Service e18529
		{ 0xEA, "Athlon Dual-Core" },
Packit Service e18529
		{ 0xEB, "Sempron SI" },
Packit Service e18529
		{ 0xEC, "Phenom II" },
Packit Service e18529
		{ 0xED, "Athlon II" },
Packit Service e18529
		{ 0xEE, "Six-Core Opteron" },
Packit Service e18529
		{ 0xEF, "Sempron M" },
Packit Service e18529
Packit Service e18529
		{ 0xFA, "i860" },
Packit Service e18529
		{ 0xFB, "i960" },
Packit Service e18529
Packit Service e18529
		{ 0x100, "ARMv7" },
Packit Service e18529
		{ 0x101, "ARMv8" },
Packit Service e18529
		{ 0x104, "SH-3" },
Packit Service e18529
		{ 0x105, "SH-4" },
Packit Service e18529
		{ 0x118, "ARM" },
Packit Service e18529
		{ 0x119, "StrongARM" },
Packit Service e18529
		{ 0x12C, "6x86" },
Packit Service e18529
		{ 0x12D, "MediaGX" },
Packit Service e18529
		{ 0x12E, "MII" },
Packit Service e18529
		{ 0x140, "WinChip" },
Packit Service e18529
		{ 0x15E, "DSP" },
Packit Service e18529
		{ 0x1F4, "Video Processor" },
Packit Service 0bfd26
Packit Service 0bfd26
		{ 0x200, "RV32" },
Packit Service 0bfd26
		{ 0x201, "RV64" },
Packit Service 0bfd26
		{ 0x202, "RV128" },
Packit Service e18529
	};
Packit Service e18529
	/*
Packit Service e18529
	 * Note to developers: when adding entries to this list, check if
Packit Service e18529
	 * function dmi_processor_id below needs updating too.
Packit Service e18529
	 */
Packit Service e18529
Packit Service e18529
	/* Special case for ambiguous value 0x30 (SMBIOS 2.0 only) */
Packit Service e18529
	if (ver == 0x0200 && data[0x06] == 0x30 && h->length >= 0x08)
Packit Service e18529
	{
Packit Service e18529
		const char *manufacturer = dmi_string(h, data[0x07]);
Packit Service e18529
Packit Service e18529
		if (strstr(manufacturer, "Intel") != NULL
Packit Service e18529
		 || strncasecmp(manufacturer, "Intel", 5) == 0)
Packit Service e18529
			return "Pentium Pro";
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	code = (data[0x06] == 0xFE && h->length >= 0x2A) ?
Packit Service e18529
		WORD(data + 0x28) : data[0x06];
Packit Service e18529
Packit Service e18529
	/* Special case for ambiguous value 0xBE */
Packit Service e18529
	if (code == 0xBE)
Packit Service e18529
	{
Packit Service e18529
		if (h->length >= 0x08)
Packit Service e18529
		{
Packit Service e18529
			const char *manufacturer = dmi_string(h, data[0x07]);
Packit Service e18529
Packit Service e18529
			/* Best bet based on manufacturer string */
Packit Service e18529
			if (strstr(manufacturer, "Intel") != NULL
Packit Service e18529
			 || strncasecmp(manufacturer, "Intel", 5) == 0)
Packit Service e18529
				return "Core 2";
Packit Service e18529
			if (strstr(manufacturer, "AMD") != NULL
Packit Service e18529
			 || strncasecmp(manufacturer, "AMD", 3) == 0)
Packit Service e18529
				return "K7";
Packit Service e18529
		}
Packit Service e18529
Packit Service e18529
		return "Core 2 or K7";
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	/* Perform a binary search */
Packit Service e18529
	low = 0;
Packit Service e18529
	high = ARRAY_SIZE(family2) - 1;
Packit Service e18529
Packit Service e18529
	while (1)
Packit Service e18529
	{
Packit Service e18529
		i = (low + high) / 2;
Packit Service e18529
		if (family2[i].value == code)
Packit Service e18529
			return family2[i].name;
Packit Service e18529
		if (low == high) /* Not found */
Packit Service e18529
			return out_of_spec;
Packit Service e18529
Packit Service e18529
		if (code < family2[i].value)
Packit Service e18529
			high = i;
Packit Service e18529
		else
Packit Service e18529
			low = i + 1;
Packit Service e18529
	}
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_processor_id(const struct dmi_header *h, const char *prefix)
Packit Service e18529
{
Packit Service e18529
	/* Intel AP-485 revision 36, table 2-4 */
Packit Service e18529
	static const char *flags[32] = {
Packit Service e18529
		"FPU (Floating-point unit on-chip)", /* 0 */
Packit Service e18529
		"VME (Virtual mode extension)",
Packit Service e18529
		"DE (Debugging extension)",
Packit Service e18529
		"PSE (Page size extension)",
Packit Service e18529
		"TSC (Time stamp counter)",
Packit Service e18529
		"MSR (Model specific registers)",
Packit Service e18529
		"PAE (Physical address extension)",
Packit Service e18529
		"MCE (Machine check exception)",
Packit Service e18529
		"CX8 (CMPXCHG8 instruction supported)",
Packit Service e18529
		"APIC (On-chip APIC hardware supported)",
Packit Service e18529
		NULL, /* 10 */
Packit Service e18529
		"SEP (Fast system call)",
Packit Service e18529
		"MTRR (Memory type range registers)",
Packit Service e18529
		"PGE (Page global enable)",
Packit Service e18529
		"MCA (Machine check architecture)",
Packit Service e18529
		"CMOV (Conditional move instruction supported)",
Packit Service e18529
		"PAT (Page attribute table)",
Packit Service e18529
		"PSE-36 (36-bit page size extension)",
Packit Service e18529
		"PSN (Processor serial number present and enabled)",
Packit Service e18529
		"CLFSH (CLFLUSH instruction supported)",
Packit Service e18529
		NULL, /* 20 */
Packit Service e18529
		"DS (Debug store)",
Packit Service e18529
		"ACPI (ACPI supported)",
Packit Service e18529
		"MMX (MMX technology supported)",
Packit Service e18529
		"FXSR (FXSAVE and FXSTOR instructions supported)",
Packit Service e18529
		"SSE (Streaming SIMD extensions)",
Packit Service e18529
		"SSE2 (Streaming SIMD extensions 2)",
Packit Service e18529
		"SS (Self-snoop)",
Packit Service e18529
		"HTT (Multi-threading)",
Packit Service e18529
		"TM (Thermal monitor supported)",
Packit Service e18529
		NULL, /* 30 */
Packit Service e18529
		"PBE (Pending break enabled)" /* 31 */
Packit Service e18529
	};
Packit Service e18529
	const u8 *data = h->data;
Packit Service e18529
	const u8 *p = data + 0x08;
Packit Service e18529
	u32 eax, edx;
Packit Service e18529
	int sig = 0;
Packit Service e18529
	u16 type;
Packit Service e18529
Packit Service e18529
	type = (data[0x06] == 0xFE && h->length >= 0x2A) ?
Packit Service e18529
		WORD(data + 0x28) : data[0x06];
Packit Service e18529
Packit Service e18529
	/*
Packit Service e18529
	 * This might help learn about new processors supporting the
Packit Service e18529
	 * CPUID instruction or another form of identification.
Packit Service e18529
	 */
Packit Service 622062
	printf("%sID: %02X %02X %02X %02X %02X %02X %02X %02X\n",
Packit Service 622062
		prefix, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
Packit Service e18529
Packit Service e18529
	if (type == 0x05) /* 80386 */
Packit Service e18529
	{
Packit Service e18529
		u16 dx = WORD(p);
Packit Service e18529
		/*
Packit Service e18529
		 * 80386 have a different signature.
Packit Service e18529
		 */
Packit Service 622062
		printf("%sSignature: Type %u, Family %u, Major Stepping %u, Minor Stepping %u\n",
Packit Service 622062
			prefix, dx >> 12, (dx >> 8) & 0xF,
Packit Service e18529
			(dx >> 4) & 0xF, dx & 0xF);
Packit Service e18529
		return;
Packit Service e18529
	}
Packit Service e18529
	if (type == 0x06) /* 80486 */
Packit Service e18529
	{
Packit Service e18529
		u16 dx = WORD(p);
Packit Service e18529
		/*
Packit Service e18529
		 * Not all 80486 CPU support the CPUID instruction, we have to find
Packit Service e18529
		 * wether the one we have here does or not. Note that this trick
Packit Service e18529
		 * works only because we know that 80486 must be little-endian.
Packit Service e18529
		 */
Packit Service e18529
		if ((dx & 0x0F00) == 0x0400
Packit Service e18529
		 && ((dx & 0x00F0) == 0x0040 || (dx & 0x00F0) >= 0x0070)
Packit Service e18529
		 && ((dx & 0x000F) >= 0x0003))
Packit Service e18529
			sig = 1;
Packit Service e18529
		else
Packit Service e18529
		{
Packit Service 622062
			printf("%sSignature: Type %u, Family %u, Model %u, Stepping %u\n",
Packit Service 622062
				prefix, (dx >> 12) & 0x3, (dx >> 8) & 0xF,
Packit Service e18529
				(dx >> 4) & 0xF, dx & 0xF);
Packit Service e18529
			return;
Packit Service e18529
		}
Packit Service e18529
	}
Packit Service e18529
	else if ((type >= 0x100 && type <= 0x101) /* ARM */
Packit Service e18529
	      || (type >= 0x118 && type <= 0x119)) /* ARM */
Packit Service e18529
	{
Packit Service e18529
		u32 midr = DWORD(p);
Packit Service e18529
		/*
Packit Service e18529
		 * The format of this field was not defined for ARM processors
Packit Service e18529
		 * before version 3.1.0 of the SMBIOS specification, so we
Packit Service e18529
		 * silently skip it if it reads all zeroes.
Packit Service e18529
		 */
Packit Service e18529
		if (midr == 0)
Packit Service e18529
			return;
Packit Service 622062
		printf("%sSignature: Implementor 0x%02x, Variant 0x%x, Architecture %u, Part 0x%03x, Revision %u\n",
Packit Service 622062
			prefix, midr >> 24, (midr >> 20) & 0xF,
Packit Service e18529
			(midr >> 16) & 0xF, (midr >> 4) & 0xFFF, midr & 0xF);
Packit Service e18529
		return;
Packit Service e18529
	}
Packit Service e18529
	else if ((type >= 0x0B && type <= 0x15) /* Intel, Cyrix */
Packit Service e18529
	      || (type >= 0x28 && type <= 0x2F) /* Intel */
Packit Service e18529
	      || (type >= 0xA1 && type <= 0xB3) /* Intel */
Packit Service e18529
	      || type == 0xB5 /* Intel */
Packit Service e18529
	      || (type >= 0xB9 && type <= 0xC7) /* Intel */
Packit Service e18529
	      || (type >= 0xCD && type <= 0xCF) /* Intel */
Packit Service e18529
	      || (type >= 0xD2 && type <= 0xDB) /* VIA, Intel */
Packit Service e18529
	      || (type >= 0xDD && type <= 0xE0)) /* Intel */
Packit Service e18529
		sig = 1;
Packit Service e18529
	else if ((type >= 0x18 && type <= 0x1D) /* AMD */
Packit Service e18529
	      || type == 0x1F /* AMD */
Packit Service e18529
	      || (type >= 0x38 && type <= 0x3F) /* AMD */
Packit Service e18529
	      || (type >= 0x46 && type <= 0x4F) /* AMD */
Packit Service e18529
	      || (type >= 0x66 && type <= 0x6B) /* AMD */
Packit Service e18529
	      || (type >= 0x83 && type <= 0x8F) /* AMD */
Packit Service e18529
	      || (type >= 0xB6 && type <= 0xB7) /* AMD */
Packit Service e18529
	      || (type >= 0xE4 && type <= 0xEF)) /* AMD */
Packit Service e18529
		sig = 2;
Packit Service e18529
	else if (type == 0x01 || type == 0x02)
Packit Service e18529
	{
Packit Service e18529
		const char *version = dmi_string(h, data[0x10]);
Packit Service e18529
		/*
Packit Service e18529
		 * Some X86-class CPU have family "Other" or "Unknown". In this case,
Packit Service e18529
		 * we use the version string to determine if they are known to
Packit Service e18529
		 * support the CPUID instruction.
Packit Service e18529
		 */
Packit Service e18529
		if (strncmp(version, "Pentium III MMX", 15) == 0
Packit Service e18529
		 || strncmp(version, "Intel(R) Core(TM)2", 18) == 0
Packit Service e18529
		 || strncmp(version, "Intel(R) Pentium(R)", 19) == 0
Packit Service e18529
		 || strcmp(version, "Genuine Intel(R) CPU U1400") == 0)
Packit Service e18529
			sig = 1;
Packit Service e18529
		else if (strncmp(version, "AMD Athlon(TM)", 14) == 0
Packit Service e18529
		      || strncmp(version, "AMD Opteron(tm)", 15) == 0
Packit Service e18529
		      || strncmp(version, "Dual-Core AMD Opteron(tm)", 25) == 0)
Packit Service e18529
			sig = 2;
Packit Service e18529
		else
Packit Service e18529
			return;
Packit Service e18529
	}
Packit Service e18529
	else /* neither X86 nor ARM */
Packit Service e18529
		return;
Packit Service e18529
Packit Service e18529
	/*
Packit Service e18529
	 * Extra flags are now returned in the ECX register when one calls
Packit Service e18529
	 * the CPUID instruction. Their meaning is explained in table 3-5, but
Packit Service e18529
	 * DMI doesn't support this yet.
Packit Service e18529
	 */
Packit Service e18529
	eax = DWORD(p);
Packit Service e18529
	edx = DWORD(p + 4);
Packit Service e18529
	switch (sig)
Packit Service e18529
	{
Packit Service e18529
		case 1: /* Intel */
Packit Service 622062
			printf("%sSignature: Type %u, Family %u, Model %u, Stepping %u\n",
Packit Service 622062
				prefix, (eax >> 12) & 0x3,
Packit Service e18529
				((eax >> 20) & 0xFF) + ((eax >> 8) & 0x0F),
Packit Service e18529
				((eax >> 12) & 0xF0) + ((eax >> 4) & 0x0F),
Packit Service e18529
				eax & 0xF);
Packit Service e18529
			break;
Packit Service e18529
		case 2: /* AMD, publication #25481 revision 2.28 */
Packit Service 622062
			printf("%sSignature: Family %u, Model %u, Stepping %u\n",
Packit Service 622062
				prefix,
Packit Service e18529
				((eax >> 8) & 0xF) + (((eax >> 8) & 0xF) == 0xF ? (eax >> 20) & 0xFF : 0),
Packit Service e18529
				((eax >> 4) & 0xF) | (((eax >> 8) & 0xF) == 0xF ? (eax >> 12) & 0xF0 : 0),
Packit Service e18529
				eax & 0xF);
Packit Service e18529
			break;
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	edx = DWORD(p + 4);
Packit Service 622062
	printf("%sFlags:", prefix);
Packit Service e18529
	if ((edx & 0xBFEFFBFF) == 0)
Packit Service 622062
		printf(" None\n");
Packit Service e18529
	else
Packit Service e18529
	{
Packit Service e18529
		int i;
Packit Service e18529
Packit Service 622062
		printf("\n");
Packit Service e18529
		for (i = 0; i <= 31; i++)
Packit Service e18529
			if (flags[i] != NULL && edx & (1 << i))
Packit Service 622062
				printf("%s\t%s\n", prefix, flags[i]);
Packit Service e18529
	}
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_processor_voltage(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.5.4 */
Packit Service e18529
	static const char *voltage[] = {
Packit Service e18529
		"5.0 V", /* 0 */
Packit Service e18529
		"3.3 V",
Packit Service e18529
		"2.9 V" /* 2 */
Packit Service e18529
	};
Packit Service e18529
	int i;
Packit Service e18529
Packit Service e18529
	if (code & 0x80)
Packit Service 622062
		printf(" %.1f V", (float)(code & 0x7f) / 10);
Packit Service d409ef
	else if ((code & 0x07) == 0x00)
Packit Service d409ef
		printf(" Unknown");
Packit Service e18529
	else
Packit Service e18529
	{
Packit Service e18529
		for (i = 0; i <= 2; i++)
Packit Service e18529
			if (code & (1 << i))
Packit Service 622062
				printf(" %s", voltage[i]);
Packit Service e18529
	}
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_processor_frequency(const u8 *p)
Packit Service e18529
{
Packit Service e18529
	u16 code = WORD(p);
Packit Service e18529
Packit Service e18529
	if (code)
Packit Service 622062
		printf("%u MHz", code);
Packit Service e18529
	else
Packit Service 622062
		printf("Unknown");
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/* code is assumed to be a 3-bit value */
Packit Service e18529
static const char *dmi_processor_status(u8 code)
Packit Service e18529
{
Packit Service e18529
	static const char *status[] = {
Packit Service e18529
		"Unknown", /* 0x00 */
Packit Service e18529
		"Enabled",
Packit Service e18529
		"Disabled By User",
Packit Service e18529
		"Disabled By BIOS",
Packit Service e18529
		"Idle", /* 0x04 */
Packit Service e18529
		out_of_spec,
Packit Service e18529
		out_of_spec,
Packit Service e18529
		"Other" /* 0x07 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	return status[code];
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_processor_upgrade(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.5.5 */
Packit Service e18529
	static const char *upgrade[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"Daughter Board",
Packit Service e18529
		"ZIF Socket",
Packit Service e18529
		"Replaceable Piggy Back",
Packit Service e18529
		"None",
Packit Service e18529
		"LIF Socket",
Packit Service e18529
		"Slot 1",
Packit Service e18529
		"Slot 2",
Packit Service e18529
		"370-pin Socket",
Packit Service e18529
		"Slot A",
Packit Service e18529
		"Slot M",
Packit Service e18529
		"Socket 423",
Packit Service e18529
		"Socket A (Socket 462)",
Packit Service e18529
		"Socket 478",
Packit Service e18529
		"Socket 754",
Packit Service e18529
		"Socket 940",
Packit Service e18529
		"Socket 939",
Packit Service e18529
		"Socket mPGA604",
Packit Service e18529
		"Socket LGA771",
Packit Service e18529
		"Socket LGA775",
Packit Service e18529
		"Socket S1",
Packit Service e18529
		"Socket AM2",
Packit Service e18529
		"Socket F (1207)",
Packit Service e18529
		"Socket LGA1366",
Packit Service e18529
		"Socket G34",
Packit Service e18529
		"Socket AM3",
Packit Service e18529
		"Socket C32",
Packit Service e18529
		"Socket LGA1156",
Packit Service e18529
		"Socket LGA1567",
Packit Service e18529
		"Socket PGA988A",
Packit Service e18529
		"Socket BGA1288",
Packit Service e18529
		"Socket rPGA988B",
Packit Service e18529
		"Socket BGA1023",
Packit Service e18529
		"Socket BGA1224",
Packit Service e18529
		"Socket BGA1155",
Packit Service e18529
		"Socket LGA1356",
Packit Service e18529
		"Socket LGA2011",
Packit Service e18529
		"Socket FS1",
Packit Service e18529
		"Socket FS2",
Packit Service e18529
		"Socket FM1",
Packit Service e18529
		"Socket FM2",
Packit Service e18529
		"Socket LGA2011-3",
Packit Service e18529
		"Socket LGA1356-3",
Packit Service e18529
		"Socket LGA1150",
Packit Service e18529
		"Socket BGA1168",
Packit Service e18529
		"Socket BGA1234",
Packit Service e18529
		"Socket BGA1364",
Packit Service e18529
		"Socket AM4",
Packit Service e18529
		"Socket LGA1151",
Packit Service e18529
		"Socket BGA1356",
Packit Service e18529
		"Socket BGA1440",
Packit Service e18529
		"Socket BGA1515",
Packit Service e18529
		"Socket LGA3647-1",
Packit Service e18529
		"Socket SP3",
Packit Service e18529
		"Socket SP3r2",
Packit Service e18529
		"Socket LGA2066",
Packit Service e18529
		"Socket BGA1392",
Packit Service e18529
		"Socket BGA1510",
Packit Service e18529
		"Socket BGA1528" /* 0x3C */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x3C)
Packit Service e18529
		return upgrade[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_processor_cache(u16 code, const char *level, u16 ver)
Packit Service e18529
{
Packit Service e18529
	if (code == 0xFFFF)
Packit Service e18529
	{
Packit Service e18529
		if (ver >= 0x0203)
Packit Service 622062
			printf(" Not Provided");
Packit Service e18529
		else
Packit Service 622062
			printf(" No %s Cache", level);
Packit Service e18529
	}
Packit Service e18529
	else
Packit Service 622062
		printf(" 0x%04X", code);
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_processor_characteristics(u16 code, const char *prefix)
Packit Service e18529
{
Packit Service e18529
	/* 7.5.9 */
Packit Service e18529
	static const char *characteristics[] = {
Packit Service e18529
		"64-bit capable", /* 2 */
Packit Service e18529
		"Multi-Core",
Packit Service e18529
		"Hardware Thread",
Packit Service e18529
		"Execute Protection",
Packit Service e18529
		"Enhanced Virtualization",
Packit Service e18529
		"Power/Performance Control" /* 7 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if ((code & 0x00FC) == 0)
Packit Service 622062
		printf(" None\n");
Packit Service e18529
	else
Packit Service e18529
	{
Packit Service e18529
		int i;
Packit Service e18529
Packit Service 622062
		printf("\n");
Packit Service e18529
		for (i = 2; i <= 7; i++)
Packit Service e18529
			if (code & (1 << i))
Packit Service 622062
				printf("%s%s\n", prefix, characteristics[i - 2]);
Packit Service e18529
	}
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.6 Memory Controller Information (Type 5)
Packit Service e18529
 */
Packit Service e18529
Packit Service e18529
static const char *dmi_memory_controller_ed_method(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.6.1 */
Packit Service e18529
	static const char *method[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"None",
Packit Service e18529
		"8-bit Parity",
Packit Service e18529
		"32-bit ECC",
Packit Service e18529
		"64-bit ECC",
Packit Service e18529
		"128-bit ECC",
Packit Service e18529
		"CRC" /* 0x08 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x08)
Packit Service e18529
		return method[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_memory_controller_ec_capabilities(u8 code, const char *prefix)
Packit Service e18529
{
Packit Service e18529
	/* 7.6.2 */
Packit Service e18529
	static const char *capabilities[] = {
Packit Service e18529
		"Other", /* 0 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"None",
Packit Service e18529
		"Single-bit Error Correcting",
Packit Service e18529
		"Double-bit Error Correcting",
Packit Service e18529
		"Error Scrubbing" /* 5 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if ((code & 0x3F) == 0)
Packit Service 622062
		printf(" None\n");
Packit Service e18529
	else
Packit Service e18529
	{
Packit Service e18529
		int i;
Packit Service e18529
Packit Service 622062
		printf("\n");
Packit Service e18529
		for (i = 0; i <= 5; i++)
Packit Service e18529
			if (code & (1 << i))
Packit Service 622062
				printf("%s%s\n", prefix, capabilities[i]);
Packit Service e18529
	}
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_memory_controller_interleave(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.6.3 */
Packit Service e18529
	static const char *interleave[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"One-way Interleave",
Packit Service e18529
		"Two-way Interleave",
Packit Service e18529
		"Four-way Interleave",
Packit Service e18529
		"Eight-way Interleave",
Packit Service e18529
		"Sixteen-way Interleave" /* 0x07 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x07)
Packit Service e18529
		return interleave[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_memory_controller_speeds(u16 code, const char *prefix)
Packit Service e18529
{
Packit Service e18529
	/* 7.6.4 */
Packit Service e18529
	const char *speeds[] = {
Packit Service e18529
		"Other", /* 0 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"70 ns",
Packit Service e18529
		"60 ns",
Packit Service e18529
		"50 ns" /* 4 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if ((code & 0x001F) == 0)
Packit Service 622062
		printf(" None\n");
Packit Service e18529
	else
Packit Service e18529
	{
Packit Service e18529
		int i;
Packit Service e18529
Packit Service 622062
		printf("\n");
Packit Service e18529
		for (i = 0; i <= 4; i++)
Packit Service e18529
			if (code & (1 << i))
Packit Service 622062
				printf("%s%s\n", prefix, speeds[i]);
Packit Service e18529
	}
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_memory_controller_slots(u8 count, const u8 *p, const char *prefix)
Packit Service e18529
{
Packit Service e18529
	int i;
Packit Service e18529
Packit Service 622062
	printf("%sAssociated Memory Slots: %u\n",
Packit Service 622062
		prefix, count);
Packit Service e18529
	for (i = 0; i < count; i++)
Packit Service 622062
		printf("%s\t0x%04X\n",
Packit Service 622062
			prefix, WORD(p + sizeof(u16) * i));
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.7 Memory Module Information (Type 6)
Packit Service e18529
 */
Packit Service e18529
Packit Service 622062
static void dmi_memory_module_types(u16 code, const char *sep)
Packit Service e18529
{
Packit Service e18529
	/* 7.7.1 */
Packit Service e18529
	static const char *types[] = {
Packit Service e18529
		"Other", /* 0 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"Standard",
Packit Service e18529
		"FPM",
Packit Service e18529
		"EDO",
Packit Service e18529
		"Parity",
Packit Service e18529
		"ECC",
Packit Service e18529
		"SIMM",
Packit Service e18529
		"DIMM",
Packit Service e18529
		"Burst EDO",
Packit Service e18529
		"SDRAM" /* 10 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if ((code & 0x07FF) == 0)
Packit Service 622062
		printf(" None");
Packit Service e18529
	else
Packit Service e18529
	{
Packit Service e18529
		int i;
Packit Service e18529
Packit Service e18529
		for (i = 0; i <= 10; i++)
Packit Service e18529
			if (code & (1 << i))
Packit Service 622062
				printf("%s%s", sep, types[i]);
Packit Service e18529
	}
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static void dmi_memory_module_connections(u8 code)
Packit Service e18529
{
Packit Service e18529
	if (code == 0xFF)
Packit Service 622062
		printf(" None");
Packit Service e18529
	else
Packit Service 622062
	{
Packit Service 622062
		if ((code & 0xF0) != 0xF0)
Packit Service 622062
			printf(" %u", code >> 4);
Packit Service 622062
		if ((code & 0x0F) != 0x0F)
Packit Service 622062
			printf(" %u", code & 0x0F);
Packit Service 622062
	}
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_memory_module_speed(u8 code)
Packit Service e18529
{
Packit Service e18529
	if (code == 0)
Packit Service 622062
		printf(" Unknown");
Packit Service e18529
	else
Packit Service 622062
		printf(" %u ns", code);
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_memory_module_size(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.7.2 */
Packit Service e18529
	switch (code & 0x7F)
Packit Service e18529
	{
Packit Service e18529
		case 0x7D:
Packit Service 622062
			printf(" Not Determinable");
Packit Service e18529
			break;
Packit Service e18529
		case 0x7E:
Packit Service 622062
			printf(" Disabled");
Packit Service e18529
			break;
Packit Service e18529
		case 0x7F:
Packit Service 622062
			printf(" Not Installed");
Packit Service e18529
			return;
Packit Service e18529
		default:
Packit Service 622062
			printf(" %u MB", 1 << (code & 0x7F));
Packit Service e18529
	}
Packit Service 622062
Packit Service 622062
	if (code & 0x80)
Packit Service 622062
		printf(" (Double-bank Connection)");
Packit Service 622062
	else
Packit Service 622062
		printf(" (Single-bank Connection)");
Packit Service e18529
}
Packit Service e18529
Packit Service 97f994
static void dmi_memory_module_error(u8 code)
Packit Service e18529
{
Packit Service 97f994
	static const char *status[] = {
Packit Service 97f994
		"OK", /* 0x00 */
Packit Service 97f994
		"Uncorrectable Errors",
Packit Service 97f994
		"Correctable Errors",
Packit Service 97f994
		"Correctable and Uncorrectable Errors" /* 0x03 */
Packit Service 97f994
	};
Packit Service 97f994
Packit Service e18529
	if (code & (1 << 2))
Packit Service 622062
		printf(" See Event Log\n");
Packit Service e18529
	else
Packit Service 97f994
		printf(" %s\n", status[code & 0x03]);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.8 Cache Information (Type 7)
Packit Service e18529
 */
Packit Service e18529
Packit Service e18529
static const char *dmi_cache_mode(u8 code)
Packit Service e18529
{
Packit Service e18529
	static const char *mode[] = {
Packit Service e18529
		"Write Through", /* 0x00 */
Packit Service e18529
		"Write Back",
Packit Service e18529
		"Varies With Memory Address",
Packit Service e18529
		"Unknown" /* 0x03 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	return mode[code];
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/* code is assumed to be a 2-bit value */
Packit Service e18529
static const char *dmi_cache_location(u8 code)
Packit Service e18529
{
Packit Service e18529
	static const char *location[4] = {
Packit Service e18529
		"Internal", /* 0x00 */
Packit Service e18529
		"External",
Packit Service e18529
		out_of_spec, /* 0x02 */
Packit Service e18529
		"Unknown" /* 0x03 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	return location[code];
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_cache_size_2(u32 code)
Packit Service 622062
{
Packit Service 8b3d66
	u64 size;
Packit Service 8b3d66
Packit Service e18529
	if (code & 0x80000000)
Packit Service e18529
	{
Packit Service e18529
		code &= 0x7FFFFFFFLU;
Packit Service 8b3d66
		size.l = code << 6;
Packit Service 8b3d66
		size.h = code >> 26;
Packit Service e18529
	}
Packit Service e18529
	else
Packit Service 8b3d66
	{
Packit Service 8b3d66
		size.l = code;
Packit Service 8b3d66
		size.h = 0;
Packit Service 8b3d66
	}
Packit Service 8b3d66
Packit Service 8b3d66
	/* Use a more convenient unit for large cache size */
Packit Service 8b3d66
	dmi_print_memory_size(size, 1);
Packit Service e18529
}
Packit Service e18529
Packit Service 2d7cf6
static void dmi_cache_size(u16 code)
Packit Service 2d7cf6
{
Packit Service 2d7cf6
	dmi_cache_size_2((((u32)code & 0x8000LU) << 16) | (code & 0x7FFFLU));
Packit Service 2d7cf6
}
Packit Service 2d7cf6
Packit Service 622062
static void dmi_cache_types(u16 code, const char *sep)
Packit Service e18529
{
Packit Service e18529
	/* 7.8.2 */
Packit Service e18529
	static const char *types[] = {
Packit Service e18529
		"Other", /* 0 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"Non-burst",
Packit Service e18529
		"Burst",
Packit Service e18529
		"Pipeline Burst",
Packit Service e18529
		"Synchronous",
Packit Service e18529
		"Asynchronous" /* 6 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if ((code & 0x007F) == 0)
Packit Service 622062
		printf(" None");
Packit Service e18529
	else
Packit Service e18529
	{
Packit Service e18529
		int i;
Packit Service e18529
Packit Service e18529
		for (i = 0; i <= 6; i++)
Packit Service e18529
			if (code & (1 << i))
Packit Service 622062
				printf("%s%s", sep, types[i]);
Packit Service e18529
	}
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_cache_ec_type(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.8.3 */
Packit Service e18529
	static const char *type[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"None",
Packit Service e18529
		"Parity",
Packit Service e18529
		"Single-bit ECC",
Packit Service e18529
		"Multi-bit ECC" /* 0x06 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x06)
Packit Service e18529
		return type[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_cache_type(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.8.4 */
Packit Service e18529
	static const char *type[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"Instruction",
Packit Service e18529
		"Data",
Packit Service e18529
		"Unified" /* 0x05 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x05)
Packit Service e18529
		return type[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_cache_associativity(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.8.5 */
Packit Service e18529
	static const char *type[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"Direct Mapped",
Packit Service e18529
		"2-way Set-associative",
Packit Service e18529
		"4-way Set-associative",
Packit Service e18529
		"Fully Associative",
Packit Service e18529
		"8-way Set-associative",
Packit Service e18529
		"16-way Set-associative",
Packit Service e18529
		"12-way Set-associative",
Packit Service e18529
		"24-way Set-associative",
Packit Service e18529
		"32-way Set-associative",
Packit Service e18529
		"48-way Set-associative",
Packit Service e18529
		"64-way Set-associative",
Packit Service e18529
		"20-way Set-associative" /* 0x0E */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x0E)
Packit Service e18529
		return type[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.9 Port Connector Information (Type 8)
Packit Service e18529
 */
Packit Service e18529
Packit Service e18529
static const char *dmi_port_connector_type(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.9.2 */
Packit Service e18529
	static const char *type[] = {
Packit Service e18529
		"None", /* 0x00 */
Packit Service e18529
		"Centronics",
Packit Service e18529
		"Mini Centronics",
Packit Service e18529
		"Proprietary",
Packit Service e18529
		"DB-25 male",
Packit Service e18529
		"DB-25 female",
Packit Service e18529
		"DB-15 male",
Packit Service e18529
		"DB-15 female",
Packit Service e18529
		"DB-9 male",
Packit Service e18529
		"DB-9 female",
Packit Service e18529
		"RJ-11",
Packit Service e18529
		"RJ-45",
Packit Service e18529
		"50 Pin MiniSCSI",
Packit Service e18529
		"Mini DIN",
Packit Service e18529
		"Micro DIN",
Packit Service e18529
		"PS/2",
Packit Service e18529
		"Infrared",
Packit Service e18529
		"HP-HIL",
Packit Service e18529
		"Access Bus (USB)",
Packit Service e18529
		"SSA SCSI",
Packit Service e18529
		"Circular DIN-8 male",
Packit Service e18529
		"Circular DIN-8 female",
Packit Service e18529
		"On Board IDE",
Packit Service e18529
		"On Board Floppy",
Packit Service e18529
		"9 Pin Dual Inline (pin 10 cut)",
Packit Service e18529
		"25 Pin Dual Inline (pin 26 cut)",
Packit Service e18529
		"50 Pin Dual Inline",
Packit Service e18529
		"68 Pin Dual Inline",
Packit Service e18529
		"On Board Sound Input From CD-ROM",
Packit Service e18529
		"Mini Centronics Type-14",
Packit Service e18529
		"Mini Centronics Type-26",
Packit Service e18529
		"Mini Jack (headphones)",
Packit Service e18529
		"BNC",
Packit Service e18529
		"IEEE 1394",
Packit Service e18529
		"SAS/SATA Plug Receptacle",
Packit Service e18529
		"USB Type-C Receptacle" /* 0x23 */
Packit Service e18529
	};
Packit Service e18529
	static const char *type_0xA0[] = {
Packit Service e18529
		"PC-98", /* 0xA0 */
Packit Service e18529
		"PC-98 Hireso",
Packit Service e18529
		"PC-H98",
Packit Service e18529
		"PC-98 Note",
Packit Service e18529
		"PC-98 Full" /* 0xA4 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code <= 0x23)
Packit Service e18529
		return type[code];
Packit Service e18529
	if (code >= 0xA0 && code <= 0xA4)
Packit Service e18529
		return type_0xA0[code - 0xA0];
Packit Service e18529
	if (code == 0xFF)
Packit Service e18529
		return "Other";
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_port_type(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.9.3 */
Packit Service e18529
	static const char *type[] = {
Packit Service e18529
		"None", /* 0x00 */
Packit Service e18529
		"Parallel Port XT/AT Compatible",
Packit Service e18529
		"Parallel Port PS/2",
Packit Service e18529
		"Parallel Port ECP",
Packit Service e18529
		"Parallel Port EPP",
Packit Service e18529
		"Parallel Port ECP/EPP",
Packit Service e18529
		"Serial Port XT/AT Compatible",
Packit Service e18529
		"Serial Port 16450 Compatible",
Packit Service e18529
		"Serial Port 16550 Compatible",
Packit Service e18529
		"Serial Port 16550A Compatible",
Packit Service e18529
		"SCSI Port",
Packit Service e18529
		"MIDI Port",
Packit Service e18529
		"Joystick Port",
Packit Service e18529
		"Keyboard Port",
Packit Service e18529
		"Mouse Port",
Packit Service e18529
		"SSA SCSI",
Packit Service e18529
		"USB",
Packit Service e18529
		"Firewire (IEEE P1394)",
Packit Service e18529
		"PCMCIA Type I",
Packit Service e18529
		"PCMCIA Type II",
Packit Service e18529
		"PCMCIA Type III",
Packit Service e18529
		"Cardbus",
Packit Service e18529
		"Access Bus Port",
Packit Service e18529
		"SCSI II",
Packit Service e18529
		"SCSI Wide",
Packit Service e18529
		"PC-98",
Packit Service e18529
		"PC-98 Hireso",
Packit Service e18529
		"PC-H98",
Packit Service e18529
		"Video Port",
Packit Service e18529
		"Audio Port",
Packit Service e18529
		"Modem Port",
Packit Service e18529
		"Network Port",
Packit Service e18529
		"SATA",
Packit Service e18529
		"SAS" /* 0x21 */
Packit Service e18529
	};
Packit Service e18529
	static const char *type_0xA0[] = {
Packit Service e18529
		"8251 Compatible", /* 0xA0 */
Packit Service e18529
		"8251 FIFO Compatible" /* 0xA1 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code <= 0x21)
Packit Service e18529
		return type[code];
Packit Service e18529
	if (code >= 0xA0 && code <= 0xA1)
Packit Service e18529
		return type_0xA0[code - 0xA0];
Packit Service e18529
	if (code == 0xFF)
Packit Service e18529
		return "Other";
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.10 System Slots (Type 9)
Packit Service e18529
 */
Packit Service e18529
Packit Service e18529
static const char *dmi_slot_type(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.10.1 */
Packit Service e18529
	static const char *type[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"ISA",
Packit Service e18529
		"MCA",
Packit Service e18529
		"EISA",
Packit Service e18529
		"PCI",
Packit Service e18529
		"PC Card (PCMCIA)",
Packit Service e18529
		"VLB",
Packit Service e18529
		"Proprietary",
Packit Service e18529
		"Processor Card",
Packit Service e18529
		"Proprietary Memory Card",
Packit Service e18529
		"I/O Riser Card",
Packit Service e18529
		"NuBus",
Packit Service e18529
		"PCI-66",
Packit Service e18529
		"AGP",
Packit Service e18529
		"AGP 2x",
Packit Service e18529
		"AGP 4x",
Packit Service e18529
		"PCI-X",
Packit Service e18529
		"AGP 8x",
Packit Service e18529
		"M.2 Socket 1-DP",
Packit Service e18529
		"M.2 Socket 1-SD",
Packit Service e18529
		"M.2 Socket 2",
Packit Service e18529
		"M.2 Socket 3",
Packit Service e18529
		"MXM Type I",
Packit Service e18529
		"MXM Type II",
Packit Service e18529
		"MXM Type III",
Packit Service e18529
		"MXM Type III-HE",
Packit Service e18529
		"MXM Type IV",
Packit Service e18529
		"MXM 3.0 Type A",
Packit Service e18529
		"MXM 3.0 Type B",
Packit Service e18529
		"PCI Express 2 SFF-8639",
Packit Service e18529
		"PCI Express 3 SFF-8639",
Packit Service e18529
		"PCI Express Mini 52-pin with bottom-side keep-outs",
Packit Service e18529
		"PCI Express Mini 52-pin without bottom-side keep-outs",
Packit Service e18529
		"PCI Express Mini 76-pin" /* 0x23 */
Packit Service e18529
	};
Packit Service 0bfd26
	static const char *type_0x30[] = {
Packit Service 0bfd26
		"CXL FLexbus 1.0" /* 0x30 */
Packit Service 0bfd26
	};
Packit Service e18529
	static const char *type_0xA0[] = {
Packit Service e18529
		"PC-98/C20", /* 0xA0 */
Packit Service e18529
		"PC-98/C24",
Packit Service e18529
		"PC-98/E",
Packit Service e18529
		"PC-98/Local Bus",
Packit Service e18529
		"PC-98/Card",
Packit Service e18529
		"PCI Express",
Packit Service e18529
		"PCI Express x1",
Packit Service e18529
		"PCI Express x2",
Packit Service e18529
		"PCI Express x4",
Packit Service e18529
		"PCI Express x8",
Packit Service e18529
		"PCI Express x16",
Packit Service e18529
		"PCI Express 2",
Packit Service e18529
		"PCI Express 2 x1",
Packit Service e18529
		"PCI Express 2 x2",
Packit Service e18529
		"PCI Express 2 x4",
Packit Service e18529
		"PCI Express 2 x8",
Packit Service e18529
		"PCI Express 2 x16",
Packit Service e18529
		"PCI Express 3",
Packit Service e18529
		"PCI Express 3 x1",
Packit Service e18529
		"PCI Express 3 x2",
Packit Service e18529
		"PCI Express 3 x4",
Packit Service e18529
		"PCI Express 3 x8",
Packit Service 0bfd26
		"PCI Express 3 x16",
Packit Service 0bfd26
		out_of_spec, /* 0xB7 */
Packit Service 0bfd26
		"PCI Express 4",
Packit Service 0bfd26
		"PCI Express 4 x1",
Packit Service 0bfd26
		"PCI Express 4 x2",
Packit Service 0bfd26
		"PCI Express 4 x4",
Packit Service 0bfd26
		"PCI Express 4 x8",
Packit Service 0bfd26
		"PCI Express 4 x16" /* 0xBD */
Packit Service e18529
	};
Packit Service e18529
	/*
Packit Service e18529
	 * Note to developers: when adding entries to these lists, check if
Packit Service e18529
	 * function dmi_slot_id below needs updating too.
Packit Service e18529
	 */
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x23)
Packit Service e18529
		return type[code - 0x01];
Packit Service 0bfd26
	if (code == 0x30)
Packit Service 0bfd26
		return type_0x30[code - 0x30];
Packit Service 0bfd26
	if (code >= 0xA0 && code <= 0xBD)
Packit Service e18529
		return type_0xA0[code - 0xA0];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_slot_bus_width(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.10.2 */
Packit Service e18529
	static const char *width[] = {
Packit Service e18529
		"", /* 0x01, "Other" */
Packit Service e18529
		"", /* "Unknown" */
Packit Service e18529
		"8-bit ",
Packit Service e18529
		"16-bit ",
Packit Service e18529
		"32-bit ",
Packit Service e18529
		"64-bit ",
Packit Service e18529
		"128-bit ",
Packit Service e18529
		"x1 ",
Packit Service e18529
		"x2 ",
Packit Service e18529
		"x4 ",
Packit Service e18529
		"x8 ",
Packit Service e18529
		"x12 ",
Packit Service e18529
		"x16 ",
Packit Service e18529
		"x32 " /* 0x0E */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x0E)
Packit Service e18529
		return width[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_slot_current_usage(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.10.3 */
Packit Service e18529
	static const char *usage[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"Available",
Packit Service e18529
		"In Use",
Packit Service e18529
		"Unavailable" /* 0x05 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x05)
Packit Service e18529
		return usage[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_slot_length(u8 code)
Packit Service e18529
{
Packit Service a6167d
	/* 7.10.4 */
Packit Service e18529
	static const char *length[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"Short",
Packit Service c5a439
		"Long",
Packit Service c5a439
		"2.5\" drive form factor",
Packit Service c5a439
		"3.5\" drive form factor" /* 0x06 */
Packit Service e18529
	};
Packit Service e18529
Packit Service c5a439
	if (code >= 0x01 && code <= 0x06)
Packit Service e18529
		return length[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_slot_id(u8 code1, u8 code2, u8 type, const char *prefix)
Packit Service e18529
{
Packit Service e18529
	/* 7.10.5 */
Packit Service e18529
	switch (type)
Packit Service e18529
	{
Packit Service e18529
		case 0x04: /* MCA */
Packit Service 622062
			printf("%sID: %u\n", prefix, code1);
Packit Service e18529
			break;
Packit Service e18529
		case 0x05: /* EISA */
Packit Service 622062
			printf("%sID: %u\n", prefix, code1);
Packit Service e18529
			break;
Packit Service e18529
		case 0x06: /* PCI */
Packit Service e18529
		case 0x0E: /* PCI */
Packit Service e18529
		case 0x0F: /* AGP */
Packit Service e18529
		case 0x10: /* AGP */
Packit Service e18529
		case 0x11: /* AGP */
Packit Service e18529
		case 0x12: /* PCI-X */
Packit Service e18529
		case 0x13: /* AGP */
Packit Service e18529
		case 0x1F: /* PCI Express 2 */
Packit Service e18529
		case 0x20: /* PCI Express 3 */
Packit Service e18529
		case 0x21: /* PCI Express Mini */
Packit Service e18529
		case 0x22: /* PCI Express Mini */
Packit Service e18529
		case 0x23: /* PCI Express Mini */
Packit Service e18529
		case 0xA5: /* PCI Express */
Packit Service e18529
		case 0xA6: /* PCI Express */
Packit Service e18529
		case 0xA7: /* PCI Express */
Packit Service e18529
		case 0xA8: /* PCI Express */
Packit Service e18529
		case 0xA9: /* PCI Express */
Packit Service e18529
		case 0xAA: /* PCI Express */
Packit Service e18529
		case 0xAB: /* PCI Express 2 */
Packit Service e18529
		case 0xAC: /* PCI Express 2 */
Packit Service e18529
		case 0xAD: /* PCI Express 2 */
Packit Service e18529
		case 0xAE: /* PCI Express 2 */
Packit Service e18529
		case 0xAF: /* PCI Express 2 */
Packit Service e18529
		case 0xB0: /* PCI Express 2 */
Packit Service e18529
		case 0xB1: /* PCI Express 3 */
Packit Service e18529
		case 0xB2: /* PCI Express 3 */
Packit Service e18529
		case 0xB3: /* PCI Express 3 */
Packit Service e18529
		case 0xB4: /* PCI Express 3 */
Packit Service e18529
		case 0xB5: /* PCI Express 3 */
Packit Service e18529
		case 0xB6: /* PCI Express 3 */
Packit Service 0bfd26
		case 0xB8: /* PCI Express 4 */
Packit Service 0bfd26
		case 0xB9: /* PCI Express 4 */
Packit Service 0bfd26
		case 0xBA: /* PCI Express 4 */
Packit Service 0bfd26
		case 0xBB: /* PCI Express 4 */
Packit Service 0bfd26
		case 0xBC: /* PCI Express 4 */
Packit Service 0bfd26
		case 0xBD: /* PCI Express 4 */
Packit Service 622062
			printf("%sID: %u\n", prefix, code1);
Packit Service e18529
			break;
Packit Service e18529
		case 0x07: /* PCMCIA */
Packit Service 622062
			printf("%sID: Adapter %u, Socket %u\n", prefix, code1, code2);
Packit Service e18529
			break;
Packit Service e18529
	}
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_slot_characteristics(u8 code1, u8 code2, const char *prefix)
Packit Service e18529
{
Packit Service e18529
	/* 7.10.6 */
Packit Service e18529
	static const char *characteristics1[] = {
Packit Service e18529
		"5.0 V is provided", /* 1 */
Packit Service e18529
		"3.3 V is provided",
Packit Service e18529
		"Opening is shared",
Packit Service e18529
		"PC Card-16 is supported",
Packit Service e18529
		"Cardbus is supported",
Packit Service e18529
		"Zoom Video is supported",
Packit Service e18529
		"Modem ring resume is supported" /* 7 */
Packit Service e18529
	};
Packit Service e18529
	/* 7.10.7 */
Packit Service e18529
	static const char *characteristics2[] = {
Packit Service e18529
		"PME signal is supported", /* 0 */
Packit Service e18529
		"Hot-plug devices are supported",
Packit Service e18529
		"SMBus signal is supported",
Packit Service e18529
		"PCIe slot bifurcation is supported" /* 3 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code1 & (1 << 0))
Packit Service 622062
		printf(" Unknown\n");
Packit Service e18529
	else if ((code1 & 0xFE) == 0 && (code2 & 0x07) == 0)
Packit Service 622062
		printf(" None\n");
Packit Service e18529
	else
Packit Service e18529
	{
Packit Service e18529
		int i;
Packit Service e18529
Packit Service 622062
		printf("\n");
Packit Service e18529
		for (i = 1; i <= 7; i++)
Packit Service e18529
			if (code1 & (1 << i))
Packit Service 622062
				printf("%s%s\n", prefix, characteristics1[i - 1]);
Packit Service e18529
		for (i = 0; i <= 3; i++)
Packit Service e18529
			if (code2 & (1 << i))
Packit Service 622062
				printf("%s%s\n", prefix, characteristics2[i]);
Packit Service e18529
	}
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_slot_segment_bus_func(u16 code1, u8 code2, u8 code3, const char *prefix)
Packit Service e18529
{
Packit Service e18529
	/* 7.10.8 */
Packit Service e18529
	if (!(code1 == 0xFFFF && code2 == 0xFF && code3 == 0xFF))
Packit Service 622062
		printf("%sBus Address: %04x:%02x:%02x.%x\n",
Packit Service 622062
		       prefix, code1, code2, code3 >> 3, code3 & 0x7);
Packit Service f18cbe
}
Packit Service f18cbe
Packit Service 568207
static void dmi_slot_peers(u8 n, const u8 *data, const char *prefix)
Packit Service 568207
{
Packit Service 568207
	int i;
Packit Service 568207
Packit Service 568207
	for (i = 1; i <= n; i++, data += 5)
Packit Service 568207
		printf("%sPeer Device %d: %04x:%02x:%02x.%x (Width %u)\n",
Packit Service 568207
		       prefix, i, WORD(data), data[2], data[3] >> 3,
Packit Service 568207
		       data[3] & 0x07, data[4]);
Packit Service 568207
}
Packit Service 568207
Packit Service e18529
/*
Packit Service e18529
 * 7.11 On Board Devices Information (Type 10)
Packit Service e18529
 */
Packit Service e18529
Packit Service e18529
static const char *dmi_on_board_devices_type(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.11.1 and 7.42.2 */
Packit Service e18529
	static const char *type[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"Video",
Packit Service e18529
		"SCSI Controller",
Packit Service e18529
		"Ethernet",
Packit Service e18529
		"Token Ring",
Packit Service e18529
		"Sound",
Packit Service e18529
		"PATA Controller",
Packit Service e18529
		"SATA Controller",
Packit Service e18529
		"SAS Controller" /* 0x0A */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x0A)
Packit Service e18529
		return type[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_on_board_devices(const struct dmi_header *h, const char *prefix)
Packit Service e18529
{
Packit Service e18529
	u8 *p = h->data + 4;
Packit Service e18529
	u8 count = (h->length - 0x04) / 2;
Packit Service e18529
	int i;
Packit Service e18529
Packit Service e18529
	for (i = 0; i < count; i++)
Packit Service e18529
	{
Packit Service e18529
		if (count == 1)
Packit Service 622062
			printf("%sOn Board Device Information\n",
Packit Service 622062
				prefix);
Packit Service e18529
		else
Packit Service 622062
			printf("%sOn Board Device %d Information\n",
Packit Service 622062
				prefix, i + 1);
Packit Service 622062
		printf("%s\tType: %s\n",
Packit Service 622062
			prefix, dmi_on_board_devices_type(p[2 * i] & 0x7F));
Packit Service 622062
		printf("%s\tStatus: %s\n",
Packit Service 622062
			prefix, p[2 * i] & 0x80 ? "Enabled" : "Disabled");
Packit Service 622062
		printf("%s\tDescription: %s\n",
Packit Service 622062
			prefix, dmi_string(h, p[2 * i + 1]));
Packit Service e18529
	}
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.12 OEM Strings (Type 11)
Packit Service e18529
 */
Packit Service e18529
Packit Service 622062
static void dmi_oem_strings(const struct dmi_header *h, const char *prefix)
Packit Service e18529
{
Packit Service e18529
	u8 *p = h->data + 4;
Packit Service e18529
	u8 count = p[0x00];
Packit Service e18529
	int i;
Packit Service e18529
Packit Service e18529
	for (i = 1; i <= count; i++)
Packit Service 622062
		printf("%sString %d: %s\n",
Packit Service 622062
			prefix, i, dmi_string(h, i));
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.13 System Configuration Options (Type 12)
Packit Service e18529
 */
Packit Service e18529
Packit Service 622062
static void dmi_system_configuration_options(const struct dmi_header *h, const char *prefix)
Packit Service e18529
{
Packit Service e18529
	u8 *p = h->data + 4;
Packit Service e18529
	u8 count = p[0x00];
Packit Service e18529
	int i;
Packit Service e18529
Packit Service e18529
	for (i = 1; i <= count; i++)
Packit Service 622062
		printf("%sOption %d: %s\n",
Packit Service 622062
			prefix, i, dmi_string(h, i));
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.14 BIOS Language Information (Type 13)
Packit Service e18529
 */
Packit Service e18529
Packit Service 622062
static void dmi_bios_languages(const struct dmi_header *h, const char *prefix)
Packit Service e18529
{
Packit Service e18529
	u8 *p = h->data + 4;
Packit Service e18529
	u8 count = p[0x00];
Packit Service e18529
	int i;
Packit Service e18529
Packit Service e18529
	for (i = 1; i <= count; i++)
Packit Service 622062
		printf("%s%s\n",
Packit Service 622062
			prefix, dmi_string(h, i));
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_bios_language_format(u8 code)
Packit Service e18529
{
Packit Service e18529
	if (code & 0x01)
Packit Service e18529
		return "Abbreviated";
Packit Service e18529
	else
Packit Service e18529
		return "Long";
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.15 Group Associations (Type 14)
Packit Service e18529
 */
Packit Service e18529
Packit Service 622062
static void dmi_group_associations_items(u8 count, const u8 *p, const char *prefix)
Packit Service e18529
{
Packit Service e18529
	int i;
Packit Service e18529
Packit Service e18529
	for (i = 0; i < count; i++)
Packit Service e18529
	{
Packit Service 622062
		printf("%s0x%04X (%s)\n",
Packit Service 622062
			prefix, WORD(p + 3 * i + 1),
Packit Service e18529
			dmi_smbios_structure_type(p[3 * i]));
Packit Service e18529
	}
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.16 System Event Log (Type 15)
Packit Service e18529
 */
Packit Service e18529
Packit Service e18529
static const char *dmi_event_log_method(u8 code)
Packit Service e18529
{
Packit Service e18529
	static const char *method[] = {
Packit Service e18529
		"Indexed I/O, one 8-bit index port, one 8-bit data port", /* 0x00 */
Packit Service e18529
		"Indexed I/O, two 8-bit index ports, one 8-bit data port",
Packit Service e18529
		"Indexed I/O, one 16-bit index port, one 8-bit data port",
Packit Service e18529
		"Memory-mapped physical 32-bit address",
Packit Service e18529
		"General-purpose non-volatile data functions" /* 0x04 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code <= 0x04)
Packit Service e18529
		return method[code];
Packit Service e18529
	if (code >= 0x80)
Packit Service e18529
		return "OEM-specific";
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static void dmi_event_log_status(u8 code)
Packit Service e18529
{
Packit Service e18529
	static const char *valid[] = {
Packit Service e18529
		"Invalid", /* 0 */
Packit Service e18529
		"Valid" /* 1 */
Packit Service e18529
	};
Packit Service e18529
	static const char *full[] = {
Packit Service e18529
		"Not Full", /* 0 */
Packit Service e18529
		"Full" /* 1 */
Packit Service e18529
	};
Packit Service e18529
Packit Service 622062
	printf(" %s, %s",
Packit Service e18529
		valid[(code >> 0) & 1], full[(code >> 1) & 1]);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static void dmi_event_log_address(u8 method, const u8 *p)
Packit Service e18529
{
Packit Service e18529
	/* 7.16.3 */
Packit Service e18529
	switch (method)
Packit Service e18529
	{
Packit Service e18529
		case 0x00:
Packit Service e18529
		case 0x01:
Packit Service e18529
		case 0x02:
Packit Service 622062
			printf(" Index 0x%04X, Data 0x%04X", WORD(p), WORD(p + 2));
Packit Service e18529
			break;
Packit Service e18529
		case 0x03:
Packit Service 622062
			printf(" 0x%08X", DWORD(p));
Packit Service e18529
			break;
Packit Service e18529
		case 0x04:
Packit Service 622062
			printf(" 0x%04X", WORD(p));
Packit Service e18529
			break;
Packit Service e18529
		default:
Packit Service 622062
			printf(" Unknown");
Packit Service e18529
	}
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_event_log_header_type(u8 code)
Packit Service e18529
{
Packit Service e18529
	static const char *type[] = {
Packit Service e18529
		"No Header", /* 0x00 */
Packit Service e18529
		"Type 1" /* 0x01 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code <= 0x01)
Packit Service e18529
		return type[code];
Packit Service e18529
	if (code >= 0x80)
Packit Service e18529
		return "OEM-specific";
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_event_log_descriptor_type(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.16.6.1 */
Packit Service e18529
	static const char *type[] = {
Packit Service e18529
		NULL, /* 0x00 */
Packit Service e18529
		"Single-bit ECC memory error",
Packit Service e18529
		"Multi-bit ECC memory error",
Packit Service e18529
		"Parity memory error",
Packit Service e18529
		"Bus timeout",
Packit Service e18529
		"I/O channel block",
Packit Service e18529
		"Software NMI",
Packit Service e18529
		"POST memory resize",
Packit Service e18529
		"POST error",
Packit Service e18529
		"PCI parity error",
Packit Service e18529
		"PCI system error",
Packit Service e18529
		"CPU failure",
Packit Service e18529
		"EISA failsafe timer timeout",
Packit Service e18529
		"Correctable memory log disabled",
Packit Service e18529
		"Logging disabled",
Packit Service e18529
		NULL, /* 0x0F */
Packit Service e18529
		"System limit exceeded",
Packit Service e18529
		"Asynchronous hardware timer expired",
Packit Service e18529
		"System configuration information",
Packit Service e18529
		"Hard disk information",
Packit Service e18529
		"System reconfigured",
Packit Service e18529
		"Uncorrectable CPU-complex error",
Packit Service e18529
		"Log area reset/cleared",
Packit Service e18529
		"System boot" /* 0x17 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code <= 0x17 && type[code] != NULL)
Packit Service e18529
		return type[code];
Packit Service e18529
	if (code >= 0x80 && code <= 0xFE)
Packit Service e18529
		return "OEM-specific";
Packit Service e18529
	if (code == 0xFF)
Packit Service e18529
		return "End of log";
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_event_log_descriptor_format(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.16.6.2 */
Packit Service e18529
	static const char *format[] = {
Packit Service e18529
		"None", /* 0x00 */
Packit Service e18529
		"Handle",
Packit Service e18529
		"Multiple-event",
Packit Service e18529
		"Multiple-event handle",
Packit Service e18529
		"POST results bitmap",
Packit Service e18529
		"System management",
Packit Service e18529
		"Multiple-event system management" /* 0x06 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code <= 0x06)
Packit Service e18529
		return format[code];
Packit Service e18529
	if (code >= 0x80)
Packit Service e18529
		return "OEM-specific";
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_event_log_descriptors(u8 count, u8 len, const u8 *p, const char *prefix)
Packit Service e18529
{
Packit Service e18529
	/* 7.16.1 */
Packit Service e18529
	int i;
Packit Service e18529
Packit Service e18529
	for (i = 0; i < count; i++)
Packit Service e18529
	{
Packit Service e18529
		if (len >= 0x02)
Packit Service e18529
		{
Packit Service 622062
			printf("%sDescriptor %u: %s\n",
Packit Service 622062
				prefix, i + 1, dmi_event_log_descriptor_type(p[i * len]));
Packit Service 622062
			printf("%sData Format %u: %s\n",
Packit Service 622062
				prefix, i + 1, dmi_event_log_descriptor_format(p[i * len + 1]));
Packit Service e18529
		}
Packit Service e18529
	}
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.17 Physical Memory Array (Type 16)
Packit Service e18529
 */
Packit Service e18529
Packit Service e18529
static const char *dmi_memory_array_location(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.17.1 */
Packit Service e18529
	static const char *location[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"System Board Or Motherboard",
Packit Service e18529
		"ISA Add-on Card",
Packit Service e18529
		"EISA Add-on Card",
Packit Service e18529
		"PCI Add-on Card",
Packit Service e18529
		"MCA Add-on Card",
Packit Service e18529
		"PCMCIA Add-on Card",
Packit Service e18529
		"Proprietary Add-on Card",
Packit Service e18529
		"NuBus" /* 0x0A */
Packit Service e18529
	};
Packit Service e18529
	static const char *location_0xA0[] = {
Packit Service e18529
		"PC-98/C20 Add-on Card", /* 0xA0 */
Packit Service e18529
		"PC-98/C24 Add-on Card",
Packit Service e18529
		"PC-98/E Add-on Card",
Packit Service 0bfd26
		"PC-98/Local Bus Add-on Card",
Packit Service 0bfd26
		"CXL Flexbus 1.0" /* 0xA4 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x0A)
Packit Service e18529
		return location[code - 0x01];
Packit Service 0bfd26
	if (code >= 0xA0 && code <= 0xA4)
Packit Service e18529
		return location_0xA0[code - 0xA0];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_memory_array_use(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.17.2 */
Packit Service e18529
	static const char *use[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"System Memory",
Packit Service e18529
		"Video Memory",
Packit Service e18529
		"Flash Memory",
Packit Service e18529
		"Non-volatile RAM",
Packit Service e18529
		"Cache Memory" /* 0x07 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x07)
Packit Service e18529
		return use[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_memory_array_ec_type(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.17.3 */
Packit Service e18529
	static const char *type[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"None",
Packit Service e18529
		"Parity",
Packit Service e18529
		"Single-bit ECC",
Packit Service e18529
		"Multi-bit ECC",
Packit Service e18529
		"CRC" /* 0x07 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x07)
Packit Service e18529
		return type[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static void dmi_memory_array_error_handle(u16 code)
Packit Service e18529
{
Packit Service e18529
	if (code == 0xFFFE)
Packit Service 622062
		printf(" Not Provided");
Packit Service e18529
	else if (code == 0xFFFF)
Packit Service 622062
		printf(" No Error");
Packit Service e18529
	else
Packit Service 622062
		printf(" 0x%04X", code);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.18 Memory Device (Type 17)
Packit Service e18529
 */
Packit Service e18529
Packit Service 622062
static void dmi_memory_device_width(u16 code)
Packit Service e18529
{
Packit Service e18529
	/*
Packit Service e18529
	 * If no memory module is present, width may be 0
Packit Service e18529
	 */
Packit Service e18529
	if (code == 0xFFFF || code == 0)
Packit Service 622062
		printf(" Unknown");
Packit Service e18529
	else
Packit Service 622062
		printf(" %u bits", code);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static void dmi_memory_device_size(u16 code)
Packit Service e18529
{
Packit Service e18529
	if (code == 0)
Packit Service 622062
		printf(" No Module Installed");
Packit Service e18529
	else if (code == 0xFFFF)
Packit Service 622062
		printf(" Unknown");
Packit Service e18529
	else
Packit Service e18529
	{
Packit Service 75548d
		u64 s = { .l = code & 0x7FFF };
Packit Service 75548d
		if (!(code & 0x8000))
Packit Service 75548d
			s.l <<= 10;
Packit Service 75548d
		dmi_print_memory_size(s, 1);
Packit Service e18529
	}
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static void dmi_memory_device_extended_size(u32 code)
Packit Service e18529
{
Packit Service e18529
	code &= 0x7FFFFFFFUL;
Packit Service e18529
Packit Service e18529
	/*
Packit Service e18529
	 * Use the greatest unit for which the exact value can be displayed
Packit Service e18529
	 * as an integer without rounding
Packit Service e18529
	 */
Packit Service e18529
	if (code & 0x3FFUL)
Packit Service 622062
		printf(" %lu MB", (unsigned long)code);
Packit Service e18529
	else if (code & 0xFFC00UL)
Packit Service 622062
		printf(" %lu GB", (unsigned long)code >> 10);
Packit Service e18529
	else
Packit Service 622062
		printf(" %lu TB", (unsigned long)code >> 20);
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_memory_voltage_value(u16 code)
Packit Service e18529
{
Packit Service e18529
	if (code == 0)
Packit Service 622062
		printf(" Unknown");
Packit Service e18529
	else
Packit Service 622062
		printf(code % 100 ? " %g V" : " %.1f V", (float)code / 1000);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_memory_device_form_factor(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.18.1 */
Packit Service e18529
	static const char *form_factor[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"SIMM",
Packit Service e18529
		"SIP",
Packit Service e18529
		"Chip",
Packit Service e18529
		"DIP",
Packit Service e18529
		"ZIP",
Packit Service e18529
		"Proprietary Card",
Packit Service e18529
		"DIMM",
Packit Service e18529
		"TSOP",
Packit Service e18529
		"Row Of Chips",
Packit Service e18529
		"RIMM",
Packit Service e18529
		"SODIMM",
Packit Service e18529
		"SRIMM",
Packit Service 0bfd26
		"FB-DIMM",
Packit Service 0bfd26
		"Die" /* 0x10 */
Packit Service e18529
	};
Packit Service e18529
Packit Service 0bfd26
	if (code >= 0x01 && code <= 0x10)
Packit Service e18529
		return form_factor[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static void dmi_memory_device_set(u8 code)
Packit Service e18529
{
Packit Service e18529
	if (code == 0)
Packit Service 622062
		printf(" None");
Packit Service e18529
	else if (code == 0xFF)
Packit Service 622062
		printf(" Unknown");
Packit Service e18529
	else
Packit Service 622062
		printf(" %u", code);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_memory_device_type(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.18.2 */
Packit Service e18529
	static const char *type[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"DRAM",
Packit Service e18529
		"EDRAM",
Packit Service e18529
		"VRAM",
Packit Service e18529
		"SRAM",
Packit Service e18529
		"RAM",
Packit Service e18529
		"ROM",
Packit Service e18529
		"Flash",
Packit Service e18529
		"EEPROM",
Packit Service e18529
		"FEPROM",
Packit Service e18529
		"EPROM",
Packit Service e18529
		"CDRAM",
Packit Service e18529
		"3DRAM",
Packit Service e18529
		"SDRAM",
Packit Service e18529
		"SGRAM",
Packit Service e18529
		"RDRAM",
Packit Service e18529
		"DDR",
Packit Service e18529
		"DDR2",
Packit Service e18529
		"DDR2 FB-DIMM",
Packit Service e18529
		"Reserved",
Packit Service e18529
		"Reserved",
Packit Service e18529
		"Reserved",
Packit Service e18529
		"DDR3",
Packit Service e18529
		"FBD2",
Packit Service e18529
		"DDR4",
Packit Service e18529
		"LPDDR",
Packit Service e18529
		"LPDDR2",
Packit Service e18529
		"LPDDR3",
Packit Service 3e59fe
		"LPDDR4",
Packit Service 0bfd26
		"Logical non-volatile device",
Packit Service 0bfd26
		"HBM",
Packit Service 0bfd26
		"HBM2" /* 0x21 */
Packit Service e18529
	};
Packit Service e18529
Packit Service 0bfd26
	if (code >= 0x01 && code <= 0x21)
Packit Service e18529
		return type[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static void dmi_memory_device_type_detail(u16 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.18.3 */
Packit Service e18529
	static const char *detail[] = {
Packit Service e18529
		"Other", /* 1 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"Fast-paged",
Packit Service e18529
		"Static Column",
Packit Service e18529
		"Pseudo-static",
Packit Service e18529
		"RAMBus",
Packit Service e18529
		"Synchronous",
Packit Service e18529
		"CMOS",
Packit Service e18529
		"EDO",
Packit Service e18529
		"Window DRAM",
Packit Service e18529
		"Cache DRAM",
Packit Service e18529
		"Non-Volatile",
Packit Service e18529
		"Registered (Buffered)",
Packit Service e18529
		"Unbuffered (Unregistered)",
Packit Service e18529
		"LRDIMM"  /* 15 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if ((code & 0xFFFE) == 0)
Packit Service 622062
		printf(" None");
Packit Service e18529
	else
Packit Service e18529
	{
Packit Service 622062
		int i;
Packit Service e18529
Packit Service e18529
		for (i = 1; i <= 15; i++)
Packit Service e18529
			if (code & (1 << i))
Packit Service 622062
				printf(" %s", detail[i - 1]);
Packit Service e18529
	}
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_memory_device_speed(u16 code)
Packit Service e18529
{
Packit Service e18529
	if (code == 0)
Packit Service 622062
		printf(" Unknown");
Packit Service e18529
	else
Packit Service 622062
		printf(" %u MT/s", code);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static void dmi_memory_technology(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.18.6 */
Packit Service e18529
	static const char * const technology[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"DRAM",
Packit Service e18529
		"NVDIMM-N",
Packit Service e18529
		"NVDIMM-F",
Packit Service e18529
		"NVDIMM-P",
Packit Service 0bfd26
		"Intel Optane DC persistent memory" /* 0x07 */
Packit Service e18529
	};
Packit Service e18529
	if (code >= 0x01 && code <= 0x07)
Packit Service 622062
		printf(" %s", technology[code - 0x01]);
Packit Service e18529
	else
Packit Service 622062
		printf(" %s", out_of_spec);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static void dmi_memory_operating_mode_capability(u16 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.18.7 */
Packit Service e18529
	static const char * const mode[] = {
Packit Service e18529
		"Other", /* 1 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"Volatile memory",
Packit Service e18529
		"Byte-accessible persistent memory",
Packit Service e18529
		"Block-accessible persistent memory" /* 5 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if ((code & 0xFFFE) == 0)
Packit Service 622062
		printf(" None");
Packit Service e18529
	else {
Packit Service 622062
		int i;
Packit Service e18529
Packit Service e18529
		for (i = 1; i <= 5; i++)
Packit Service e18529
			if (code & (1 << i))
Packit Service 622062
				printf(" %s", mode[i - 1]);
Packit Service e18529
	}
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_memory_manufacturer_id(u16 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.18.8 */
Packit Service e18529
	/* 7.18.10 */
Packit Service e18529
	/* LSB is 7-bit Odd Parity number of continuation codes */
Packit Service e18529
	if (code == 0)
Packit Service 622062
		printf(" Unknown");
Packit Service e18529
	else
Packit Service 622062
		printf(" Bank %d, Hex 0x%02X", (code & 0x7F) + 1, code >> 8);
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_memory_product_id(u16 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.18.9 */
Packit Service e18529
	/* 7.18.11 */
Packit Service e18529
	if (code == 0)
Packit Service 622062
		printf(" Unknown");
Packit Service e18529
	else
Packit Service 622062
		printf(" 0x%04X", code);
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_memory_size(u64 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.18.12 */
Packit Service e18529
	/* 7.18.13 */
Packit Service e18529
	if (code.h == 0xFFFFFFFF && code.l == 0xFFFFFFFF)
Packit Service 622062
		printf(" Unknown");
Packit Service e18529
	else if (code.h == 0x0 && code.l == 0x0)
Packit Service 622062
		printf(" None");
Packit Service e18529
	else
Packit Service 622062
		dmi_print_memory_size(code, 0);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.19 32-bit Memory Error Information (Type 18)
Packit Service e18529
 */
Packit Service e18529
Packit Service e18529
static const char *dmi_memory_error_type(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.19.1 */
Packit Service e18529
	static const char *type[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"OK",
Packit Service e18529
		"Bad Read",
Packit Service e18529
		"Parity Error",
Packit Service e18529
		"Single-bit Error",
Packit Service e18529
		"Double-bit Error",
Packit Service e18529
		"Multi-bit Error",
Packit Service e18529
		"Nibble Error",
Packit Service e18529
		"Checksum Error",
Packit Service e18529
		"CRC Error",
Packit Service e18529
		"Corrected Single-bit Error",
Packit Service e18529
		"Corrected Error",
Packit Service e18529
		"Uncorrectable Error" /* 0x0E */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x0E)
Packit Service e18529
		return type[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_memory_error_granularity(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.19.2 */
Packit Service e18529
	static const char *granularity[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"Device Level",
Packit Service e18529
		"Memory Partition Level" /* 0x04 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x04)
Packit Service e18529
		return granularity[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_memory_error_operation(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.19.3 */
Packit Service e18529
	static const char *operation[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"Read",
Packit Service e18529
		"Write",
Packit Service e18529
		"Partial Write" /* 0x05 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x05)
Packit Service e18529
		return operation[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static void dmi_memory_error_syndrome(u32 code)
Packit Service e18529
{
Packit Service e18529
	if (code == 0x00000000)
Packit Service 622062
		printf(" Unknown");
Packit Service e18529
	else
Packit Service 622062
		printf(" 0x%08X", code);
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_32bit_memory_error_address(u32 code)
Packit Service e18529
{
Packit Service e18529
	if (code == 0x80000000)
Packit Service 622062
		printf(" Unknown");
Packit Service e18529
	else
Packit Service 622062
		printf(" 0x%08X", code);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.20 Memory Array Mapped Address (Type 19)
Packit Service e18529
 */
Packit Service e18529
Packit Service e18529
static void dmi_mapped_address_size(u32 code)
Packit Service e18529
{
Packit Service e18529
	if (code == 0)
Packit Service 622062
		printf(" Invalid");
Packit Service e18529
	else
Packit Service e18529
	{
Packit Service e18529
		u64 size;
Packit Service e18529
Packit Service e18529
		size.h = 0;
Packit Service e18529
		size.l = code;
Packit Service 622062
		dmi_print_memory_size(size, 1);
Packit Service e18529
	}
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static void dmi_mapped_address_extended_size(u64 start, u64 end)
Packit Service e18529
{
Packit Service e18529
	if (start.h == end.h && start.l == end.l)
Packit Service 622062
		printf(" Invalid");
Packit Service e18529
	else
Packit Service 622062
		dmi_print_memory_size(u64_range(start, end), 0);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.21 Memory Device Mapped Address (Type 20)
Packit Service e18529
 */
Packit Service e18529
Packit Service e18529
static void dmi_mapped_address_row_position(u8 code)
Packit Service e18529
{
Packit Service e18529
	if (code == 0)
Packit Service 622062
		printf(" %s", out_of_spec);
Packit Service e18529
	else if (code == 0xFF)
Packit Service 622062
		printf(" Unknown");
Packit Service e18529
	else
Packit Service 622062
		printf(" %u", code);
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_mapped_address_interleave_position(u8 code, const char *prefix)
Packit Service e18529
{
Packit Service e18529
	if (code != 0)
Packit Service e18529
	{
Packit Service 622062
		printf("%sInterleave Position:", prefix);
Packit Service e18529
		if (code == 0xFF)
Packit Service 622062
			printf(" Unknown");
Packit Service e18529
		else
Packit Service 622062
			printf(" %u", code);
Packit Service 622062
		printf("\n");
Packit Service e18529
	}
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_mapped_address_interleaved_data_depth(u8 code, const char *prefix)
Packit Service e18529
{
Packit Service e18529
	if (code != 0)
Packit Service e18529
	{
Packit Service 622062
		printf("%sInterleaved Data Depth:", prefix);
Packit Service e18529
		if (code == 0xFF)
Packit Service 622062
			printf(" Unknown");
Packit Service e18529
		else
Packit Service 622062
			printf(" %u", code);
Packit Service 622062
		printf("\n");
Packit Service e18529
	}
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.22 Built-in Pointing Device (Type 21)
Packit Service e18529
 */
Packit Service e18529
Packit Service e18529
static const char *dmi_pointing_device_type(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.22.1 */
Packit Service e18529
	static const char *type[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"Mouse",
Packit Service e18529
		"Track Ball",
Packit Service e18529
		"Track Point",
Packit Service e18529
		"Glide Point",
Packit Service e18529
		"Touch Pad",
Packit Service e18529
		"Touch Screen",
Packit Service e18529
		"Optical Sensor" /* 0x09 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x09)
Packit Service e18529
		return type[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_pointing_device_interface(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.22.2 */
Packit Service e18529
	static const char *interface[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"Serial",
Packit Service e18529
		"PS/2",
Packit Service e18529
		"Infrared",
Packit Service e18529
		"HIP-HIL",
Packit Service e18529
		"Bus Mouse",
Packit Service e18529
		"ADB (Apple Desktop Bus)" /* 0x08 */
Packit Service e18529
	};
Packit Service e18529
	static const char *interface_0xA0[] = {
Packit Service e18529
		"Bus Mouse DB-9", /* 0xA0 */
Packit Service e18529
		"Bus Mouse Micro DIN",
Packit Service e18529
		"USB" /* 0xA2 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x08)
Packit Service e18529
		return interface[code - 0x01];
Packit Service e18529
	if (code >= 0xA0 && code <= 0xA2)
Packit Service e18529
		return interface_0xA0[code - 0xA0];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.23 Portable Battery (Type 22)
Packit Service e18529
 */
Packit Service e18529
Packit Service e18529
static const char *dmi_battery_chemistry(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.23.1 */
Packit Service e18529
	static const char *chemistry[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"Lead Acid",
Packit Service e18529
		"Nickel Cadmium",
Packit Service e18529
		"Nickel Metal Hydride",
Packit Service e18529
		"Lithium Ion",
Packit Service e18529
		"Zinc Air",
Packit Service e18529
		"Lithium Polymer" /* 0x08 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x08)
Packit Service e18529
		return chemistry[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static void dmi_battery_capacity(u16 code, u8 multiplier)
Packit Service e18529
{
Packit Service e18529
	if (code == 0)
Packit Service 622062
		printf(" Unknown");
Packit Service e18529
	else
Packit Service 622062
		printf(" %u mWh", code * multiplier);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static void dmi_battery_voltage(u16 code)
Packit Service e18529
{
Packit Service e18529
	if (code == 0)
Packit Service 622062
		printf(" Unknown");
Packit Service e18529
	else
Packit Service 622062
		printf(" %u mV", code);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static void dmi_battery_maximum_error(u8 code)
Packit Service e18529
{
Packit Service e18529
	if (code == 0xFF)
Packit Service 622062
		printf(" Unknown");
Packit Service e18529
	else
Packit Service 622062
		printf(" %u%%", code);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.24 System Reset (Type 23)
Packit Service e18529
 */
Packit Service e18529
Packit Service e18529
/* code is assumed to be a 2-bit value */
Packit Service e18529
static const char *dmi_system_reset_boot_option(u8 code)
Packit Service e18529
{
Packit Service e18529
	static const char *option[] = {
Packit Service e18529
		out_of_spec, /* 0x0 */
Packit Service e18529
		"Operating System", /* 0x1 */
Packit Service e18529
		"System Utilities",
Packit Service e18529
		"Do Not Reboot" /* 0x3 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	return option[code];
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_system_reset_count(u16 code)
Packit Service e18529
{
Packit Service e18529
	if (code == 0xFFFF)
Packit Service 622062
		printf(" Unknown");
Packit Service e18529
	else
Packit Service 622062
		printf(" %u", code);
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_system_reset_timer(u16 code)
Packit Service e18529
{
Packit Service e18529
	if (code == 0xFFFF)
Packit Service 622062
		printf(" Unknown");
Packit Service e18529
	else
Packit Service 622062
		printf(" %u min", code);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.25 Hardware Security (Type 24)
Packit Service e18529
 */
Packit Service e18529
Packit Service e18529
static const char *dmi_hardware_security_status(u8 code)
Packit Service e18529
{
Packit Service e18529
	static const char *status[] = {
Packit Service e18529
		"Disabled", /* 0x00 */
Packit Service e18529
		"Enabled",
Packit Service e18529
		"Not Implemented",
Packit Service e18529
		"Unknown" /* 0x03 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	return status[code];
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.26 System Power Controls (Type 25)
Packit Service e18529
 */
Packit Service e18529
Packit Service e18529
static void dmi_power_controls_power_on(const u8 *p)
Packit Service e18529
{
Packit Service e18529
	/* 7.26.1 */
Packit Service e18529
	if (dmi_bcd_range(p[0], 0x01, 0x12))
Packit Service 622062
		printf(" %02X", p[0]);
Packit Service e18529
	else
Packit Service 622062
		printf(" *");
Packit Service e18529
	if (dmi_bcd_range(p[1], 0x01, 0x31))
Packit Service 622062
		printf("-%02X", p[1]);
Packit Service e18529
	else
Packit Service 622062
		printf("-*");
Packit Service e18529
	if (dmi_bcd_range(p[2], 0x00, 0x23))
Packit Service 622062
		printf(" %02X", p[2]);
Packit Service e18529
	else
Packit Service 622062
		printf(" *");
Packit Service e18529
	if (dmi_bcd_range(p[3], 0x00, 0x59))
Packit Service 622062
		printf(":%02X", p[3]);
Packit Service e18529
	else
Packit Service 622062
		printf(":*");
Packit Service e18529
	if (dmi_bcd_range(p[4], 0x00, 0x59))
Packit Service 622062
		printf(":%02X", p[4]);
Packit Service e18529
	else
Packit Service 622062
		printf(":*");
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.27 Voltage Probe (Type 26)
Packit Service e18529
 */
Packit Service e18529
Packit Service e18529
static const char *dmi_voltage_probe_location(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.27.1 */
Packit Service e18529
	static const char *location[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"Processor",
Packit Service e18529
		"Disk",
Packit Service e18529
		"Peripheral Bay",
Packit Service e18529
		"System Management Module",
Packit Service e18529
		"Motherboard",
Packit Service e18529
		"Memory Module",
Packit Service e18529
		"Processor Module",
Packit Service e18529
		"Power Unit",
Packit Service e18529
		"Add-in Card" /* 0x0B */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x0B)
Packit Service e18529
		return location[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_probe_status(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.27.1 */
Packit Service e18529
	static const char *status[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"OK",
Packit Service e18529
		"Non-critical",
Packit Service e18529
		"Critical",
Packit Service e18529
		"Non-recoverable" /* 0x06 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x06)
Packit Service e18529
		return status[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_voltage_probe_value(u16 code)
Packit Service e18529
{
Packit Service e18529
	if (code == 0x8000)
Packit Service 622062
		printf(" Unknown");
Packit Service e18529
	else
Packit Service 622062
		printf(" %.3f V", (float)(i16)code / 1000);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static void dmi_voltage_probe_resolution(u16 code)
Packit Service e18529
{
Packit Service e18529
	if (code == 0x8000)
Packit Service 622062
		printf(" Unknown");
Packit Service e18529
	else
Packit Service 622062
		printf(" %.1f mV", (float)code / 10);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static void dmi_probe_accuracy(u16 code)
Packit Service e18529
{
Packit Service e18529
	if (code == 0x8000)
Packit Service 622062
		printf(" Unknown");
Packit Service e18529
	else
Packit Service 622062
		printf(" %.2f%%", (float)code / 100);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.28 Cooling Device (Type 27)
Packit Service e18529
 */
Packit Service e18529
Packit Service e18529
static const char *dmi_cooling_device_type(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.28.1 */
Packit Service e18529
	static const char *type[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"Fan",
Packit Service e18529
		"Centrifugal Blower",
Packit Service e18529
		"Chip Fan",
Packit Service e18529
		"Cabinet Fan",
Packit Service e18529
		"Power Supply Fan",
Packit Service e18529
		"Heat Pipe",
Packit Service e18529
		"Integrated Refrigeration" /* 0x09 */
Packit Service e18529
	};
Packit Service e18529
	static const char *type_0x10[] = {
Packit Service e18529
		"Active Cooling", /* 0x10 */
Packit Service e18529
		"Passive Cooling" /* 0x11 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x09)
Packit Service e18529
		return type[code - 0x01];
Packit Service e18529
	if (code >= 0x10 && code <= 0x11)
Packit Service e18529
		return type_0x10[code - 0x10];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static void dmi_cooling_device_speed(u16 code)
Packit Service e18529
{
Packit Service e18529
	if (code == 0x8000)
Packit Service 622062
		printf(" Unknown Or Non-rotating");
Packit Service e18529
	else
Packit Service 622062
		printf(" %u rpm", code);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.29 Temperature Probe (Type 28)
Packit Service e18529
 */
Packit Service e18529
Packit Service e18529
static const char *dmi_temperature_probe_location(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.29.1 */
Packit Service e18529
	static const char *location[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"Processor",
Packit Service e18529
		"Disk",
Packit Service e18529
		"Peripheral Bay",
Packit Service e18529
		"System Management Module",
Packit Service e18529
		"Motherboard",
Packit Service e18529
		"Memory Module",
Packit Service e18529
		"Processor Module",
Packit Service e18529
		"Power Unit",
Packit Service e18529
		"Add-in Card",
Packit Service e18529
		"Front Panel Board",
Packit Service e18529
		"Back Panel Board",
Packit Service e18529
		"Power System Board",
Packit Service e18529
		"Drive Back Plane" /* 0x0F */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x0F)
Packit Service e18529
		return location[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_temperature_probe_value(u16 code)
Packit Service e18529
{
Packit Service e18529
	if (code == 0x8000)
Packit Service 622062
		printf(" Unknown");
Packit Service e18529
	else
Packit Service 622062
		printf(" %.1f deg C", (float)(i16)code / 10);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static void dmi_temperature_probe_resolution(u16 code)
Packit Service e18529
{
Packit Service e18529
	if (code == 0x8000)
Packit Service 622062
		printf(" Unknown");
Packit Service e18529
	else
Packit Service 622062
		printf(" %.3f deg C", (float)code / 1000);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.30 Electrical Current Probe (Type 29)
Packit Service e18529
 */
Packit Service e18529
Packit Service 622062
static void dmi_current_probe_value(u16 code)
Packit Service e18529
{
Packit Service e18529
	if (code == 0x8000)
Packit Service 622062
		printf(" Unknown");
Packit Service e18529
	else
Packit Service 622062
		printf(" %.3f A", (float)(i16)code / 1000);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static void dmi_current_probe_resolution(u16 code)
Packit Service e18529
{
Packit Service e18529
	if (code == 0x8000)
Packit Service 622062
		printf(" Unknown");
Packit Service e18529
	else
Packit Service 622062
		printf(" %.1f mA", (float)code / 10);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.33 System Boot Information (Type 32)
Packit Service e18529
 */
Packit Service e18529
Packit Service e18529
static const char *dmi_system_boot_status(u8 code)
Packit Service e18529
{
Packit Service e18529
	static const char *status[] = {
Packit Service e18529
		"No errors detected", /* 0 */
Packit Service e18529
		"No bootable media",
Packit Service e18529
		"Operating system failed to load",
Packit Service e18529
		"Firmware-detected hardware failure",
Packit Service e18529
		"Operating system-detected hardware failure",
Packit Service e18529
		"User-requested boot",
Packit Service e18529
		"System security violation",
Packit Service e18529
		"Previously-requested image",
Packit Service e18529
		"System watchdog timer expired" /* 8 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code <= 8)
Packit Service e18529
		return status[code];
Packit Service e18529
	if (code >= 128 && code <= 191)
Packit Service e18529
		return "OEM-specific";
Packit Service e18529
	if (code >= 192)
Packit Service e18529
		return "Product-specific";
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.34 64-bit Memory Error Information (Type 33)
Packit Service e18529
 */
Packit Service e18529
Packit Service 622062
static void dmi_64bit_memory_error_address(u64 code)
Packit Service e18529
{
Packit Service e18529
	if (code.h == 0x80000000 && code.l == 0x00000000)
Packit Service 622062
		printf(" Unknown");
Packit Service e18529
	else
Packit Service 622062
		printf(" 0x%08X%08X", code.h, code.l);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.35 Management Device (Type 34)
Packit Service e18529
 */
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * Several boards have a bug where some type 34 structures have their
Packit Service e18529
 * length incorrectly set to 0x10 instead of 0x0B. This causes the
Packit Service e18529
 * first 5 characters of the device name to be trimmed. It's easy to
Packit Service e18529
 * check and fix, so do it, but warn.
Packit Service e18529
 */
Packit Service e18529
static void dmi_fixup_type_34(struct dmi_header *h, int display)
Packit Service e18529
{
Packit Service e18529
	u8 *p = h->data;
Packit Service e18529
Packit Service 622062
 	/* Make sure the hidden data is ASCII only */
Packit Service e18529
	if (h->length == 0x10
Packit Service e18529
	 && is_printable(p + 0x0B, 0x10 - 0x0B))
Packit Service e18529
	{
Packit Service e18529
		if (!(opt.flags & FLAG_QUIET) && display)
Packit Service e18529
			fprintf(stderr,
Packit Service e18529
				"Invalid entry length (%u). Fixed up to %u.\n",
Packit Service e18529
				0x10, 0x0B);
Packit Service e18529
		h->length = 0x0B;
Packit Service e18529
	}
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_management_device_type(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.35.1 */
Packit Service e18529
	static const char *type[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"LM75",
Packit Service e18529
		"LM78",
Packit Service e18529
		"LM79",
Packit Service e18529
		"LM80",
Packit Service e18529
		"LM81",
Packit Service e18529
		"ADM9240",
Packit Service e18529
		"DS1780",
Packit Service e18529
		"MAX1617",
Packit Service e18529
		"GL518SM",
Packit Service e18529
		"W83781D",
Packit Service e18529
		"HT82H791" /* 0x0D */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x0D)
Packit Service e18529
		return type[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_management_device_address_type(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.35.2 */
Packit Service e18529
	static const char *type[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"I/O Port",
Packit Service e18529
		"Memory",
Packit Service e18529
		"SMBus" /* 0x05 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x05)
Packit Service e18529
		return type[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.38 Memory Channel (Type 37)
Packit Service e18529
 */
Packit Service e18529
Packit Service e18529
static const char *dmi_memory_channel_type(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.38.1 */
Packit Service e18529
	static const char *type[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"RamBus",
Packit Service e18529
		"SyncLink" /* 0x04 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x04)
Packit Service e18529
		return type[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_memory_channel_devices(u8 count, const u8 *p, const char *prefix)
Packit Service e18529
{
Packit Service e18529
	int i;
Packit Service e18529
Packit Service e18529
	for (i = 1; i <= count; i++)
Packit Service e18529
	{
Packit Service 622062
		printf("%sDevice %u Load: %u\n",
Packit Service 622062
			prefix, i, p[3 * i]);
Packit Service e18529
		if (!(opt.flags & FLAG_QUIET))
Packit Service 622062
			printf("%sDevice %u Handle: 0x%04X\n",
Packit Service 622062
				prefix, i, WORD(p + 3 * i + 1));
Packit Service e18529
	}
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.39 IPMI Device Information (Type 38)
Packit Service e18529
 */
Packit Service e18529
Packit Service e18529
static const char *dmi_ipmi_interface_type(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.39.1 and IPMI 2.0, appendix C1, table C1-2 */
Packit Service e18529
	static const char *type[] = {
Packit Service e18529
		"Unknown", /* 0x00 */
Packit Service e18529
		"KCS (Keyboard Control Style)",
Packit Service e18529
		"SMIC (Server Management Interface Chip)",
Packit Service e18529
		"BT (Block Transfer)",
Packit Service e18529
		"SSIF (SMBus System Interface)" /* 0x04 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code <= 0x04)
Packit Service e18529
		return type[code];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static void dmi_ipmi_base_address(u8 type, const u8 *p, u8 lsb)
Packit Service e18529
{
Packit Service e18529
	if (type == 0x04) /* SSIF */
Packit Service e18529
	{
Packit Service 622062
		printf("0x%02X (SMBus)", (*p) >> 1);
Packit Service e18529
	}
Packit Service e18529
	else
Packit Service e18529
	{
Packit Service e18529
		u64 address = QWORD(p);
Packit Service 622062
		printf("0x%08X%08X (%s)", address.h, (address.l & ~1) | lsb,
Packit Service e18529
			address.l & 1 ? "I/O" : "Memory-mapped");
Packit Service e18529
	}
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/* code is assumed to be a 2-bit value */
Packit Service e18529
static const char *dmi_ipmi_register_spacing(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* IPMI 2.0, appendix C1, table C1-1 */
Packit Service e18529
	static const char *spacing[] = {
Packit Service e18529
		"Successive Byte Boundaries", /* 0x00 */
Packit Service e18529
		"32-bit Boundaries",
Packit Service e18529
		"16-byte Boundaries", /* 0x02 */
Packit Service e18529
		out_of_spec /* 0x03 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	return spacing[code];
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.40 System Power Supply (Type 39)
Packit Service e18529
 */
Packit Service e18529
Packit Service e18529
static void dmi_power_supply_power(u16 code)
Packit Service e18529
{
Packit Service e18529
	if (code == 0x8000)
Packit Service 622062
		printf(" Unknown");
Packit Service e18529
	else
Packit Service 622062
		printf(" %u W", (unsigned int)code);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_power_supply_type(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.40.1 */
Packit Service e18529
	static const char *type[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"Linear",
Packit Service e18529
		"Switching",
Packit Service e18529
		"Battery",
Packit Service e18529
		"UPS",
Packit Service e18529
		"Converter",
Packit Service e18529
		"Regulator" /* 0x08 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x08)
Packit Service e18529
		return type[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_power_supply_status(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.40.1 */
Packit Service e18529
	static const char *status[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"OK",
Packit Service e18529
		"Non-critical",
Packit Service e18529
		"Critical" /* 0x05 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x05)
Packit Service e18529
		return status[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static const char *dmi_power_supply_range_switching(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* 7.40.1 */
Packit Service e18529
	static const char *switching[] = {
Packit Service e18529
		"Other", /* 0x01 */
Packit Service e18529
		"Unknown",
Packit Service e18529
		"Manual",
Packit Service e18529
		"Auto-switch",
Packit Service e18529
		"Wide Range",
Packit Service e18529
		"N/A" /* 0x06 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x01 && code <= 0x06)
Packit Service e18529
		return switching[code - 0x01];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.41 Additional Information (Type 40)
Packit Service e18529
 *
Packit Service e18529
 * Proper support of this entry type would require redesigning a large part of
Packit Service e18529
 * the code, so I am waiting to see actual implementations of it to decide
Packit Service e18529
 * whether it's worth the effort.
Packit Service e18529
 */
Packit Service e18529
Packit Service 622062
static void dmi_additional_info(const struct dmi_header *h, const char *prefix)
Packit Service e18529
{
Packit Service e18529
	u8 *p = h->data + 4;
Packit Service e18529
	u8 count = *p++;
Packit Service e18529
	u8 length;
Packit Service e18529
	int i, offset = 5;
Packit Service e18529
Packit Service e18529
	for (i = 0; i < count; i++)
Packit Service e18529
	{
Packit Service 622062
		printf("%sAdditional Information %d\n", prefix, i + 1);
Packit Service e18529
Packit Service e18529
		/* Check for short entries */
Packit Service e18529
		if (h->length < offset + 1) break;
Packit Service e18529
		length = p[0x00];
Packit Service e18529
		if (length < 0x05 || h->length < offset + length) break;
Packit Service e18529
Packit Service 622062
		printf("%s\tReferenced Handle: 0x%04x\n",
Packit Service 622062
			prefix, WORD(p + 0x01));
Packit Service 622062
		printf("%s\tReferenced Offset: 0x%02x\n",
Packit Service 622062
			prefix, p[0x03]);
Packit Service 622062
		printf("%s\tString: %s\n",
Packit Service 622062
			prefix, dmi_string(h, p[0x04]));
Packit Service e18529
Packit Service 622062
		printf("%s\tValue: ", prefix);
Packit Service e18529
		switch (length - 0x05)
Packit Service e18529
		{
Packit Service e18529
			case 1:
Packit Service 622062
				printf("0x%02x", p[0x05]);
Packit Service e18529
				break;
Packit Service e18529
			case 2:
Packit Service 622062
				printf("0x%04x", WORD(p + 0x05));
Packit Service e18529
				break;
Packit Service e18529
			case 4:
Packit Service 622062
				printf("0x%08x", DWORD(p + 0x05));
Packit Service e18529
				break;
Packit Service e18529
			default:
Packit Service 622062
				printf("Unexpected size");
Packit Service e18529
				break;
Packit Service e18529
		}
Packit Service 622062
		printf("\n");
Packit Service e18529
Packit Service e18529
		p += length;
Packit Service e18529
		offset += length;
Packit Service e18529
	}
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.43 Management Controller Host Interface (Type 42)
Packit Service e18529
 */
Packit Service e18529
Packit Service e18529
static const char *dmi_management_controller_host_type(u8 code)
Packit Service e18529
{
Packit Service e18529
	/* DMTF DSP0239 (MCTP) version 1.1.0 */
Packit Service e18529
	static const char *type[] = {
Packit Service e18529
		"KCS: Keyboard Controller Style", /* 0x02 */
Packit Service e18529
		"8250 UART Register Compatible",
Packit Service e18529
		"16450 UART Register Compatible",
Packit Service e18529
		"16550/16550A UART Register Compatible",
Packit Service e18529
		"16650/16650A UART Register Compatible",
Packit Service e18529
		"16750/16750A UART Register Compatible",
Packit Service e18529
		"16850/16850A UART Register Compatible" /* 0x08 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (code >= 0x02 && code <= 0x08)
Packit Service e18529
		return type[code - 0x02];
Packit Service e18529
	if (code <= 0x3F)
Packit Service e18529
		return "MCTP";
Packit Service e18529
	if (code == 0x40)
Packit Service e18529
		return "Network";
Packit Service e18529
	if (code == 0xF0)
Packit Service e18529
		return "OEM";
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.43.2: Protocol Record Types
Packit Service e18529
 */
Packit Service e18529
static const char *dmi_protocol_record_type(u8 type)
Packit Service e18529
{
Packit Service e18529
	const char *protocol[] = {
Packit Service e18529
		"Reserved",		/* 0x0 */
Packit Service e18529
		"Reserved",
Packit Service e18529
		"IPMI",
Packit Service e18529
		"MCTP",
Packit Service 622062
		"Redfish over IP", 	/* 0x4 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (type <= 0x4)
Packit Service e18529
		return protocol[type];
Packit Service e18529
	if (type == 0xF0)
Packit Service e18529
		return "OEM";
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * DSP0270: 8.6: Protocol IP Assignment types
Packit Service e18529
 */
Packit Service e18529
static const char *dmi_protocol_assignment_type(u8 type)
Packit Service e18529
{
Packit Service e18529
	const char *assignment[] = {
Packit Service e18529
		"Unknown",		/* 0x0 */
Packit Service e18529
		"Static",
Packit Service e18529
		"DHCP",
Packit Service e18529
		"AutoConf",
Packit Service e18529
		"Host Selected",	/* 0x4 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (type <= 0x4)
Packit Service e18529
		return assignment[type];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * DSP0270: 8.6: Protocol IP Address type
Packit Service e18529
 */
Packit Service e18529
static const char *dmi_address_type(u8 type)
Packit Service e18529
{
Packit Service e18529
	const char *addressformat[] = {
Packit Service e18529
		"Unknown",	/* 0x0 */
Packit Service e18529
		"IPv4",
Packit Service e18529
		"IPv6",		/* 0x2 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (type <= 0x2)
Packit Service e18529
		return addressformat[type];
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 *  DSP0270: 8.6 Protocol Address decode
Packit Service e18529
 */
Packit Service e18529
static const char *dmi_address_decode(u8 *data, char *storage, u8 addrtype)
Packit Service e18529
{
Packit Service e18529
	if (addrtype == 0x1) /* IPv4 */
Packit Service e18529
		return inet_ntop(AF_INET, data, storage, 64);
Packit Service e18529
	if (addrtype == 0x2) /* IPv6 */
Packit Service e18529
		return inet_ntop(AF_INET6, data, storage, 64);
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * DSP0270: 8.5: Parse the protocol record format
Packit Service e18529
 */
Packit Service 622062
static void dmi_parse_protocol_record(const char *prefix, u8 *rec)
Packit Service e18529
{
Packit Service e18529
	u8 rid;
Packit Service e18529
	u8 rlen;
Packit Service e18529
	u8 *rdata;
Packit Service e18529
	char buf[64];
Packit Service e18529
	u8 assign_val;
Packit Service e18529
	u8 addrtype;
Packit Service e18529
	u8 hlen;
Packit Service e18529
	const char *addrstr;
Packit Service e18529
	const char *hname;
Packit Service e18529
Packit Service e18529
	/* DSP0270: 8.5: Protocol Identifier */
Packit Service e18529
	rid = rec[0x0];
Packit Service e18529
	/* DSP0270: 8.5: Protocol Record Length */
Packit Service e18529
	rlen = rec[0x1];
Packit Service e18529
	/* DSP0270: 8.5: Protocol Record Data */
Packit Service e18529
	rdata = &rec[0x2];
Packit Service e18529
Packit Service 622062
	printf("%s\tProtocol ID: %02x (%s)\n", prefix, rid,
Packit Service e18529
		dmi_protocol_record_type(rid));
Packit Service e18529
Packit Service e18529
	/*
Packit Service e18529
	 * Don't decode anything other than Redfish for now
Packit Service e18529
	 * Note 0x4 is Redfish over IP in 7.43.2
Packit Service e18529
	 * and DSP0270: 8.5
Packit Service e18529
	 */
Packit Service e18529
	if (rid != 0x4)
Packit Service e18529
		return;
Packit Service e18529
Packit Service e18529
	/*
Packit Service e18529
	 * Ensure that the protocol record is of sufficient length
Packit Service e18529
	 * For RedFish that means rlen must be at least 91 bytes
Packit Service e18529
	 * other protcols will need different length checks
Packit Service e18529
	 */
Packit Service e18529
	if (rlen < 91)
Packit Service e18529
		return;
Packit Service e18529
Packit Service e18529
	/*
Packit Service e18529
	 * DSP0270: 8.6: Redfish Over IP Service UUID
Packit Service e18529
	 * Note: ver is hardcoded to 0x311 here just for
Packit Service e18529
	 * convenience.  It could get passed from the SMBIOS
Packit Service e18529
	 * header, but that's a lot of passing of pointers just
Packit Service e18529
	 * to get that info, and the only thing it is used for is
Packit Service e18529
	 * to determine the endianess of the field.  Since we only
Packit Service e18529
	 * do this parsing on versions of SMBIOS after 3.1.1, and the
Packit Service e18529
	 * endianess of the field is always little after version 2.6.0
Packit Service e18529
	 * we can just pick a sufficiently recent version here.
Packit Service e18529
	 */
Packit Service 622062
	printf("%s\t\tService UUID: ", prefix);
Packit Service 622062
	dmi_system_uuid(&rdata[0], 0x311);
Packit Service 622062
	printf("\n");
Packit Service e18529
Packit Service e18529
	/*
Packit Service e18529
	 * DSP0270: 8.6: Redfish Over IP Host IP Assignment Type
Packit Service e18529
	 * Note, using decimal indicies here, as the DSP0270
Packit Service e18529
	 * uses decimal, so as to make it more comparable
Packit Service e18529
	 */
Packit Service e18529
	assign_val = rdata[16];
Packit Service 622062
	printf("%s\t\tHost IP Assignment Type: %s\n", prefix,
Packit Service e18529
		dmi_protocol_assignment_type(assign_val));
Packit Service e18529
Packit Service 622062
	 /* DSP0270: 8.6: Redfish Over IP Host Address format */
Packit Service e18529
	addrtype = rdata[17];
Packit Service e18529
	addrstr = dmi_address_type(addrtype);
Packit Service 622062
	printf("%s\t\tHost IP Address Format: %s\n", prefix,
Packit Service e18529
		addrstr);
Packit Service e18529
Packit Service e18529
	/* DSP0270: 8.6 IP Assignment types */
Packit Service e18529
	/* We only use the Host IP Address and Mask if the assignment type is static */
Packit Service e18529
	if (assign_val == 0x1 || assign_val == 0x3)
Packit Service e18529
	{
Packit Service e18529
		/* DSP0270: 8.6: the Host IPv[4|6] Address */
Packit Service 622062
		printf("%s\t\t%s Address: %s\n", prefix, addrstr,
Packit Service e18529
			dmi_address_decode(&rdata[18], buf, addrtype));
Packit Service e18529
Packit Service e18529
		/* DSP0270: 8.6: Prints the Host IPv[4|6] Mask */
Packit Service 622062
		printf("%s\t\t%s Mask: %s\n", prefix, addrstr,
Packit Service e18529
			dmi_address_decode(&rdata[34], buf, addrtype));
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	/* DSP0270: 8.6: Get the Redfish Service IP Discovery Type */
Packit Service e18529
	assign_val = rdata[50];
Packit Service e18529
	/* Redfish Service IP Discovery type mirrors Host IP Assignment type */
Packit Service 622062
	printf("%s\t\tRedfish Service IP Discovery Type: %s\n", prefix,
Packit Service e18529
		dmi_protocol_assignment_type(assign_val));
Packit Service e18529
Packit Service e18529
	/* DSP0270: 8.6: Get the Redfish Service IP Address Format */
Packit Service e18529
	addrtype = rdata[51];
Packit Service e18529
	addrstr = dmi_address_type(addrtype);
Packit Service 622062
	printf("%s\t\tRedfish Service IP Address Format: %s\n", prefix,
Packit Service e18529
		addrstr);
Packit Service e18529
Packit Service e18529
	if (assign_val == 0x1 || assign_val == 0x3)
Packit Service e18529
	{
Packit Service e18529
		u16 port;
Packit Service e18529
		u32 vlan;
Packit Service e18529
Packit Service e18529
		/* DSP0270: 8.6: Prints the Redfish IPv[4|6] Service Address */
Packit Service 622062
		printf("%s\t\t%s Redfish Service Address: %s\n", prefix,
Packit Service 622062
			addrstr, dmi_address_decode(&rdata[52], buf,
Packit Service e18529
			addrtype));
Packit Service e18529
Packit Service e18529
		/* DSP0270: 8.6: Prints the Redfish IPv[4|6] Service Mask */
Packit Service 622062
		printf("%s\t\t%s Redfish Service Mask: %s\n", prefix,
Packit Service 622062
			addrstr, dmi_address_decode(&rdata[68], buf,
Packit Service e18529
			addrtype));
Packit Service e18529
Packit Service e18529
		/* DSP0270: 8.6: Redfish vlan and port info */
Packit Service e18529
		port = WORD(&rdata[84]);
Packit Service e18529
		vlan = DWORD(&rdata[86]);
Packit Service 622062
		printf("%s\t\tRedfish Service Port: %hu\n", prefix, port);
Packit Service 622062
		printf("%s\t\tRedfish Service Vlan: %u\n", prefix, vlan);
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	/* DSP0270: 8.6: Redfish host length and name */
Packit Service e18529
	hlen = rdata[90];
Packit Service e18529
Packit Service e18529
	/*
Packit Service e18529
	 * DSP0270: 8.6: The length of the host string + 91 (the minimum
Packit Service e18529
	 * size of a protocol record) cannot exceed the record length
Packit Service e18529
	 * (rec[0x1])
Packit Service e18529
	 */
Packit Service e18529
	hname = (const char *)&rdata[91];
Packit Service e18529
	if (hlen + 91 > rlen)
Packit Service e18529
	{
Packit Service e18529
		hname = out_of_spec;
Packit Service e18529
		hlen = strlen(out_of_spec);
Packit Service e18529
	}
Packit Service 6f2637
	printf("%s\t\tRedfish Service Hostname: %.*s\n", prefix, hlen, hname);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * DSP0270: 8.3: Device type ennumeration
Packit Service e18529
 */
Packit Service e18529
static const char *dmi_parse_device_type(u8 type)
Packit Service e18529
{
Packit Service e18529
	const char *devname[] = {
Packit Service e18529
		"USB",		/* 0x2 */
Packit Service e18529
		"PCI/PCIe",	/* 0x3 */
Packit Service e18529
	};
Packit Service e18529
Packit Service e18529
	if (type >= 0x2 && type <= 0x3)
Packit Service e18529
		return devname[type - 0x2];
Packit Service e18529
	if (type >= 0x80)
Packit Service e18529
		return "OEM";
Packit Service e18529
	return out_of_spec;
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_parse_controller_structure(const struct dmi_header *h,
Packit Service 622062
					   const char *prefix)
Packit Service e18529
{
Packit Service e18529
	int i;
Packit Service e18529
	u8 *data = h->data;
Packit Service e18529
	/* Host interface type */
Packit Service e18529
	u8 type;
Packit Service e18529
	/* Host Interface specific data length */
Packit Service e18529
	u8 len;
Packit Service e18529
	u8 count;
Packit Service e18529
	u32 total_read;
Packit Service e18529
Packit Service e18529
	/*
Packit Service e18529
	 * Minimum length of this struct is 0xB bytes
Packit Service e18529
	 */
Packit Service e18529
	if (h->length < 0xB)
Packit Service e18529
		return;
Packit Service e18529
Packit Service e18529
	/*
Packit Service e18529
	 * Also need to ensure that the interface specific data length
Packit Service e18529
	 * plus the size of the structure to that point don't exceed
Packit Service e18529
	 * the defined length of the structure, or we will overrun its
Packit Service e18529
	 * bounds
Packit Service e18529
	 */
Packit Service e18529
	len = data[0x5];
Packit Service e18529
	total_read = len + 0x6;
Packit Service e18529
Packit Service e18529
	if (total_read > h->length)
Packit Service e18529
		return;
Packit Service e18529
Packit Service e18529
	type = data[0x4];
Packit Service 622062
	printf("%sHost Interface Type: %s\n", prefix,
Packit Service e18529
		dmi_management_controller_host_type(type));
Packit Service e18529
Packit Service e18529
	/*
Packit Service e18529
	 * The following decodes are code for Network interface host types only
Packit Service e18529
	 * As defined in DSP0270
Packit Service e18529
	 */
Packit Service e18529
	if (type != 0x40)
Packit Service e18529
		return;
Packit Service e18529
Packit Service e18529
	if (len != 0)
Packit Service e18529
	{
Packit Service e18529
		/* DSP0270: 8.3 Table 2: Device Type */
Packit Service e18529
		type = data[0x6];
Packit Service e18529
Packit Service 622062
		printf("%sDevice Type: %s\n", prefix,
Packit Service e18529
			dmi_parse_device_type(type));
Packit Service e18529
		if (type == 0x2 && len >= 5)
Packit Service e18529
		{
Packit Service e18529
			/* USB Device Type - need at least 6 bytes */
Packit Service e18529
			u8 *usbdata = &data[0x7];
Packit Service e18529
			/* USB Device Descriptor: idVendor */
Packit Service 622062
			printf("%s\tidVendor: 0x%04x\n", prefix,
Packit Service e18529
				WORD(&usbdata[0x0]));
Packit Service e18529
			/* USB Device Descriptor: idProduct */
Packit Service 622062
			printf("%s\tidProduct: 0x%04x\n", prefix,
Packit Service e18529
				WORD(&usbdata[0x2]));
Packit Service e18529
			/*
Packit Service e18529
			 * USB Serial number is here, but its useless, don't
Packit Service e18529
			 * bother decoding it
Packit Service e18529
			 */
Packit Service e18529
		}
Packit Service e18529
		else if (type == 0x3 && len >= 9)
Packit Service e18529
		{
Packit Service e18529
			/* PCI Device Type - Need at least 8 bytes */
Packit Service e18529
			u8 *pcidata = &data[0x7];
Packit Service e18529
			/* PCI Device Descriptor: VendorID */
Packit Service 622062
			printf("%s\tVendorID: 0x%04x\n", prefix,
Packit Service e18529
				WORD(&pcidata[0x0]));
Packit Service e18529
			/* PCI Device Descriptor: DeviceID */
Packit Service 622062
			printf("%s\tDeviceID: 0x%04x\n", prefix,
Packit Service e18529
				WORD(&pcidata[0x2]));
Packit Service e18529
			/* PCI Device Descriptor: PCI SubvendorID */
Packit Service 622062
			printf("%s\tSubVendorID: 0x%04x\n", prefix,
Packit Service e18529
				WORD(&pcidata[0x4]));
Packit Service e18529
			/* PCI Device Descriptor: PCI SubdeviceID */
Packit Service 622062
			printf("%s\tSubDeviceID: 0x%04x\n", prefix,
Packit Service e18529
				WORD(&pcidata[0x6]));
Packit Service e18529
		}
Packit Service e18529
		else if (type == 0x4 && len >= 5)
Packit Service e18529
		{
Packit Service e18529
			/* OEM Device Type - Need at least 4 bytes */
Packit Service e18529
			u8 *oemdata = &data[0x7];
Packit Service e18529
			/* OEM Device Descriptor: IANA */
Packit Service 622062
			printf("%s\tVendor ID: 0x%02x:0x%02x:0x%02x:0x%02x\n",
Packit Service 622062
				prefix, oemdata[0x0], oemdata[0x1],
Packit Service e18529
				oemdata[0x2], oemdata[0x3]);
Packit Service e18529
		}
Packit Service e18529
		/* Don't mess with unknown types for now */
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	/*
Packit Service e18529
	 * DSP0270: 8.2 and 8.5: Protocol record count and protocol records
Packit Service e18529
	 * Move to the Protocol Count.
Packit Service e18529
	 */
Packit Service e18529
	data = &data[total_read];
Packit Service e18529
Packit Service e18529
	/*
Packit Service e18529
	 * We've validated up to 0x6 + len bytes, but we need to validate
Packit Service e18529
	 * the next byte below, the count value.
Packit Service e18529
	 */
Packit Service e18529
	total_read++;
Packit Service e18529
	if (total_read > h->length)
Packit Service e18529
	{
Packit Service 622062
		printf("%s\tWARN: Total read length %d exceeds total structure length %d\n",
Packit Service 622062
			prefix, total_read, h->length);
Packit Service e18529
		return;
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	/* Get the protocol records count */
Packit Service e18529
	count = data[0x0];
Packit Service e18529
	if (count)
Packit Service e18529
	{
Packit Service e18529
		u8 *rec = &data[0x1];
Packit Service e18529
		for (i = 0; i < count; i++)
Packit Service e18529
		{
Packit Service e18529
			/*
Packit Service e18529
			 * Need to ensure that this record doesn't overrun
Packit Service e18529
			 * the total length of the type 42 struct.  Note the +2
Packit Service e18529
			 * is added for the two leading bytes of a protocol
Packit Service e18529
			 * record representing the type and length bytes.
Packit Service e18529
			 */
Packit Service e18529
			total_read += rec[1] + 2;
Packit Service e18529
			if (total_read > h->length)
Packit Service e18529
			{
Packit Service 622062
				printf("%s\tWARN: Total read length %d exceeds total structure length %d\n",
Packit Service 622062
					prefix, total_read, h->length);
Packit Service e18529
				return;
Packit Service e18529
			}
Packit Service e18529
Packit Service 622062
			dmi_parse_protocol_record(prefix, rec);
Packit Service e18529
Packit Service e18529
			/*
Packit Service e18529
			 * DSP0270: 8.6
Packit Service e18529
			 * Each record is rec[1] bytes long, starting at the
Packit Service e18529
			 * data byte immediately following the length field.
Packit Service e18529
			 * That means we need to add the byte for the rec id,
Packit Service e18529
			 * the byte for the length field, and the value of the
Packit Service e18529
			 * length field itself.
Packit Service e18529
			 */
Packit Service e18529
			rec += rec[1] + 2;
Packit Service e18529
		}
Packit Service e18529
	}
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * 7.44 TPM Device (Type 43)
Packit Service e18529
 */
Packit Service e18529
Packit Service e18529
static void dmi_tpm_vendor_id(const u8 *p)
Packit Service e18529
{
Packit Service e18529
	char vendor_id[5];
Packit Service e18529
	int i;
Packit Service e18529
Packit Service e18529
	/* ASCII filtering */
Packit Service e18529
	for (i = 0; i < 4 && p[i] != 0; i++)
Packit Service e18529
	{
Packit Service e18529
		if (p[i] < 32 || p[i] >= 127)
Packit Service e18529
			vendor_id[i] = '.';
Packit Service e18529
		else
Packit Service e18529
			vendor_id[i] = p[i];
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	/* Terminate the string */
Packit Service e18529
	vendor_id[i] = '\0';
Packit Service e18529
Packit Service 622062
	printf(" %s", vendor_id);
Packit Service e18529
}
Packit Service e18529
Packit Service 622062
static void dmi_tpm_characteristics(u64 code, const char *prefix)
Packit Service e18529
{
Packit Service e18529
	/* 7.1.1 */
Packit Service e18529
	static const char *characteristics[] = {
Packit Service e18529
		"TPM Device characteristics not supported", /* 2 */
Packit Service e18529
		"Family configurable via firmware update",
Packit Service e18529
		"Family configurable via platform software support",
Packit Service e18529
		"Family configurable via OEM proprietary mechanism" /* 5 */
Packit Service e18529
	};
Packit Service e18529
	int i;
Packit Service e18529
Packit Service e18529
	/*
Packit Service e18529
	 * This isn't very clear what this bit is supposed to mean
Packit Service e18529
	 */
Packit Service e18529
	if (code.l & (1 << 2))
Packit Service e18529
	{
Packit Service 622062
		printf("%s%s\n",
Packit Service 622062
			prefix, characteristics[0]);
Packit Service e18529
		return;
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	for (i = 3; i <= 5; i++)
Packit Service e18529
		if (code.l & (1 << i))
Packit Service 622062
			printf("%s%s\n",
Packit Service 622062
				prefix, characteristics[i - 2]);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * Main
Packit Service e18529
 */
Packit Service e18529
Packit Service e18529
static void dmi_decode(const struct dmi_header *h, u16 ver)
Packit Service e18529
{
Packit Service e18529
	const u8 *data = h->data;
Packit Service e18529
Packit Service e18529
	/*
Packit Service e18529
	 * Note: DMI types 37 and 42 are untested
Packit Service e18529
	 */
Packit Service e18529
	switch (h->type)
Packit Service e18529
	{
Packit Service e18529
		case 0: /* 7.1 BIOS Information */
Packit Service 622062
			printf("BIOS Information\n");
Packit Service e18529
			if (h->length < 0x12) break;
Packit Service 622062
			printf("\tVendor: %s\n",
Packit Service e18529
				dmi_string(h, data[0x04]));
Packit Service 622062
			printf("\tVersion: %s\n",
Packit Service e18529
				dmi_string(h, data[0x05]));
Packit Service 622062
			printf("\tRelease Date: %s\n",
Packit Service e18529
				dmi_string(h, data[0x08]));
Packit Service e18529
			/*
Packit Service e18529
			 * On IA-64, the BIOS base address will read 0 because
Packit Service e18529
			 * there is no BIOS. Skip the base address and the
Packit Service e18529
			 * runtime size in this case.
Packit Service e18529
			 */
Packit Service e18529
			if (WORD(data + 0x06) != 0)
Packit Service e18529
			{
Packit Service 622062
				printf("\tAddress: 0x%04X0\n",
Packit Service e18529
					WORD(data + 0x06));
Packit Service 622062
				printf("\tRuntime Size:");
Packit Service e18529
				dmi_bios_runtime_size((0x10000 - WORD(data + 0x06)) << 4);
Packit Service 622062
				printf("\n");
Packit Service e18529
			}
Packit Service 622062
			printf("\tROM Size:");
Packit Service e18529
			dmi_bios_rom_size(data[0x09], h->length < 0x1A ? 16 : WORD(data + 0x18));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tCharacteristics:\n");
Packit Service 622062
			dmi_bios_characteristics(QWORD(data + 0x0A), "\t\t");
Packit Service e18529
			if (h->length < 0x13) break;
Packit Service 622062
			dmi_bios_characteristics_x1(data[0x12], "\t\t");
Packit Service e18529
			if (h->length < 0x14) break;
Packit Service 622062
			dmi_bios_characteristics_x2(data[0x13], "\t\t");
Packit Service e18529
			if (h->length < 0x18) break;
Packit Service e18529
			if (data[0x14] != 0xFF && data[0x15] != 0xFF)
Packit Service 622062
				printf("\tBIOS Revision: %u.%u\n",
Packit Service e18529
					data[0x14], data[0x15]);
Packit Service e18529
			if (data[0x16] != 0xFF && data[0x17] != 0xFF)
Packit Service 622062
				printf("\tFirmware Revision: %u.%u\n",
Packit Service e18529
					data[0x16], data[0x17]);
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 1: /* 7.2 System Information */
Packit Service 622062
			printf("System Information\n");
Packit Service e18529
			if (h->length < 0x08) break;
Packit Service 622062
			printf("\tManufacturer: %s\n",
Packit Service e18529
				dmi_string(h, data[0x04]));
Packit Service 622062
			printf("\tProduct Name: %s\n",
Packit Service e18529
				dmi_string(h, data[0x05]));
Packit Service 622062
			printf("\tVersion: %s\n",
Packit Service e18529
				dmi_string(h, data[0x06]));
Packit Service 622062
			printf("\tSerial Number: %s\n",
Packit Service e18529
				dmi_string(h, data[0x07]));
Packit Service e18529
			if (h->length < 0x19) break;
Packit Service 622062
			printf("\tUUID: ");
Packit Service 622062
			dmi_system_uuid(data + 0x08, ver);
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tWake-up Type: %s\n",
Packit Service e18529
				dmi_system_wake_up_type(data[0x18]));
Packit Service e18529
			if (h->length < 0x1B) break;
Packit Service 622062
			printf("\tSKU Number: %s\n",
Packit Service e18529
				dmi_string(h, data[0x19]));
Packit Service 622062
			printf("\tFamily: %s\n",
Packit Service e18529
				dmi_string(h, data[0x1A]));
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 2: /* 7.3 Base Board Information */
Packit Service 622062
			printf("Base Board Information\n");
Packit Service e18529
			if (h->length < 0x08) break;
Packit Service 622062
			printf("\tManufacturer: %s\n",
Packit Service e18529
				dmi_string(h, data[0x04]));
Packit Service 622062
			printf("\tProduct Name: %s\n",
Packit Service e18529
				dmi_string(h, data[0x05]));
Packit Service 622062
			printf("\tVersion: %s\n",
Packit Service e18529
				dmi_string(h, data[0x06]));
Packit Service 622062
			printf("\tSerial Number: %s\n",
Packit Service e18529
				dmi_string(h, data[0x07]));
Packit Service e18529
			if (h->length < 0x09) break;
Packit Service 622062
			printf("\tAsset Tag: %s\n",
Packit Service e18529
				dmi_string(h, data[0x08]));
Packit Service e18529
			if (h->length < 0x0A) break;
Packit Service 622062
			printf("\tFeatures:");
Packit Service 622062
			dmi_base_board_features(data[0x09], "\t\t");
Packit Service e18529
			if (h->length < 0x0E) break;
Packit Service 622062
			printf("\tLocation In Chassis: %s\n",
Packit Service e18529
				dmi_string(h, data[0x0A]));
Packit Service e18529
			if (!(opt.flags & FLAG_QUIET))
Packit Service 622062
				printf("\tChassis Handle: 0x%04X\n",
Packit Service e18529
					WORD(data + 0x0B));
Packit Service 622062
			printf("\tType: %s\n",
Packit Service e18529
				dmi_base_board_type(data[0x0D]));
Packit Service e18529
			if (h->length < 0x0F) break;
Packit Service e18529
			if (h->length < 0x0F + data[0x0E] * sizeof(u16)) break;
Packit Service e18529
			if (!(opt.flags & FLAG_QUIET))
Packit Service 622062
				dmi_base_board_handles(data[0x0E], data + 0x0F, "\t");
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 3: /* 7.4 Chassis Information */
Packit Service 622062
			printf("Chassis Information\n");
Packit Service e18529
			if (h->length < 0x09) break;
Packit Service 622062
			printf("\tManufacturer: %s\n",
Packit Service e18529
				dmi_string(h, data[0x04]));
Packit Service 622062
			printf("\tType: %s\n",
Packit Service e18529
				dmi_chassis_type(data[0x05]));
Packit Service 622062
			printf("\tLock: %s\n",
Packit Service e18529
				dmi_chassis_lock(data[0x05] >> 7));
Packit Service 622062
			printf("\tVersion: %s\n",
Packit Service e18529
				dmi_string(h, data[0x06]));
Packit Service 622062
			printf("\tSerial Number: %s\n",
Packit Service e18529
				dmi_string(h, data[0x07]));
Packit Service 622062
			printf("\tAsset Tag: %s\n",
Packit Service e18529
				dmi_string(h, data[0x08]));
Packit Service e18529
			if (h->length < 0x0D) break;
Packit Service 622062
			printf("\tBoot-up State: %s\n",
Packit Service e18529
				dmi_chassis_state(data[0x09]));
Packit Service 622062
			printf("\tPower Supply State: %s\n",
Packit Service e18529
				dmi_chassis_state(data[0x0A]));
Packit Service 622062
			printf("\tThermal State: %s\n",
Packit Service e18529
				dmi_chassis_state(data[0x0B]));
Packit Service 622062
			printf("\tSecurity Status: %s\n",
Packit Service e18529
				dmi_chassis_security_status(data[0x0C]));
Packit Service e18529
			if (h->length < 0x11) break;
Packit Service 622062
			printf("\tOEM Information: 0x%08X\n",
Packit Service e18529
				DWORD(data + 0x0D));
Packit Service e18529
			if (h->length < 0x13) break;
Packit Service 622062
			printf("\tHeight:");
Packit Service e18529
			dmi_chassis_height(data[0x11]);
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tNumber Of Power Cords:");
Packit Service e18529
			dmi_chassis_power_cords(data[0x12]);
Packit Service 622062
			printf("\n");
Packit Service e18529
			if (h->length < 0x15) break;
Packit Service e18529
			if (h->length < 0x15 + data[0x13] * data[0x14]) break;
Packit Service 622062
			dmi_chassis_elements(data[0x13], data[0x14], data + 0x15, "\t");
Packit Service e18529
			if (h->length < 0x16 + data[0x13] * data[0x14]) break;
Packit Service 622062
			printf("\tSKU Number: %s\n",
Packit Service e18529
				dmi_string(h, data[0x15 + data[0x13] * data[0x14]]));
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 4: /* 7.5 Processor Information */
Packit Service 622062
			printf("Processor Information\n");
Packit Service e18529
			if (h->length < 0x1A) break;
Packit Service 622062
			printf("\tSocket Designation: %s\n",
Packit Service e18529
				dmi_string(h, data[0x04]));
Packit Service 622062
			printf("\tType: %s\n",
Packit Service e18529
				dmi_processor_type(data[0x05]));
Packit Service 622062
			printf("\tFamily: %s\n",
Packit Service e18529
				dmi_processor_family(h, ver));
Packit Service 622062
			printf("\tManufacturer: %s\n",
Packit Service e18529
				dmi_string(h, data[0x07]));
Packit Service 622062
			dmi_processor_id(h, "\t");
Packit Service 622062
			printf("\tVersion: %s\n",
Packit Service e18529
				dmi_string(h, data[0x10]));
Packit Service 622062
			printf("\tVoltage:");
Packit Service 622062
			dmi_processor_voltage(data[0x11]);
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tExternal Clock: ");
Packit Service 622062
			dmi_processor_frequency(data + 0x12);
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tMax Speed: ");
Packit Service 622062
			dmi_processor_frequency(data + 0x14);
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tCurrent Speed: ");
Packit Service 622062
			dmi_processor_frequency(data + 0x16);
Packit Service 622062
			printf("\n");
Packit Service e18529
			if (data[0x18] & (1 << 6))
Packit Service 622062
				printf("\tStatus: Populated, %s\n",
Packit Service e18529
					dmi_processor_status(data[0x18] & 0x07));
Packit Service e18529
			else
Packit Service 622062
				printf("\tStatus: Unpopulated\n");
Packit Service 622062
			printf("\tUpgrade: %s\n",
Packit Service e18529
				dmi_processor_upgrade(data[0x19]));
Packit Service e18529
			if (h->length < 0x20) break;
Packit Service e18529
			if (!(opt.flags & FLAG_QUIET))
Packit Service e18529
			{
Packit Service 622062
				printf("\tL1 Cache Handle:");
Packit Service 622062
				dmi_processor_cache(WORD(data + 0x1A), "L1", ver);
Packit Service 622062
				printf("\n");
Packit Service 622062
				printf("\tL2 Cache Handle:");
Packit Service 622062
				dmi_processor_cache(WORD(data + 0x1C), "L2", ver);
Packit Service 622062
				printf("\n");
Packit Service 622062
				printf("\tL3 Cache Handle:");
Packit Service 622062
				dmi_processor_cache(WORD(data + 0x1E), "L3", ver);
Packit Service 622062
				printf("\n");
Packit Service e18529
			}
Packit Service e18529
			if (h->length < 0x23) break;
Packit Service 622062
			printf("\tSerial Number: %s\n",
Packit Service e18529
				dmi_string(h, data[0x20]));
Packit Service 622062
			printf("\tAsset Tag: %s\n",
Packit Service e18529
				dmi_string(h, data[0x21]));
Packit Service 622062
			printf("\tPart Number: %s\n",
Packit Service e18529
				dmi_string(h, data[0x22]));
Packit Service e18529
			if (h->length < 0x28) break;
Packit Service e18529
			if (data[0x23] != 0)
Packit Service 622062
				printf("\tCore Count: %u\n",
Packit Service e18529
					h->length >= 0x2C && data[0x23] == 0xFF ?
Packit Service e18529
					WORD(data + 0x2A) : data[0x23]);
Packit Service e18529
			if (data[0x24] != 0)
Packit Service 622062
				printf("\tCore Enabled: %u\n",
Packit Service e18529
					h->length >= 0x2E && data[0x24] == 0xFF ?
Packit Service e18529
					WORD(data + 0x2C) : data[0x24]);
Packit Service e18529
			if (data[0x25] != 0)
Packit Service 622062
				printf("\tThread Count: %u\n",
Packit Service e18529
					h->length >= 0x30 && data[0x25] == 0xFF ?
Packit Service e18529
					WORD(data + 0x2E) : data[0x25]);
Packit Service 622062
			printf("\tCharacteristics:");
Packit Service 622062
			dmi_processor_characteristics(WORD(data + 0x26), "\t\t");
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 5: /* 7.6 Memory Controller Information */
Packit Service 622062
			printf("Memory Controller Information\n");
Packit Service e18529
			if (h->length < 0x0F) break;
Packit Service 622062
			printf("\tError Detecting Method: %s\n",
Packit Service e18529
				dmi_memory_controller_ed_method(data[0x04]));
Packit Service 622062
			printf("\tError Correcting Capabilities:");
Packit Service 622062
			dmi_memory_controller_ec_capabilities(data[0x05], "\t\t");
Packit Service 622062
			printf("\tSupported Interleave: %s\n",
Packit Service e18529
				dmi_memory_controller_interleave(data[0x06]));
Packit Service 622062
			printf("\tCurrent Interleave: %s\n",
Packit Service e18529
				dmi_memory_controller_interleave(data[0x07]));
Packit Service 622062
			printf("\tMaximum Memory Module Size: %u MB\n",
Packit Service e18529
				1 << data[0x08]);
Packit Service 622062
			printf("\tMaximum Total Memory Size: %u MB\n",
Packit Service e18529
				data[0x0E] * (1 << data[0x08]));
Packit Service 622062
			printf("\tSupported Speeds:");
Packit Service 622062
			dmi_memory_controller_speeds(WORD(data + 0x09), "\t\t");
Packit Service 622062
			printf("\tSupported Memory Types:");
Packit Service 622062
			dmi_memory_module_types(WORD(data + 0x0B), "\n\t\t");
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tMemory Module Voltage:");
Packit Service 622062
			dmi_processor_voltage(data[0x0D]);
Packit Service 622062
			printf("\n");
Packit Service e18529
			if (h->length < 0x0F + data[0x0E] * sizeof(u16)) break;
Packit Service 622062
			dmi_memory_controller_slots(data[0x0E], data + 0x0F, "\t");
Packit Service e18529
			if (h->length < 0x10 + data[0x0E] * sizeof(u16)) break;
Packit Service 622062
			printf("\tEnabled Error Correcting Capabilities:");
Packit Service 622062
			dmi_memory_controller_ec_capabilities(data[0x0F + data[0x0E] * sizeof(u16)], "\t\t");
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 6: /* 7.7 Memory Module Information */
Packit Service 622062
			printf("Memory Module Information\n");
Packit Service e18529
			if (h->length < 0x0C) break;
Packit Service 622062
			printf("\tSocket Designation: %s\n",
Packit Service e18529
				dmi_string(h, data[0x04]));
Packit Service 622062
			printf("\tBank Connections:");
Packit Service e18529
			dmi_memory_module_connections(data[0x05]);
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tCurrent Speed:");
Packit Service 622062
			dmi_memory_module_speed(data[0x06]);
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tType:");
Packit Service 622062
			dmi_memory_module_types(WORD(data + 0x07), " ");
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tInstalled Size:");
Packit Service 622062
			dmi_memory_module_size(data[0x09]);
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tEnabled Size:");
Packit Service 622062
			dmi_memory_module_size(data[0x0A]);
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tError Status:");
Packit Service 97f994
			dmi_memory_module_error(data[0x0B]);
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 7: /* 7.8 Cache Information */
Packit Service 622062
			printf("Cache Information\n");
Packit Service e18529
			if (h->length < 0x0F) break;
Packit Service 622062
			printf("\tSocket Designation: %s\n",
Packit Service e18529
				dmi_string(h, data[0x04]));
Packit Service 622062
			printf("\tConfiguration: %s, %s, Level %u\n",
Packit Service e18529
				WORD(data + 0x05) & 0x0080 ? "Enabled" : "Disabled",
Packit Service e18529
				WORD(data + 0x05) & 0x0008 ? "Socketed" : "Not Socketed",
Packit Service e18529
				(WORD(data + 0x05) & 0x0007) + 1);
Packit Service 622062
			printf("\tOperational Mode: %s\n",
Packit Service e18529
				dmi_cache_mode((WORD(data + 0x05) >> 8) & 0x0003));
Packit Service 622062
			printf("\tLocation: %s\n",
Packit Service e18529
				dmi_cache_location((WORD(data + 0x05) >> 5) & 0x0003));
Packit Service 622062
			printf("\tInstalled Size:");
Packit Service e18529
			if (h->length >= 0x1B)
Packit Service 622062
				dmi_cache_size_2(DWORD(data + 0x17));
Packit Service e18529
			else
Packit Service 622062
				dmi_cache_size(WORD(data + 0x09));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tMaximum Size:");
Packit Service e18529
			if (h->length >= 0x17)
Packit Service 622062
				dmi_cache_size_2(DWORD(data + 0x13));
Packit Service e18529
			else
Packit Service 622062
				dmi_cache_size(WORD(data + 0x07));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tSupported SRAM Types:");
Packit Service 622062
			dmi_cache_types(WORD(data + 0x0B), "\n\t\t");
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tInstalled SRAM Type:");
Packit Service 622062
			dmi_cache_types(WORD(data + 0x0D), " ");
Packit Service 622062
			printf("\n");
Packit Service e18529
			if (h->length < 0x13) break;
Packit Service 622062
			printf("\tSpeed:");
Packit Service 622062
			dmi_memory_module_speed(data[0x0F]);
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tError Correction Type: %s\n",
Packit Service e18529
				dmi_cache_ec_type(data[0x10]));
Packit Service 622062
			printf("\tSystem Type: %s\n",
Packit Service e18529
				dmi_cache_type(data[0x11]));
Packit Service 622062
			printf("\tAssociativity: %s\n",
Packit Service e18529
				dmi_cache_associativity(data[0x12]));
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 8: /* 7.9 Port Connector Information */
Packit Service 622062
			printf("Port Connector Information\n");
Packit Service e18529
			if (h->length < 0x09) break;
Packit Service 622062
			printf("\tInternal Reference Designator: %s\n",
Packit Service e18529
				dmi_string(h, data[0x04]));
Packit Service 622062
			printf("\tInternal Connector Type: %s\n",
Packit Service e18529
				dmi_port_connector_type(data[0x05]));
Packit Service 622062
			printf("\tExternal Reference Designator: %s\n",
Packit Service e18529
				dmi_string(h, data[0x06]));
Packit Service 622062
			printf("\tExternal Connector Type: %s\n",
Packit Service e18529
				dmi_port_connector_type(data[0x07]));
Packit Service 622062
			printf("\tPort Type: %s\n",
Packit Service e18529
				dmi_port_type(data[0x08]));
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 9: /* 7.10 System Slots */
Packit Service 622062
			printf("System Slot Information\n");
Packit Service e18529
			if (h->length < 0x0C) break;
Packit Service 622062
			printf("\tDesignation: %s\n",
Packit Service e18529
				dmi_string(h, data[0x04]));
Packit Service 622062
			printf("\tType: %s%s\n",
Packit Service e18529
				dmi_slot_bus_width(data[0x06]),
Packit Service e18529
				dmi_slot_type(data[0x05]));
Packit Service 622062
			printf("\tCurrent Usage: %s\n",
Packit Service e18529
				dmi_slot_current_usage(data[0x07]));
Packit Service 622062
			printf("\tLength: %s\n",
Packit Service e18529
				dmi_slot_length(data[0x08]));
Packit Service 622062
			dmi_slot_id(data[0x09], data[0x0A], data[0x05], "\t");
Packit Service 622062
			printf("\tCharacteristics:");
Packit Service e18529
			if (h->length < 0x0D)
Packit Service 622062
				dmi_slot_characteristics(data[0x0B], 0x00, "\t\t");
Packit Service e18529
			else
Packit Service 622062
				dmi_slot_characteristics(data[0x0B], data[0x0C], "\t\t");
Packit Service e18529
			if (h->length < 0x11) break;
Packit Service 622062
			dmi_slot_segment_bus_func(WORD(data + 0x0D), data[0x0F], data[0x10], "\t");
Packit Service 568207
			if (h->length < 0x13) break;
Packit Service 568207
			printf("\tData Bus Width: %u\n", data[0x11]);
Packit Service 568207
			printf("\tPeer Devices: %u\n", data[0x12]);
Packit Service 568207
			if (h->length - 0x13 >= data[0x12] * 5)
Packit Service 568207
				dmi_slot_peers(data[0x12], data + 0x13, "\t");
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 10: /* 7.11 On Board Devices Information */
Packit Service 622062
			dmi_on_board_devices(h, "");
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 11: /* 7.12 OEM Strings */
Packit Service 622062
			printf("OEM Strings\n");
Packit Service e18529
			if (h->length < 0x05) break;
Packit Service 622062
			dmi_oem_strings(h, "\t");
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 12: /* 7.13 System Configuration Options */
Packit Service 622062
			printf("System Configuration Options\n");
Packit Service e18529
			if (h->length < 0x05) break;
Packit Service 622062
			dmi_system_configuration_options(h, "\t");
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 13: /* 7.14 BIOS Language Information */
Packit Service 622062
			printf("BIOS Language Information\n");
Packit Service e18529
			if (h->length < 0x16) break;
Packit Service e18529
			if (ver >= 0x0201)
Packit Service e18529
			{
Packit Service 622062
				printf("\tLanguage Description Format: %s\n",
Packit Service e18529
					dmi_bios_language_format(data[0x05]));
Packit Service e18529
			}
Packit Service 622062
			printf("\tInstallable Languages: %u\n", data[0x04]);
Packit Service 622062
			dmi_bios_languages(h, "\t\t");
Packit Service 622062
			printf("\tCurrently Installed Language: %s\n",
Packit Service e18529
				dmi_string(h, data[0x15]));
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 14: /* 7.15 Group Associations */
Packit Service 622062
			printf("Group Associations\n");
Packit Service e18529
			if (h->length < 0x05) break;
Packit Service 622062
			printf("\tName: %s\n",
Packit Service e18529
				dmi_string(h, data[0x04]));
Packit Service 622062
			printf("\tItems: %u\n",
Packit Service e18529
				(h->length - 0x05) / 3);
Packit Service 622062
			dmi_group_associations_items((h->length - 0x05) / 3, data + 0x05, "\t\t");
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 15: /* 7.16 System Event Log */
Packit Service 622062
			printf("System Event Log\n");
Packit Service e18529
			if (h->length < 0x14) break;
Packit Service 622062
			printf("\tArea Length: %u bytes\n",
Packit Service e18529
				WORD(data + 0x04));
Packit Service 622062
			printf("\tHeader Start Offset: 0x%04X\n",
Packit Service e18529
				WORD(data + 0x06));
Packit Service e18529
			if (WORD(data + 0x08) - WORD(data + 0x06))
Packit Service 622062
				printf("\tHeader Length: %u byte%s\n",
Packit Service e18529
					WORD(data + 0x08) - WORD(data + 0x06),
Packit Service e18529
					WORD(data + 0x08) - WORD(data + 0x06) > 1 ? "s" : "");
Packit Service 622062
			printf("\tData Start Offset: 0x%04X\n",
Packit Service e18529
				WORD(data + 0x08));
Packit Service 622062
			printf("\tAccess Method: %s\n",
Packit Service e18529
				dmi_event_log_method(data[0x0A]));
Packit Service 622062
			printf("\tAccess Address:");
Packit Service e18529
			dmi_event_log_address(data[0x0A], data + 0x10);
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tStatus:");
Packit Service e18529
			dmi_event_log_status(data[0x0B]);
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tChange Token: 0x%08X\n",
Packit Service e18529
				DWORD(data + 0x0C));
Packit Service e18529
			if (h->length < 0x17) break;
Packit Service 622062
			printf("\tHeader Format: %s\n",
Packit Service e18529
				dmi_event_log_header_type(data[0x14]));
Packit Service 622062
			printf("\tSupported Log Type Descriptors: %u\n",
Packit Service e18529
				data[0x15]);
Packit Service e18529
			if (h->length < 0x17 + data[0x15] * data[0x16]) break;
Packit Service 622062
			dmi_event_log_descriptors(data[0x15], data[0x16], data + 0x17, "\t");
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 16: /* 7.17 Physical Memory Array */
Packit Service 622062
			printf("Physical Memory Array\n");
Packit Service e18529
			if (h->length < 0x0F) break;
Packit Service 622062
			printf("\tLocation: %s\n",
Packit Service e18529
				dmi_memory_array_location(data[0x04]));
Packit Service 622062
			printf("\tUse: %s\n",
Packit Service e18529
				dmi_memory_array_use(data[0x05]));
Packit Service 622062
			printf("\tError Correction Type: %s\n",
Packit Service e18529
				dmi_memory_array_ec_type(data[0x06]));
Packit Service 622062
			printf("\tMaximum Capacity:");
Packit Service e18529
			if (DWORD(data + 0x07) == 0x80000000)
Packit Service e18529
			{
Packit Service e18529
				if (h->length < 0x17)
Packit Service 622062
					printf(" Unknown");
Packit Service e18529
				else
Packit Service 622062
					dmi_print_memory_size(QWORD(data + 0x0F), 0);
Packit Service e18529
			}
Packit Service e18529
			else
Packit Service e18529
			{
Packit Service e18529
				u64 capacity;
Packit Service e18529
Packit Service e18529
				capacity.h = 0;
Packit Service e18529
				capacity.l = DWORD(data + 0x07);
Packit Service 622062
				dmi_print_memory_size(capacity, 1);
Packit Service e18529
			}
Packit Service 622062
			printf("\n");
Packit Service e18529
			if (!(opt.flags & FLAG_QUIET))
Packit Service 622062
			{
Packit Service 622062
				printf("\tError Information Handle:");
Packit Service e18529
				dmi_memory_array_error_handle(WORD(data + 0x0B));
Packit Service 622062
				printf("\n");
Packit Service 622062
			}
Packit Service 622062
			printf("\tNumber Of Devices: %u\n",
Packit Service e18529
				WORD(data + 0x0D));
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 17: /* 7.18 Memory Device */
Packit Service 622062
			printf("Memory Device\n");
Packit Service e18529
			if (h->length < 0x15) break;
Packit Service e18529
			if (!(opt.flags & FLAG_QUIET))
Packit Service e18529
			{
Packit Service 622062
				printf("\tArray Handle: 0x%04X\n",
Packit Service e18529
					WORD(data + 0x04));
Packit Service 622062
				printf("\tError Information Handle:");
Packit Service e18529
				dmi_memory_array_error_handle(WORD(data + 0x06));
Packit Service 622062
				printf("\n");
Packit Service e18529
			}
Packit Service 622062
			printf("\tTotal Width:");
Packit Service 622062
			dmi_memory_device_width(WORD(data + 0x08));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tData Width:");
Packit Service 622062
			dmi_memory_device_width(WORD(data + 0x0A));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tSize:");
Packit Service e18529
			if (h->length >= 0x20 && WORD(data + 0x0C) == 0x7FFF)
Packit Service e18529
				dmi_memory_device_extended_size(DWORD(data + 0x1C));
Packit Service e18529
			else
Packit Service e18529
				dmi_memory_device_size(WORD(data + 0x0C));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tForm Factor: %s\n",
Packit Service e18529
				dmi_memory_device_form_factor(data[0x0E]));
Packit Service 622062
			printf("\tSet:");
Packit Service e18529
			dmi_memory_device_set(data[0x0F]);
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tLocator: %s\n",
Packit Service e18529
				dmi_string(h, data[0x10]));
Packit Service 622062
			printf("\tBank Locator: %s\n",
Packit Service e18529
				dmi_string(h, data[0x11]));
Packit Service 622062
			printf("\tType: %s\n",
Packit Service e18529
				dmi_memory_device_type(data[0x12]));
Packit Service 622062
			printf("\tType Detail:");
Packit Service e18529
			dmi_memory_device_type_detail(WORD(data + 0x13));
Packit Service 622062
			printf("\n");
Packit Service e18529
			if (h->length < 0x17) break;
Packit Service 622062
			printf("\tSpeed:");
Packit Service 622062
			dmi_memory_device_speed(WORD(data + 0x15));
Packit Service 622062
			printf("\n");
Packit Service e18529
			if (h->length < 0x1B) break;
Packit Service 622062
			printf("\tManufacturer: %s\n",
Packit Service e18529
				dmi_string(h, data[0x17]));
Packit Service 622062
			printf("\tSerial Number: %s\n",
Packit Service e18529
				dmi_string(h, data[0x18]));
Packit Service 622062
			printf("\tAsset Tag: %s\n",
Packit Service e18529
				dmi_string(h, data[0x19]));
Packit Service 622062
			printf("\tPart Number: %s\n",
Packit Service e18529
				dmi_string(h, data[0x1A]));
Packit Service e18529
			if (h->length < 0x1C) break;
Packit Service 622062
			printf("\tRank: ");
Packit Service e18529
			if ((data[0x1B] & 0x0F) == 0)
Packit Service 622062
				printf("Unknown");
Packit Service e18529
			else
Packit Service 622062
				printf("%u", data[0x1B] & 0x0F);
Packit Service 622062
			printf("\n");
Packit Service e18529
			if (h->length < 0x22) break;
Packit Service 622062
			printf("\tConfigured Memory Speed:");
Packit Service 622062
			dmi_memory_device_speed(WORD(data + 0x20));
Packit Service 622062
			printf("\n");
Packit Service e18529
			if (h->length < 0x28) break;
Packit Service 622062
			printf("\tMinimum Voltage:");
Packit Service 622062
			dmi_memory_voltage_value(WORD(data + 0x22));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tMaximum Voltage:");
Packit Service 622062
			dmi_memory_voltage_value(WORD(data + 0x24));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tConfigured Voltage:");
Packit Service 622062
			dmi_memory_voltage_value(WORD(data + 0x26));
Packit Service 622062
			printf("\n");
Packit Service e18529
			if (h->length < 0x34) break;
Packit Service 622062
			printf("\tMemory Technology:");
Packit Service e18529
			dmi_memory_technology(data[0x28]);
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tMemory Operating Mode Capability:");
Packit Service e18529
			dmi_memory_operating_mode_capability(WORD(data + 0x29));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tFirmware Version: %s\n",
Packit Service e18529
				dmi_string(h, data[0x2B]));
Packit Service 622062
			printf("\tModule Manufacturer ID:");
Packit Service 622062
			dmi_memory_manufacturer_id(WORD(data + 0x2C));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tModule Product ID:");
Packit Service 622062
			dmi_memory_product_id(WORD(data + 0x2E));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tMemory Subsystem Controller Manufacturer ID:");
Packit Service 622062
			dmi_memory_manufacturer_id(WORD(data + 0x30));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tMemory Subsystem Controller Product ID:");
Packit Service 622062
			dmi_memory_product_id(WORD(data + 0x32));
Packit Service 622062
			printf("\n");
Packit Service e18529
			if (h->length < 0x3C) break;
Packit Service 622062
			printf("\tNon-Volatile Size:");
Packit Service 622062
			dmi_memory_size(QWORD(data + 0x34));
Packit Service 622062
			printf("\n");
Packit Service e18529
			if (h->length < 0x44) break;
Packit Service 622062
			printf("\tVolatile Size:");
Packit Service 622062
			dmi_memory_size(QWORD(data + 0x3C));
Packit Service 622062
			printf("\n");
Packit Service e18529
			if (h->length < 0x4C) break;
Packit Service 622062
			printf("\tCache Size:");
Packit Service 622062
			dmi_memory_size(QWORD(data + 0x44));
Packit Service 622062
			printf("\n");
Packit Service e18529
			if (h->length < 0x54) break;
Packit Service 622062
			printf("\tLogical Size:");
Packit Service 622062
			dmi_memory_size(QWORD(data + 0x4C));
Packit Service 622062
			printf("\n");
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 18: /* 7.19 32-bit Memory Error Information */
Packit Service 622062
			printf("32-bit Memory Error Information\n");
Packit Service e18529
			if (h->length < 0x17) break;
Packit Service 622062
			printf("\tType: %s\n",
Packit Service e18529
				dmi_memory_error_type(data[0x04]));
Packit Service 622062
			printf("\tGranularity: %s\n",
Packit Service e18529
				dmi_memory_error_granularity(data[0x05]));
Packit Service 622062
			printf("\tOperation: %s\n",
Packit Service e18529
				dmi_memory_error_operation(data[0x06]));
Packit Service 622062
			printf("\tVendor Syndrome:");
Packit Service e18529
			dmi_memory_error_syndrome(DWORD(data + 0x07));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tMemory Array Address:");
Packit Service 622062
			dmi_32bit_memory_error_address(DWORD(data + 0x0B));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tDevice Address:");
Packit Service 622062
			dmi_32bit_memory_error_address(DWORD(data + 0x0F));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tResolution:");
Packit Service 622062
			dmi_32bit_memory_error_address(DWORD(data + 0x13));
Packit Service 622062
			printf("\n");
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 19: /* 7.20 Memory Array Mapped Address */
Packit Service 622062
			printf("Memory Array Mapped Address\n");
Packit Service e18529
			if (h->length < 0x0F) break;
Packit Service e18529
			if (h->length >= 0x1F && DWORD(data + 0x04) == 0xFFFFFFFF)
Packit Service e18529
			{
Packit Service e18529
				u64 start, end;
Packit Service e18529
Packit Service e18529
				start = QWORD(data + 0x0F);
Packit Service e18529
				end = QWORD(data + 0x17);
Packit Service e18529
Packit Service 622062
				printf("\tStarting Address: 0x%08X%08Xk\n",
Packit Service e18529
					start.h, start.l);
Packit Service 622062
				printf("\tEnding Address: 0x%08X%08Xk\n",
Packit Service e18529
					end.h, end.l);
Packit Service 622062
				printf("\tRange Size:");
Packit Service e18529
				dmi_mapped_address_extended_size(start, end);
Packit Service e18529
			}
Packit Service e18529
			else
Packit Service e18529
			{
Packit Service 622062
				printf("\tStarting Address: 0x%08X%03X\n",
Packit Service e18529
					DWORD(data + 0x04) >> 2,
Packit Service e18529
					(DWORD(data + 0x04) & 0x3) << 10);
Packit Service 622062
				printf("\tEnding Address: 0x%08X%03X\n",
Packit Service e18529
					DWORD(data + 0x08) >> 2,
Packit Service e18529
					((DWORD(data + 0x08) & 0x3) << 10) + 0x3FF);
Packit Service 622062
				printf("\tRange Size:");
Packit Service e18529
				dmi_mapped_address_size(DWORD(data + 0x08) - DWORD(data + 0x04) + 1);
Packit Service e18529
			}
Packit Service 622062
			printf("\n");
Packit Service e18529
			if (!(opt.flags & FLAG_QUIET))
Packit Service 622062
				printf("\tPhysical Array Handle: 0x%04X\n",
Packit Service e18529
					WORD(data + 0x0C));
Packit Service 622062
			printf("\tPartition Width: %u\n",
Packit Service e18529
				data[0x0E]);
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 20: /* 7.21 Memory Device Mapped Address */
Packit Service 622062
			printf("Memory Device Mapped Address\n");
Packit Service e18529
			if (h->length < 0x13) break;
Packit Service e18529
			if (h->length >= 0x23 && DWORD(data + 0x04) == 0xFFFFFFFF)
Packit Service e18529
			{
Packit Service e18529
				u64 start, end;
Packit Service e18529
Packit Service e18529
				start = QWORD(data + 0x13);
Packit Service e18529
				end = QWORD(data + 0x1B);
Packit Service e18529
Packit Service 622062
				printf("\tStarting Address: 0x%08X%08Xk\n",
Packit Service e18529
					start.h, start.l);
Packit Service 622062
				printf("\tEnding Address: 0x%08X%08Xk\n",
Packit Service e18529
					end.h, end.l);
Packit Service 622062
				printf("\tRange Size:");
Packit Service e18529
				dmi_mapped_address_extended_size(start, end);
Packit Service e18529
			}
Packit Service e18529
			else
Packit Service e18529
			{
Packit Service 622062
				printf("\tStarting Address: 0x%08X%03X\n",
Packit Service e18529
					DWORD(data + 0x04) >> 2,
Packit Service e18529
					(DWORD(data + 0x04) & 0x3) << 10);
Packit Service 622062
				printf("\tEnding Address: 0x%08X%03X\n",
Packit Service e18529
					DWORD(data + 0x08) >> 2,
Packit Service e18529
					((DWORD(data + 0x08) & 0x3) << 10) + 0x3FF);
Packit Service 622062
				printf("\tRange Size:");
Packit Service e18529
				dmi_mapped_address_size(DWORD(data + 0x08) - DWORD(data + 0x04) + 1);
Packit Service e18529
			}
Packit Service 622062
			printf("\n");
Packit Service e18529
			if (!(opt.flags & FLAG_QUIET))
Packit Service e18529
			{
Packit Service 622062
				printf("\tPhysical Device Handle: 0x%04X\n",
Packit Service e18529
					WORD(data + 0x0C));
Packit Service 622062
				printf("\tMemory Array Mapped Address Handle: 0x%04X\n",
Packit Service e18529
					WORD(data + 0x0E));
Packit Service e18529
			}
Packit Service 622062
			printf("\tPartition Row Position:");
Packit Service e18529
			dmi_mapped_address_row_position(data[0x10]);
Packit Service 622062
			printf("\n");
Packit Service 622062
			dmi_mapped_address_interleave_position(data[0x11], "\t");
Packit Service 622062
			dmi_mapped_address_interleaved_data_depth(data[0x12], "\t");
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 21: /* 7.22 Built-in Pointing Device */
Packit Service 622062
			printf("Built-in Pointing Device\n");
Packit Service e18529
			if (h->length < 0x07) break;
Packit Service 622062
			printf("\tType: %s\n",
Packit Service e18529
				dmi_pointing_device_type(data[0x04]));
Packit Service 622062
			printf("\tInterface: %s\n",
Packit Service e18529
				dmi_pointing_device_interface(data[0x05]));
Packit Service 622062
			printf("\tButtons: %u\n",
Packit Service e18529
				data[0x06]);
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 22: /* 7.23 Portable Battery */
Packit Service 622062
			printf("Portable Battery\n");
Packit Service e18529
			if (h->length < 0x10) break;
Packit Service 622062
			printf("\tLocation: %s\n",
Packit Service e18529
				dmi_string(h, data[0x04]));
Packit Service 622062
			printf("\tManufacturer: %s\n",
Packit Service e18529
				dmi_string(h, data[0x05]));
Packit Service e18529
			if (data[0x06] || h->length < 0x1A)
Packit Service 622062
				printf("\tManufacture Date: %s\n",
Packit Service e18529
					dmi_string(h, data[0x06]));
Packit Service e18529
			if (data[0x07] || h->length < 0x1A)
Packit Service 622062
				printf("\tSerial Number: %s\n",
Packit Service e18529
					dmi_string(h, data[0x07]));
Packit Service 622062
			printf("\tName: %s\n",
Packit Service e18529
				dmi_string(h, data[0x08]));
Packit Service e18529
			if (data[0x09] != 0x02 || h->length < 0x1A)
Packit Service 622062
				printf("\tChemistry: %s\n",
Packit Service e18529
					dmi_battery_chemistry(data[0x09]));
Packit Service 622062
			printf("\tDesign Capacity:");
Packit Service e18529
			if (h->length < 0x16)
Packit Service e18529
				dmi_battery_capacity(WORD(data + 0x0A), 1);
Packit Service e18529
			else
Packit Service e18529
				dmi_battery_capacity(WORD(data + 0x0A), data[0x15]);
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tDesign Voltage:");
Packit Service e18529
			dmi_battery_voltage(WORD(data + 0x0C));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tSBDS Version: %s\n",
Packit Service e18529
				dmi_string(h, data[0x0E]));
Packit Service 622062
			printf("\tMaximum Error:");
Packit Service e18529
			dmi_battery_maximum_error(data[0x0F]);
Packit Service 622062
			printf("\n");
Packit Service e18529
			if (h->length < 0x1A) break;
Packit Service e18529
			if (data[0x07] == 0)
Packit Service 622062
				printf("\tSBDS Serial Number: %04X\n",
Packit Service e18529
					WORD(data + 0x10));
Packit Service e18529
			if (data[0x06] == 0)
Packit Service 622062
				printf("\tSBDS Manufacture Date: %u-%02u-%02u\n",
Packit Service e18529
					1980 + (WORD(data + 0x12) >> 9),
Packit Service e18529
					(WORD(data + 0x12) >> 5) & 0x0F,
Packit Service e18529
					WORD(data + 0x12) & 0x1F);
Packit Service e18529
			if (data[0x09] == 0x02)
Packit Service 622062
				printf("\tSBDS Chemistry: %s\n",
Packit Service e18529
					dmi_string(h, data[0x14]));
Packit Service 622062
			printf("\tOEM-specific Information: 0x%08X\n",
Packit Service e18529
				DWORD(data + 0x16));
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 23: /* 7.24 System Reset */
Packit Service 622062
			printf("System Reset\n");
Packit Service e18529
			if (h->length < 0x0D) break;
Packit Service 622062
			printf("\tStatus: %s\n",
Packit Service e18529
				data[0x04] & (1 << 0) ? "Enabled" : "Disabled");
Packit Service 622062
			printf("\tWatchdog Timer: %s\n",
Packit Service e18529
				data[0x04] & (1 << 5) ? "Present" : "Not Present");
Packit Service e18529
			if (!(data[0x04] & (1 << 5)))
Packit Service e18529
				break;
Packit Service 622062
			printf("\tBoot Option: %s\n",
Packit Service e18529
				dmi_system_reset_boot_option((data[0x04] >> 1) & 0x3));
Packit Service 622062
			printf("\tBoot Option On Limit: %s\n",
Packit Service e18529
				dmi_system_reset_boot_option((data[0x04] >> 3) & 0x3));
Packit Service 622062
			printf("\tReset Count:");
Packit Service 622062
			dmi_system_reset_count(WORD(data + 0x05));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tReset Limit:");
Packit Service 622062
			dmi_system_reset_count(WORD(data + 0x07));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tTimer Interval:");
Packit Service 622062
			dmi_system_reset_timer(WORD(data + 0x09));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tTimeout:");
Packit Service 622062
			dmi_system_reset_timer(WORD(data + 0x0B));
Packit Service 622062
			printf("\n");
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 24: /* 7.25 Hardware Security */
Packit Service 622062
			printf("Hardware Security\n");
Packit Service e18529
			if (h->length < 0x05) break;
Packit Service 622062
			printf("\tPower-On Password Status: %s\n",
Packit Service e18529
				dmi_hardware_security_status(data[0x04] >> 6));
Packit Service 622062
			printf("\tKeyboard Password Status: %s\n",
Packit Service e18529
				dmi_hardware_security_status((data[0x04] >> 4) & 0x3));
Packit Service 622062
			printf("\tAdministrator Password Status: %s\n",
Packit Service e18529
				dmi_hardware_security_status((data[0x04] >> 2) & 0x3));
Packit Service 622062
			printf("\tFront Panel Reset Status: %s\n",
Packit Service e18529
				dmi_hardware_security_status(data[0x04] & 0x3));
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 25: /* 7.26 System Power Controls */
Packit Service 622062
			printf("\tSystem Power Controls\n");
Packit Service e18529
			if (h->length < 0x09) break;
Packit Service 622062
			printf("\tNext Scheduled Power-on:");
Packit Service e18529
			dmi_power_controls_power_on(data + 0x04);
Packit Service 622062
			printf("\n");
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 26: /* 7.27 Voltage Probe */
Packit Service 622062
			printf("Voltage Probe\n");
Packit Service e18529
			if (h->length < 0x14) break;
Packit Service 622062
			printf("\tDescription: %s\n",
Packit Service e18529
				dmi_string(h, data[0x04]));
Packit Service 622062
			printf("\tLocation: %s\n",
Packit Service e18529
				dmi_voltage_probe_location(data[0x05] & 0x1f));
Packit Service 622062
			printf("\tStatus: %s\n",
Packit Service e18529
				dmi_probe_status(data[0x05] >> 5));
Packit Service 622062
			printf("\tMaximum Value:");
Packit Service 622062
			dmi_voltage_probe_value(WORD(data + 0x06));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tMinimum Value:");
Packit Service 622062
			dmi_voltage_probe_value(WORD(data + 0x08));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tResolution:");
Packit Service e18529
			dmi_voltage_probe_resolution(WORD(data + 0x0A));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tTolerance:");
Packit Service 622062
			dmi_voltage_probe_value(WORD(data + 0x0C));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tAccuracy:");
Packit Service e18529
			dmi_probe_accuracy(WORD(data + 0x0E));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tOEM-specific Information: 0x%08X\n",
Packit Service e18529
				DWORD(data + 0x10));
Packit Service e18529
			if (h->length < 0x16) break;
Packit Service 622062
			printf("\tNominal Value:");
Packit Service 622062
			dmi_voltage_probe_value(WORD(data + 0x14));
Packit Service 622062
			printf("\n");
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 27: /* 7.28 Cooling Device */
Packit Service 622062
			printf("Cooling Device\n");
Packit Service e18529
			if (h->length < 0x0C) break;
Packit Service e18529
			if (!(opt.flags & FLAG_QUIET) && WORD(data + 0x04) != 0xFFFF)
Packit Service 622062
				printf("\tTemperature Probe Handle: 0x%04X\n",
Packit Service e18529
					WORD(data + 0x04));
Packit Service 622062
			printf("\tType: %s\n",
Packit Service e18529
				dmi_cooling_device_type(data[0x06] & 0x1f));
Packit Service 622062
			printf("\tStatus: %s\n",
Packit Service e18529
				dmi_probe_status(data[0x06] >> 5));
Packit Service e18529
			if (data[0x07] != 0x00)
Packit Service 622062
				printf("\tCooling Unit Group: %u\n",
Packit Service e18529
					data[0x07]);
Packit Service 622062
			printf("\tOEM-specific Information: 0x%08X\n",
Packit Service e18529
				DWORD(data + 0x08));
Packit Service e18529
			if (h->length < 0x0E) break;
Packit Service 622062
			printf("\tNominal Speed:");
Packit Service e18529
			dmi_cooling_device_speed(WORD(data + 0x0C));
Packit Service 622062
			printf("\n");
Packit Service e18529
			if (h->length < 0x0F) break;
Packit Service 622062
			printf("\tDescription: %s\n", dmi_string(h, data[0x0E]));
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 28: /* 7.29 Temperature Probe */
Packit Service 622062
			printf("Temperature Probe\n");
Packit Service e18529
			if (h->length < 0x14) break;
Packit Service 622062
			printf("\tDescription: %s\n",
Packit Service e18529
				dmi_string(h, data[0x04]));
Packit Service 622062
			printf("\tLocation: %s\n",
Packit Service e18529
				dmi_temperature_probe_location(data[0x05] & 0x1F));
Packit Service 622062
			printf("\tStatus: %s\n",
Packit Service e18529
				dmi_probe_status(data[0x05] >> 5));
Packit Service 622062
			printf("\tMaximum Value:");
Packit Service 622062
			dmi_temperature_probe_value(WORD(data + 0x06));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tMinimum Value:");
Packit Service 622062
			dmi_temperature_probe_value(WORD(data + 0x08));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tResolution:");
Packit Service e18529
			dmi_temperature_probe_resolution(WORD(data + 0x0A));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tTolerance:");
Packit Service 622062
			dmi_temperature_probe_value(WORD(data + 0x0C));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tAccuracy:");
Packit Service e18529
			dmi_probe_accuracy(WORD(data + 0x0E));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tOEM-specific Information: 0x%08X\n",
Packit Service e18529
				DWORD(data + 0x10));
Packit Service e18529
			if (h->length < 0x16) break;
Packit Service 622062
			printf("\tNominal Value:");
Packit Service 622062
			dmi_temperature_probe_value(WORD(data + 0x14));
Packit Service 622062
			printf("\n");
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 29: /* 7.30 Electrical Current Probe */
Packit Service 622062
			printf("Electrical Current Probe\n");
Packit Service e18529
			if (h->length < 0x14) break;
Packit Service 622062
			printf("\tDescription: %s\n",
Packit Service e18529
				dmi_string(h, data[0x04]));
Packit Service 622062
			printf("\tLocation: %s\n",
Packit Service e18529
				dmi_voltage_probe_location(data[5] & 0x1F));
Packit Service 622062
			printf("\tStatus: %s\n",
Packit Service e18529
				dmi_probe_status(data[0x05] >> 5));
Packit Service 622062
			printf("\tMaximum Value:");
Packit Service 622062
			dmi_current_probe_value(WORD(data + 0x06));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tMinimum Value:");
Packit Service 622062
			dmi_current_probe_value(WORD(data + 0x08));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tResolution:");
Packit Service e18529
			dmi_current_probe_resolution(WORD(data + 0x0A));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tTolerance:");
Packit Service 622062
			dmi_current_probe_value(WORD(data + 0x0C));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tAccuracy:");
Packit Service e18529
			dmi_probe_accuracy(WORD(data + 0x0E));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tOEM-specific Information: 0x%08X\n",
Packit Service e18529
				DWORD(data + 0x10));
Packit Service e18529
			if (h->length < 0x16) break;
Packit Service 622062
			printf("\tNominal Value:");
Packit Service 622062
			dmi_current_probe_value(WORD(data + 0x14));
Packit Service 622062
			printf("\n");
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 30: /* 7.31 Out-of-band Remote Access */
Packit Service 622062
			printf("Out-of-band Remote Access\n");
Packit Service e18529
			if (h->length < 0x06) break;
Packit Service 622062
			printf("\tManufacturer Name: %s\n",
Packit Service e18529
				dmi_string(h, data[0x04]));
Packit Service 622062
			printf("\tInbound Connection: %s\n",
Packit Service e18529
				data[0x05] & (1 << 0) ? "Enabled" : "Disabled");
Packit Service 622062
			printf("\tOutbound Connection: %s\n",
Packit Service e18529
				data[0x05] & (1 << 1) ? "Enabled" : "Disabled");
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 31: /* 7.32 Boot Integrity Services Entry Point */
Packit Service 622062
			printf("Boot Integrity Services Entry Point\n");
Packit Service e18529
			if (h->length < 0x1C) break;
Packit Service 622062
			printf("\tChecksum: %s\n",
Packit Service e18529
				checksum(data, h->length) ? "OK" : "Invalid");
Packit Service 622062
			printf("\t16-bit Entry Point Address: %04X:%04X\n",
Packit Service e18529
				DWORD(data + 0x08) >> 16,
Packit Service e18529
				DWORD(data + 0x08) & 0xFFFF);
Packit Service 622062
			printf("\t32-bit Entry Point Address: 0x%08X\n",
Packit Service e18529
				DWORD(data + 0x0C));
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 32: /* 7.33 System Boot Information */
Packit Service 622062
			printf("System Boot Information\n");
Packit Service e18529
			if (h->length < 0x0B) break;
Packit Service 622062
			printf("\tStatus: %s\n",
Packit Service e18529
				dmi_system_boot_status(data[0x0A]));
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 33: /* 7.34 64-bit Memory Error Information */
Packit Service 622062
			printf("64-bit Memory Error Information\n");
Packit Service 0ae466
			if (h->length < 0x1F) break;
Packit Service 622062
			printf("\tType: %s\n",
Packit Service e18529
				dmi_memory_error_type(data[0x04]));
Packit Service 622062
			printf("\tGranularity: %s\n",
Packit Service e18529
				dmi_memory_error_granularity(data[0x05]));
Packit Service 622062
			printf("\tOperation: %s\n",
Packit Service e18529
				dmi_memory_error_operation(data[0x06]));
Packit Service 622062
			printf("\tVendor Syndrome:");
Packit Service e18529
			dmi_memory_error_syndrome(DWORD(data + 0x07));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tMemory Array Address:");
Packit Service 622062
			dmi_64bit_memory_error_address(QWORD(data + 0x0B));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tDevice Address:");
Packit Service 622062
			dmi_64bit_memory_error_address(QWORD(data + 0x13));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tResolution:");
Packit Service 622062
			dmi_32bit_memory_error_address(DWORD(data + 0x1B));
Packit Service 622062
			printf("\n");
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 34: /* 7.35 Management Device */
Packit Service 622062
			printf("Management Device\n");
Packit Service e18529
			if (h->length < 0x0B) break;
Packit Service 622062
			printf("\tDescription: %s\n",
Packit Service e18529
				dmi_string(h, data[0x04]));
Packit Service 622062
			printf("\tType: %s\n",
Packit Service e18529
				dmi_management_device_type(data[0x05]));
Packit Service 622062
			printf("\tAddress: 0x%08X\n",
Packit Service e18529
				DWORD(data + 0x06));
Packit Service 622062
			printf("\tAddress Type: %s\n",
Packit Service e18529
				dmi_management_device_address_type(data[0x0A]));
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 35: /* 7.36 Management Device Component */
Packit Service 622062
			printf("Management Device Component\n");
Packit Service e18529
			if (h->length < 0x0B) break;
Packit Service 622062
			printf("\tDescription: %s\n",
Packit Service e18529
				dmi_string(h, data[0x04]));
Packit Service e18529
			if (!(opt.flags & FLAG_QUIET))
Packit Service e18529
			{
Packit Service 622062
				printf("\tManagement Device Handle: 0x%04X\n",
Packit Service e18529
					WORD(data + 0x05));
Packit Service 622062
				printf("\tComponent Handle: 0x%04X\n",
Packit Service e18529
					WORD(data + 0x07));
Packit Service e18529
				if (WORD(data + 0x09) != 0xFFFF)
Packit Service 622062
					printf("\tThreshold Handle: 0x%04X\n",
Packit Service 622062
					WORD(data + 0x09));
Packit Service e18529
			}
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 36: /* 7.37 Management Device Threshold Data */
Packit Service 622062
			printf("Management Device Threshold Data\n");
Packit Service e18529
			if (h->length < 0x10) break;
Packit Service e18529
			if (WORD(data + 0x04) != 0x8000)
Packit Service 622062
				printf("\tLower Non-critical Threshold: %d\n",
Packit Service e18529
					(i16)WORD(data + 0x04));
Packit Service e18529
			if (WORD(data + 0x06) != 0x8000)
Packit Service 622062
				printf("\tUpper Non-critical Threshold: %d\n",
Packit Service e18529
					(i16)WORD(data + 0x06));
Packit Service e18529
			if (WORD(data + 0x08) != 0x8000)
Packit Service 622062
				printf("\tLower Critical Threshold: %d\n",
Packit Service e18529
					(i16)WORD(data + 0x08));
Packit Service e18529
			if (WORD(data + 0x0A) != 0x8000)
Packit Service 622062
				printf("\tUpper Critical Threshold: %d\n",
Packit Service e18529
					(i16)WORD(data + 0x0A));
Packit Service e18529
			if (WORD(data + 0x0C) != 0x8000)
Packit Service 622062
				printf("\tLower Non-recoverable Threshold: %d\n",
Packit Service e18529
					(i16)WORD(data + 0x0C));
Packit Service e18529
			if (WORD(data + 0x0E) != 0x8000)
Packit Service 622062
				printf("\tUpper Non-recoverable Threshold: %d\n",
Packit Service e18529
					(i16)WORD(data + 0x0E));
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 37: /* 7.38 Memory Channel */
Packit Service 622062
			printf("Memory Channel\n");
Packit Service e18529
			if (h->length < 0x07) break;
Packit Service 622062
			printf("\tType: %s\n",
Packit Service e18529
				dmi_memory_channel_type(data[0x04]));
Packit Service 622062
			printf("\tMaximal Load: %u\n",
Packit Service e18529
				data[0x05]);
Packit Service 622062
			printf("\tDevices: %u\n",
Packit Service e18529
				data[0x06]);
Packit Service e18529
			if (h->length < 0x07 + 3 * data[0x06]) break;
Packit Service 622062
			dmi_memory_channel_devices(data[0x06], data + 0x07, "\t");
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 38: /* 7.39 IPMI Device Information */
Packit Service e18529
			/*
Packit Service e18529
			 * We use the word "Version" instead of "Revision", conforming to
Packit Service e18529
			 * the IPMI specification.
Packit Service e18529
			 */
Packit Service 622062
			printf("IPMI Device Information\n");
Packit Service e18529
			if (h->length < 0x10) break;
Packit Service 622062
			printf("\tInterface Type: %s\n",
Packit Service e18529
				dmi_ipmi_interface_type(data[0x04]));
Packit Service 622062
			printf("\tSpecification Version: %u.%u\n",
Packit Service e18529
				data[0x05] >> 4, data[0x05] & 0x0F);
Packit Service 622062
			printf("\tI2C Slave Address: 0x%02x\n",
Packit Service e18529
				data[0x06] >> 1);
Packit Service e18529
			if (data[0x07] != 0xFF)
Packit Service 622062
				printf("\tNV Storage Device Address: %u\n",
Packit Service e18529
					data[0x07]);
Packit Service e18529
			else
Packit Service 622062
				printf("\tNV Storage Device: Not Present\n");
Packit Service 622062
			printf("\tBase Address: ");
Packit Service e18529
			dmi_ipmi_base_address(data[0x04], data + 0x08,
Packit Service e18529
				h->length < 0x11 ? 0 : (data[0x10] >> 4) & 1);
Packit Service 622062
			printf("\n");
Packit Service e18529
			if (h->length < 0x12) break;
Packit Service e18529
			if (data[0x04] != 0x04)
Packit Service e18529
			{
Packit Service 622062
				printf("\tRegister Spacing: %s\n",
Packit Service e18529
					dmi_ipmi_register_spacing(data[0x10] >> 6));
Packit Service e18529
				if (data[0x10] & (1 << 3))
Packit Service e18529
				{
Packit Service 622062
					printf("\tInterrupt Polarity: %s\n",
Packit Service e18529
						data[0x10] & (1 << 1) ? "Active High" : "Active Low");
Packit Service 622062
					printf("\tInterrupt Trigger Mode: %s\n",
Packit Service e18529
						data[0x10] & (1 << 0) ? "Level" : "Edge");
Packit Service e18529
				}
Packit Service e18529
			}
Packit Service e18529
			if (data[0x11] != 0x00)
Packit Service e18529
			{
Packit Service 622062
				printf("\tInterrupt Number: %u\n",
Packit Service e18529
					data[0x11]);
Packit Service e18529
			}
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 39: /* 7.40 System Power Supply */
Packit Service 622062
			printf("System Power Supply\n");
Packit Service e18529
			if (h->length < 0x10) break;
Packit Service e18529
			if (data[0x04] != 0x00)
Packit Service 622062
				printf("\tPower Unit Group: %u\n",
Packit Service e18529
					data[0x04]);
Packit Service 622062
			printf("\tLocation: %s\n",
Packit Service e18529
				dmi_string(h, data[0x05]));
Packit Service 622062
			printf("\tName: %s\n",
Packit Service e18529
				dmi_string(h, data[0x06]));
Packit Service 622062
			printf("\tManufacturer: %s\n",
Packit Service e18529
				dmi_string(h, data[0x07]));
Packit Service 622062
			printf("\tSerial Number: %s\n",
Packit Service e18529
				dmi_string(h, data[0x08]));
Packit Service 622062
			printf("\tAsset Tag: %s\n",
Packit Service e18529
				dmi_string(h, data[0x09]));
Packit Service 622062
			printf("\tModel Part Number: %s\n",
Packit Service e18529
				dmi_string(h, data[0x0A]));
Packit Service 622062
			printf("\tRevision: %s\n",
Packit Service e18529
				dmi_string(h, data[0x0B]));
Packit Service 622062
			printf("\tMax Power Capacity:");
Packit Service e18529
			dmi_power_supply_power(WORD(data + 0x0C));
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tStatus:");
Packit Service e18529
			if (WORD(data + 0x0E) & (1 << 1))
Packit Service 622062
				printf(" Present, %s",
Packit Service e18529
					dmi_power_supply_status((WORD(data + 0x0E) >> 7) & 0x07));
Packit Service e18529
			else
Packit Service 622062
				printf(" Not Present");
Packit Service 622062
			printf("\n");
Packit Service 622062
			printf("\tType: %s\n",
Packit Service e18529
				dmi_power_supply_type((WORD(data + 0x0E) >> 10) & 0x0F));
Packit Service 622062
			printf("\tInput Voltage Range Switching: %s\n",
Packit Service e18529
				dmi_power_supply_range_switching((WORD(data + 0x0E) >> 3) & 0x0F));
Packit Service 622062
			printf("\tPlugged: %s\n",
Packit Service e18529
				WORD(data + 0x0E) & (1 << 2) ? "No" : "Yes");
Packit Service 622062
			printf("\tHot Replaceable: %s\n",
Packit Service e18529
				WORD(data + 0x0E) & (1 << 0) ? "Yes" : "No");
Packit Service e18529
			if (h->length < 0x16) break;
Packit Service e18529
			if (!(opt.flags & FLAG_QUIET))
Packit Service e18529
			{
Packit Service e18529
				if (WORD(data + 0x10) != 0xFFFF)
Packit Service 622062
					printf("\tInput Voltage Probe Handle: 0x%04X\n",
Packit Service e18529
						WORD(data + 0x10));
Packit Service e18529
				if (WORD(data + 0x12) != 0xFFFF)
Packit Service 622062
					printf("\tCooling Device Handle: 0x%04X\n",
Packit Service e18529
						WORD(data + 0x12));
Packit Service e18529
				if (WORD(data + 0x14) != 0xFFFF)
Packit Service 622062
					printf("\tInput Current Probe Handle: 0x%04X\n",
Packit Service e18529
						WORD(data + 0x14));
Packit Service e18529
			}
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 40: /* 7.41 Additional Information */
Packit Service e18529
			if (h->length < 0x0B) break;
Packit Service e18529
			if (opt.flags & FLAG_QUIET)
Packit Service e18529
				return;
Packit Service 622062
			dmi_additional_info(h, "");
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 41: /* 7.42 Onboard Device Extended Information */
Packit Service 622062
			printf("Onboard Device\n");
Packit Service e18529
			if (h->length < 0x0B) break;
Packit Service 622062
			printf("\tReference Designation: %s\n", dmi_string(h, data[0x04]));
Packit Service 622062
			printf("\tType: %s\n",
Packit Service e18529
				dmi_on_board_devices_type(data[0x05] & 0x7F));
Packit Service 622062
			printf("\tStatus: %s\n",
Packit Service e18529
				data[0x05] & 0x80 ? "Enabled" : "Disabled");
Packit Service 622062
			printf("\tType Instance: %u\n", data[0x06]);
Packit Service 622062
			dmi_slot_segment_bus_func(WORD(data + 0x07), data[0x09], data[0x0A], "\t");
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 42: /* 7.43 Management Controller Host Interface */
Packit Service 622062
			printf("Management Controller Host Interface\n");
Packit Service e18529
			if (ver < 0x0302)
Packit Service e18529
			{
Packit Service e18529
				if (h->length < 0x05) break;
Packit Service 622062
				printf("\tInterface Type: %s\n",
Packit Service e18529
					dmi_management_controller_host_type(data[0x04]));
Packit Service e18529
				/*
Packit Service e18529
				 * There you have a type-dependent, variable-length
Packit Service e18529
				 * part in the middle of the structure, with no
Packit Service e18529
				 * length specifier, so no easy way to decode the
Packit Service e18529
				 * common, final part of the structure. What a pity.
Packit Service e18529
				 */
Packit Service e18529
				if (h->length < 0x09) break;
Packit Service e18529
				if (data[0x04] == 0xF0)		/* OEM */
Packit Service e18529
				{
Packit Service 622062
					printf("\tVendor ID: 0x%02X%02X%02X%02X\n",
Packit Service e18529
						data[0x05], data[0x06], data[0x07],
Packit Service e18529
						data[0x08]);
Packit Service e18529
				}
Packit Service e18529
			}
Packit Service e18529
			else
Packit Service 622062
				dmi_parse_controller_structure(h, "\t");
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 43: /* 7.44 TPM Device */
Packit Service 622062
			printf("TPM Device\n");
Packit Service e18529
			if (h->length < 0x1B) break;
Packit Service 622062
			printf("\tVendor ID:");
Packit Service e18529
			dmi_tpm_vendor_id(data + 0x04);
Packit Service 622062
			printf("\n");
Packit Service ded0d2
			printf("\tSpecification Version: %d.%d\n", data[0x08], data[0x09]);
Packit Service e18529
			switch (data[0x08])
Packit Service e18529
			{
Packit Service e18529
				case 0x01:
Packit Service e18529
					/*
Packit Service e18529
					 * We skip the first 2 bytes, which are
Packit Service e18529
					 * redundant with the above, and uncoded
Packit Service e18529
					 * in a silly way.
Packit Service e18529
					 */
Packit Service 622062
					printf("\tFirmware Revision: %u.%u\n",
Packit Service e18529
						data[0x0C], data[0x0D]);
Packit Service e18529
					break;
Packit Service e18529
				case 0x02:
Packit Service 622062
					printf("\tFirmware Revision: %u.%u\n",
Packit Service e18529
						DWORD(data + 0x0A) >> 16,
Packit Service e18529
						DWORD(data + 0x0A) & 0xFFFF);
Packit Service e18529
					/*
Packit Service e18529
					 * We skip the next 4 bytes, as their
Packit Service e18529
					 * format is not standardized and their
Packit Service e18529
					 * usefulness seems limited anyway.
Packit Service e18529
					 */
Packit Service e18529
					break;
Packit Service e18529
			}
Packit Service ded0d2
			printf("\tDescription: %s\n", dmi_string(h, data[0x12]));
Packit Service 622062
			printf("\tCharacteristics:\n");
Packit Service 622062
			dmi_tpm_characteristics(QWORD(data + 0x13), "\t\t");
Packit Service e18529
			if (h->length < 0x1F) break;
Packit Service 622062
			printf("\tOEM-specific Information: 0x%08X\n",
Packit Service e18529
				DWORD(data + 0x1B));
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 126: /* 7.44 Inactive */
Packit Service 622062
			printf("Inactive\n");
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		case 127: /* 7.45 End Of Table */
Packit Service 622062
			printf("End Of Table\n");
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		default:
Packit Service e18529
			if (dmi_decode_oem(h))
Packit Service e18529
				break;
Packit Service e18529
			if (opt.flags & FLAG_QUIET)
Packit Service e18529
				return;
Packit Service 622062
			printf("%s Type\n",
Packit Service e18529
				h->type >= 128 ? "OEM-specific" : "Unknown");
Packit Service 622062
			dmi_dump(h, "\t");
Packit Service e18529
	}
Packit Service 622062
	printf("\n");
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static void to_dmi_header(struct dmi_header *h, u8 *data)
Packit Service e18529
{
Packit Service e18529
	h->type = data[0];
Packit Service e18529
	h->length = data[1];
Packit Service e18529
	h->handle = WORD(data + 2);
Packit Service e18529
	h->data = data;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static void dmi_table_string(const struct dmi_header *h, const u8 *data, u16 ver)
Packit Service e18529
{
Packit Service e18529
	int key;
Packit Service e18529
	u8 offset = opt.string->offset;
Packit Service e18529
Packit Service e18529
	if (opt.string->type == 11) /* OEM strings */
Packit Service e18529
	{
Packit Service e18529
		if (h->length < 5 || offset > data[4])
Packit Service e18529
		{
Packit Service e18529
			fprintf(stderr, "No OEM string number %u\n", offset);
Packit Service e18529
			return;
Packit Service e18529
		}
Packit Service e18529
Packit Service e18529
		if (offset)
Packit Service e18529
			printf("%s\n", dmi_string(h, offset));
Packit Service e18529
		else
Packit Service e18529
			printf("%u\n", data[4]);	/* count */
Packit Service e18529
		return;
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	if (offset >= h->length)
Packit Service e18529
		return;
Packit Service e18529
Packit Service e18529
	key = (opt.string->type << 8) | offset;
Packit Service e18529
	switch (key)
Packit Service e18529
	{
Packit Service af3361
		case 0x015: /* -s bios-revision */
Packit Service af3361
			if (data[key - 1] != 0xFF && data[key] != 0xFF)
Packit Service af3361
				printf("%u.%u\n", data[key - 1], data[key]);
Packit Service af3361
			break;
Packit Service 9d83ba
		case 0x017: /* -s firmware-revision */
Packit Service 9d83ba
			if (data[key - 1] != 0xFF && data[key] != 0xFF)
Packit Service 9d83ba
				printf("%u.%u\n", data[key - 1], data[key]);
Packit Service 9d83ba
			break;
Packit Service e18529
		case 0x108:
Packit Service 622062
			dmi_system_uuid(data + offset, ver);
Packit Service 622062
			printf("\n");
Packit Service e18529
			break;
Packit Service e18529
		case 0x305:
Packit Service e18529
			printf("%s\n", dmi_chassis_type(data[offset]));
Packit Service e18529
			break;
Packit Service e18529
		case 0x406:
Packit Service e18529
			printf("%s\n", dmi_processor_family(h, ver));
Packit Service e18529
			break;
Packit Service e18529
		case 0x416:
Packit Service 622062
			dmi_processor_frequency(data + offset);
Packit Service 622062
			printf("\n");
Packit Service e18529
			break;
Packit Service e18529
		default:
Packit Service e18529
			printf("%s\n", dmi_string(h, data[offset]));
Packit Service e18529
	}
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static void dmi_table_dump(const u8 *buf, u32 len)
Packit Service e18529
{
Packit Service e18529
	if (!(opt.flags & FLAG_QUIET))
Packit Service 622062
		printf("# Writing %d bytes to %s.\n", len, opt.dumpfile);
Packit Service e18529
	write_dump(32, len, buf, opt.dumpfile, 0);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static void dmi_table_decode(u8 *buf, u32 len, u16 num, u16 ver, u32 flags)
Packit Service e18529
{
Packit Service e18529
	u8 *data;
Packit Service e18529
	int i = 0;
Packit Service e18529
Packit Service e18529
	data = buf;
Packit Service e18529
	while ((i < num || !num)
Packit Service e18529
	    && data + 4 <= buf + len) /* 4 is the length of an SMBIOS structure header */
Packit Service e18529
	{
Packit Service e18529
		u8 *next;
Packit Service e18529
		struct dmi_header h;
Packit Service e18529
		int display;
Packit Service e18529
Packit Service e18529
		to_dmi_header(&h, data);
Packit Service e18529
		display = ((opt.type == NULL || opt.type[h.type])
Packit Service e18529
			&& (opt.handle == ~0U || opt.handle == h.handle)
Packit Service e18529
			&& !((opt.flags & FLAG_QUIET) && (h.type == 126 || h.type == 127))
Packit Service e18529
			&& !opt.string);
Packit Service e18529
Packit Service e18529
		/*
Packit Service e18529
		 * If a short entry is found (less than 4 bytes), not only it
Packit Service e18529
		 * is invalid, but we cannot reliably locate the next entry.
Packit Service e18529
		 * Better stop at this point, and let the user know his/her
Packit Service e18529
		 * table is broken.
Packit Service e18529
		 */
Packit Service e18529
		if (h.length < 4)
Packit Service e18529
		{
Packit Service e18529
			if (!(opt.flags & FLAG_QUIET))
Packit Service e18529
			{
Packit Service e18529
				fprintf(stderr,
Packit Service e18529
					"Invalid entry length (%u). DMI table "
Packit Service e18529
					"is broken! Stop.\n\n",
Packit Service e18529
					(unsigned int)h.length);
Packit Service e18529
				opt.flags |= FLAG_QUIET;
Packit Service e18529
			}
Packit Service e18529
			break;
Packit Service e18529
		}
Packit Service e18529
		i++;
Packit Service e18529
Packit Service e18529
		/* In quiet mode, stop decoding at end of table marker */
Packit Service e18529
		if ((opt.flags & FLAG_QUIET) && h.type == 127)
Packit Service e18529
			break;
Packit Service e18529
Packit Service e18529
		if (display
Packit Service e18529
		 && (!(opt.flags & FLAG_QUIET) || (opt.flags & FLAG_DUMP)))
Packit Service 622062
			printf("Handle 0x%04X, DMI type %d, %d bytes\n",
Packit Service 622062
				h.handle, h.type, h.length);
Packit Service e18529
Packit Service e18529
		/* Look for the next handle */
Packit Service e18529
		next = data + h.length;
Packit Service e18529
		while ((unsigned long)(next - buf + 1) < len
Packit Service e18529
		    && (next[0] != 0 || next[1] != 0))
Packit Service e18529
			next++;
Packit Service e18529
		next += 2;
Packit Service e18529
Packit Service e18529
		/* Make sure the whole structure fits in the table */
Packit Service e18529
		if ((unsigned long)(next - buf) > len)
Packit Service e18529
		{
Packit Service e18529
			if (display && !(opt.flags & FLAG_QUIET))
Packit Service 622062
				printf("\t<TRUNCATED>\n\n");
Packit Service e18529
			data = next;
Packit Service e18529
			break;
Packit Service e18529
		}
Packit Service e18529
Packit Service e18529
		/* assign vendor for vendor-specific decodes later */
Packit Service e18529
		if (h.type == 1 && h.length >= 5)
Packit Service e18529
			dmi_set_vendor(dmi_string(&h, data[0x04]));
Packit Service e18529
Packit Service e18529
		/* Fixup a common mistake */
Packit Service e18529
		if (h.type == 34)
Packit Service e18529
			dmi_fixup_type_34(&h, display);
Packit Service e18529
Packit Service e18529
		if (display)
Packit Service e18529
		{
Packit Service e18529
			if (opt.flags & FLAG_DUMP)
Packit Service e18529
			{
Packit Service 622062
				dmi_dump(&h, "\t");
Packit Service 622062
				printf("\n");
Packit Service e18529
			}
Packit Service e18529
			else
Packit Service e18529
				dmi_decode(&h, ver);
Packit Service e18529
		}
Packit Service e18529
		else if (opt.string != NULL
Packit Service e18529
		      && opt.string->type == h.type)
Packit Service e18529
			dmi_table_string(&h, data, ver);
Packit Service e18529
Packit Service e18529
		data = next;
Packit Service e18529
Packit Service e18529
		/* SMBIOS v3 requires stopping at this marker */
Packit Service e18529
		if (h.type == 127 && (flags & FLAG_STOP_AT_EOT))
Packit Service e18529
			break;
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	/*
Packit Service e18529
	 * SMBIOS v3 64-bit entry points do not announce a structures count,
Packit Service e18529
	 * and only indicate a maximum size for the table.
Packit Service e18529
	 */
Packit Service e18529
	if (!(opt.flags & FLAG_QUIET))
Packit Service e18529
	{
Packit Service e18529
		if (num && i != num)
Packit Service e18529
			fprintf(stderr, "Wrong DMI structures count: %d announced, "
Packit Service e18529
				"only %d decoded.\n", num, i);
Packit Service e18529
		if ((unsigned long)(data - buf) > len
Packit Service e18529
		 || (num && (unsigned long)(data - buf) < len))
Packit Service e18529
			fprintf(stderr, "Wrong DMI structures length: %u bytes "
Packit Service e18529
				"announced, structures occupy %lu bytes.\n",
Packit Service e18529
				len, (unsigned long)(data - buf));
Packit Service e18529
	}
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static void dmi_table(off_t base, u32 len, u16 num, u32 ver, const char *devmem,
Packit Service e18529
		      u32 flags)
Packit Service e18529
{
Packit Service e18529
	u8 *buf;
Packit Service e18529
Packit Service e18529
	if (ver > SUPPORTED_SMBIOS_VER && !(opt.flags & FLAG_QUIET))
Packit Service e18529
	{
Packit Service 622062
		printf("# SMBIOS implementations newer than version %u.%u.%u are not\n"
Packit Service 622062
		       "# fully supported by this version of dmidecode.\n",
Packit Service 622062
		       SUPPORTED_SMBIOS_VER >> 16,
Packit Service 622062
		       (SUPPORTED_SMBIOS_VER >> 8) & 0xFF,
Packit Service 622062
		       SUPPORTED_SMBIOS_VER & 0xFF);
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	if (!(opt.flags & FLAG_QUIET))
Packit Service e18529
	{
Packit Service e18529
		if (opt.type == NULL)
Packit Service e18529
		{
Packit Service e18529
			if (num)
Packit Service 622062
				printf("%u structures occupying %u bytes.\n",
Packit Service 622062
				       num, len);
Packit Service e18529
			if (!(opt.flags & FLAG_FROM_DUMP))
Packit Service 622062
				printf("Table at 0x%08llX.\n",
Packit Service 622062
				       (unsigned long long)base);
Packit Service e18529
		}
Packit Service 622062
		printf("\n");
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	if ((flags & FLAG_NO_FILE_OFFSET) || (opt.flags & FLAG_FROM_DUMP))
Packit Service e18529
	{
Packit Service e18529
		/*
Packit Service e18529
		 * When reading from sysfs or from a dump file, the file may be
Packit Service e18529
		 * shorter than announced. For SMBIOS v3 this is expcted, as we
Packit Service e18529
		 * only know the maximum table size, not the actual table size.
Packit Service e18529
		 * For older implementations (and for SMBIOS v3 too), this
Packit Service e18529
		 * would be the result of the kernel truncating the table on
Packit Service e18529
		 * parse error.
Packit Service e18529
		 */
Packit Service e18529
		size_t size = len;
Packit Service e18529
		buf = read_file(flags & FLAG_NO_FILE_OFFSET ? 0 : base,
Packit Service e18529
			&size, devmem);
Packit Service e18529
		if (!(opt.flags & FLAG_QUIET) && num && size != (size_t)len)
Packit Service e18529
		{
Packit Service e18529
			fprintf(stderr, "Wrong DMI structures length: %u bytes "
Packit Service e18529
				"announced, only %lu bytes available.\n",
Packit Service e18529
				len, (unsigned long)size);
Packit Service e18529
		}
Packit Service e18529
		len = size;
Packit Service e18529
	}
Packit Service e18529
	else
Packit Service e18529
		buf = mem_chunk(base, len, devmem);
Packit Service e18529
Packit Service e18529
	if (buf == NULL)
Packit Service e18529
	{
Packit Service e18529
		fprintf(stderr, "Failed to read table, sorry.\n");
Packit Service e18529
#ifndef USE_MMAP
Packit Service e18529
		if (!(flags & FLAG_NO_FILE_OFFSET))
Packit Service e18529
			fprintf(stderr,
Packit Service e18529
				"Try compiling dmidecode with -DUSE_MMAP.\n");
Packit Service e18529
#endif
Packit Service e18529
		return;
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	if (opt.flags & FLAG_DUMP_BIN)
Packit Service e18529
		dmi_table_dump(buf, len);
Packit Service e18529
	else
Packit Service e18529
		dmi_table_decode(buf, len, num, ver >> 8, flags);
Packit Service e18529
Packit Service e18529
	free(buf);
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * Build a crafted entry point with table address hard-coded to 32,
Packit Service e18529
 * as this is where we will put it in the output file. We adjust the
Packit Service e18529
 * DMI checksum appropriately. The SMBIOS checksum needs no adjustment.
Packit Service e18529
 */
Packit Service e18529
static void overwrite_dmi_address(u8 *buf)
Packit Service e18529
{
Packit Service e18529
	buf[0x05] += buf[0x08] + buf[0x09] + buf[0x0A] + buf[0x0B] - 32;
Packit Service e18529
	buf[0x08] = 32;
Packit Service e18529
	buf[0x09] = 0;
Packit Service e18529
	buf[0x0A] = 0;
Packit Service e18529
	buf[0x0B] = 0;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/* Same thing for SMBIOS3 entry points */
Packit Service e18529
static void overwrite_smbios3_address(u8 *buf)
Packit Service e18529
{
Packit Service e18529
	buf[0x05] += buf[0x10] + buf[0x11] + buf[0x12] + buf[0x13]
Packit Service e18529
		   + buf[0x14] + buf[0x15] + buf[0x16] + buf[0x17] - 32;
Packit Service e18529
	buf[0x10] = 32;
Packit Service e18529
	buf[0x11] = 0;
Packit Service e18529
	buf[0x12] = 0;
Packit Service e18529
	buf[0x13] = 0;
Packit Service e18529
	buf[0x14] = 0;
Packit Service e18529
	buf[0x15] = 0;
Packit Service e18529
	buf[0x16] = 0;
Packit Service e18529
	buf[0x17] = 0;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static int smbios3_decode(u8 *buf, const char *devmem, u32 flags)
Packit Service e18529
{
Packit Service e18529
	u32 ver;
Packit Service e18529
	u64 offset;
Packit Service e18529
Packit Service e18529
	/* Don't let checksum run beyond the buffer */
Packit Service e18529
	if (buf[0x06] > 0x20)
Packit Service e18529
	{
Packit Service e18529
		fprintf(stderr,
Packit Service e18529
			"Entry point length too large (%u bytes, expected %u).\n",
Packit Service e18529
			(unsigned int)buf[0x06], 0x18U);
Packit Service e18529
		return 0;
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	if (!checksum(buf, buf[0x06]))
Packit Service e18529
		return 0;
Packit Service e18529
Packit Service e18529
	ver = (buf[0x07] << 16) + (buf[0x08] << 8) + buf[0x09];
Packit Service e18529
	if (!(opt.flags & FLAG_QUIET))
Packit Service 622062
		printf("SMBIOS %u.%u.%u present.\n",
Packit Service 622062
		       buf[0x07], buf[0x08], buf[0x09]);
Packit Service e18529
Packit Service e18529
	offset = QWORD(buf + 0x10);
Packit Service e18529
	if (!(flags & FLAG_NO_FILE_OFFSET) && offset.h && sizeof(off_t) < 8)
Packit Service e18529
	{
Packit Service e18529
		fprintf(stderr, "64-bit addresses not supported, sorry.\n");
Packit Service e18529
		return 0;
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	dmi_table(((off_t)offset.h << 32) | offset.l,
Packit Service e18529
		  DWORD(buf + 0x0C), 0, ver, devmem, flags | FLAG_STOP_AT_EOT);
Packit Service e18529
Packit Service e18529
	if (opt.flags & FLAG_DUMP_BIN)
Packit Service e18529
	{
Packit Service e18529
		u8 crafted[32];
Packit Service e18529
Packit Service e18529
		memcpy(crafted, buf, 32);
Packit Service e18529
		overwrite_smbios3_address(crafted);
Packit Service e18529
Packit Service e18529
		if (!(opt.flags & FLAG_QUIET))
Packit Service 622062
			printf("# Writing %d bytes to %s.\n", crafted[0x06],
Packit Service 622062
			       opt.dumpfile);
Packit Service e18529
		write_dump(0, crafted[0x06], crafted, opt.dumpfile, 1);
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	return 1;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static int smbios_decode(u8 *buf, const char *devmem, u32 flags)
Packit Service e18529
{
Packit Service e18529
	u16 ver;
Packit Service e18529
Packit Service e18529
	/* Don't let checksum run beyond the buffer */
Packit Service e18529
	if (buf[0x05] > 0x20)
Packit Service e18529
	{
Packit Service e18529
		fprintf(stderr,
Packit Service e18529
			"Entry point length too large (%u bytes, expected %u).\n",
Packit Service e18529
			(unsigned int)buf[0x05], 0x1FU);
Packit Service e18529
		return 0;
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	if (!checksum(buf, buf[0x05])
Packit Service e18529
	 || memcmp(buf + 0x10, "_DMI_", 5) != 0
Packit Service e18529
	 || !checksum(buf + 0x10, 0x0F))
Packit Service e18529
		return 0;
Packit Service e18529
Packit Service e18529
	ver = (buf[0x06] << 8) + buf[0x07];
Packit Service e18529
	/* Some BIOS report weird SMBIOS version, fix that up */
Packit Service e18529
	switch (ver)
Packit Service e18529
	{
Packit Service e18529
		case 0x021F:
Packit Service e18529
		case 0x0221:
Packit Service e18529
			if (!(opt.flags & FLAG_QUIET))
Packit Service e18529
				fprintf(stderr,
Packit Service e18529
					"SMBIOS version fixup (2.%d -> 2.%d).\n",
Packit Service e18529
					ver & 0xFF, 3);
Packit Service e18529
			ver = 0x0203;
Packit Service e18529
			break;
Packit Service e18529
		case 0x0233:
Packit Service e18529
			if (!(opt.flags & FLAG_QUIET))
Packit Service e18529
				fprintf(stderr,
Packit Service e18529
					"SMBIOS version fixup (2.%d -> 2.%d).\n",
Packit Service e18529
					51, 6);
Packit Service e18529
			ver = 0x0206;
Packit Service e18529
			break;
Packit Service e18529
	}
Packit Service e18529
	if (!(opt.flags & FLAG_QUIET))
Packit Service 622062
		printf("SMBIOS %u.%u present.\n",
Packit Service e18529
			ver >> 8, ver & 0xFF);
Packit Service e18529
Packit Service e18529
	dmi_table(DWORD(buf + 0x18), WORD(buf + 0x16), WORD(buf + 0x1C),
Packit Service e18529
		ver << 8, devmem, flags);
Packit Service e18529
Packit Service e18529
	if (opt.flags & FLAG_DUMP_BIN)
Packit Service e18529
	{
Packit Service e18529
		u8 crafted[32];
Packit Service e18529
Packit Service e18529
		memcpy(crafted, buf, 32);
Packit Service e18529
		overwrite_dmi_address(crafted + 0x10);
Packit Service e18529
Packit Service e18529
		if (!(opt.flags & FLAG_QUIET))
Packit Service 622062
			printf("# Writing %d bytes to %s.\n", crafted[0x05],
Packit Service 622062
				opt.dumpfile);
Packit Service e18529
		write_dump(0, crafted[0x05], crafted, opt.dumpfile, 1);
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	return 1;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
static int legacy_decode(u8 *buf, const char *devmem, u32 flags)
Packit Service e18529
{
Packit Service e18529
	if (!checksum(buf, 0x0F))
Packit Service e18529
		return 0;
Packit Service e18529
Packit Service e18529
	if (!(opt.flags & FLAG_QUIET))
Packit Service 622062
		printf("Legacy DMI %u.%u present.\n",
Packit Service e18529
			buf[0x0E] >> 4, buf[0x0E] & 0x0F);
Packit Service e18529
Packit Service e18529
	dmi_table(DWORD(buf + 0x08), WORD(buf + 0x06), WORD(buf + 0x0C),
Packit Service e18529
		((buf[0x0E] & 0xF0) << 12) + ((buf[0x0E] & 0x0F) << 8),
Packit Service e18529
		devmem, flags);
Packit Service e18529
Packit Service e18529
	if (opt.flags & FLAG_DUMP_BIN)
Packit Service e18529
	{
Packit Service e18529
		u8 crafted[16];
Packit Service e18529
Packit Service e18529
		memcpy(crafted, buf, 16);
Packit Service e18529
		overwrite_dmi_address(crafted);
Packit Service e18529
Packit Service e18529
		if (!(opt.flags & FLAG_QUIET))
Packit Service 622062
			printf("# Writing %d bytes to %s.\n", 0x0F,
Packit Service 622062
				opt.dumpfile);
Packit Service e18529
		write_dump(0, 0x0F, crafted, opt.dumpfile, 1);
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	return 1;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
/*
Packit Service e18529
 * Probe for EFI interface
Packit Service e18529
 */
Packit Service e18529
#define EFI_NOT_FOUND   (-1)
Packit Service e18529
#define EFI_NO_SMBIOS   (-2)
Packit Service e18529
static int address_from_efi(off_t *address)
Packit Service e18529
{
Packit Service e18529
#if defined(__linux__)
Packit Service e18529
	FILE *efi_systab;
Packit Service e18529
	const char *filename;
Packit Service e18529
	char linebuf[64];
Packit Service e18529
#elif defined(__FreeBSD__)
Packit Service e18529
	char addrstr[KENV_MVALLEN + 1];
Packit Service e18529
#endif
Packit Service e18529
	const char *eptype;
Packit Service e18529
	int ret;
Packit Service e18529
Packit Service e18529
	*address = 0; /* Prevent compiler warning */
Packit Service e18529
Packit Service e18529
#if defined(__linux__)
Packit Service e18529
	/*
Packit Service e18529
	 * Linux up to 2.6.6: /proc/efi/systab
Packit Service e18529
	 * Linux 2.6.7 and up: /sys/firmware/efi/systab
Packit Service e18529
	 */
Packit Service e18529
	if ((efi_systab = fopen(filename = "/sys/firmware/efi/systab", "r")) == NULL
Packit Service e18529
	 && (efi_systab = fopen(filename = "/proc/efi/systab", "r")) == NULL)
Packit Service e18529
	{
Packit Service e18529
		/* No EFI interface, fallback to memory scan */
Packit Service e18529
		return EFI_NOT_FOUND;
Packit Service e18529
	}
Packit Service e18529
	ret = EFI_NO_SMBIOS;
Packit Service e18529
	while ((fgets(linebuf, sizeof(linebuf) - 1, efi_systab)) != NULL)
Packit Service e18529
	{
Packit Service e18529
		char *addrp = strchr(linebuf, '=');
Packit Service e18529
		*(addrp++) = '\0';
Packit Service e18529
		if (strcmp(linebuf, "SMBIOS3") == 0
Packit Service e18529
		 || strcmp(linebuf, "SMBIOS") == 0)
Packit Service e18529
		{
Packit Service e18529
			*address = strtoull(addrp, NULL, 0);
Packit Service e18529
			eptype = linebuf;
Packit Service e18529
			ret = 0;
Packit Service e18529
			break;
Packit Service e18529
		}
Packit Service e18529
	}
Packit Service e18529
	if (fclose(efi_systab) != 0)
Packit Service e18529
		perror(filename);
Packit Service e18529
Packit Service e18529
	if (ret == EFI_NO_SMBIOS)
Packit Service e18529
		fprintf(stderr, "%s: SMBIOS entry point missing\n", filename);
Packit Service e18529
#elif defined(__FreeBSD__)
Packit Service e18529
	/*
Packit Service e18529
	 * On FreeBSD, SMBIOS anchor base address in UEFI mode is exposed
Packit Service e18529
	 * via kernel environment:
Packit Service e18529
	 * https://svnweb.freebsd.org/base?view=revision&revision=307326
Packit Service e18529
	 */
Packit Service e18529
	ret = kenv(KENV_GET, "hint.smbios.0.mem", addrstr, sizeof(addrstr));
Packit Service e18529
	if (ret == -1)
Packit Service e18529
	{
Packit Service e18529
		if (errno != ENOENT)
Packit Service e18529
			perror("kenv");
Packit Service e18529
		return EFI_NOT_FOUND;
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	*address = strtoull(addrstr, NULL, 0);
Packit Service e18529
	eptype = "SMBIOS";
Packit Service e18529
	ret = 0;
Packit Service e18529
#else
Packit Service e18529
	ret = EFI_NOT_FOUND;
Packit Service e18529
#endif
Packit Service e18529
Packit Service e18529
	if (ret == 0 && !(opt.flags & FLAG_QUIET))
Packit Service 622062
		printf("# %s entry point at 0x%08llx\n",
Packit Service 622062
		       eptype, (unsigned long long)*address);
Packit Service e18529
Packit Service e18529
	return ret;
Packit Service e18529
}
Packit Service e18529
Packit Service e18529
int main(int argc, char * const argv[])
Packit Service e18529
{
Packit Service e18529
	int ret = 0;                /* Returned value */
Packit Service e18529
	int found = 0;
Packit Service e18529
	off_t fp;
Packit Service e18529
	size_t size;
Packit Service e18529
	int efi;
Packit Service 25e533
	u8 *buf = NULL;
Packit Service e18529
Packit Service e18529
	/*
Packit Service e18529
	 * We don't want stdout and stderr to be mixed up if both are
Packit Service e18529
	 * redirected to the same file.
Packit Service e18529
	 */
Packit Service e18529
	setlinebuf(stdout);
Packit Service e18529
	setlinebuf(stderr);
Packit Service e18529
Packit Service e18529
	if (sizeof(u8) != 1 || sizeof(u16) != 2 || sizeof(u32) != 4 || '\0' != 0)
Packit Service e18529
	{
Packit Service e18529
		fprintf(stderr, "%s: compiler incompatibility\n", argv[0]);
Packit Service e18529
		exit(255);
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	/* Set default option values */
Packit Service e18529
	opt.devmem = DEFAULT_MEM_DEV;
Packit Service e18529
	opt.flags = 0;
Packit Service e18529
	opt.handle = ~0U;
Packit Service e18529
Packit Service e18529
	if (parse_command_line(argc, argv)<0)
Packit Service e18529
	{
Packit Service e18529
		ret = 2;
Packit Service e18529
		goto exit_free;
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	if (opt.flags & FLAG_HELP)
Packit Service e18529
	{
Packit Service e18529
		print_help();
Packit Service e18529
		goto exit_free;
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	if (opt.flags & FLAG_VERSION)
Packit Service e18529
	{
Packit Service e18529
		printf("%s\n", VERSION);
Packit Service e18529
		goto exit_free;
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	if (!(opt.flags & FLAG_QUIET))
Packit Service 622062
		printf("# dmidecode %s\n", VERSION);
Packit Service e18529
Packit Service e18529
	/* Read from dump if so instructed */
Packit Service e18529
	if (opt.flags & FLAG_FROM_DUMP)
Packit Service e18529
	{
Packit Service e18529
		if (!(opt.flags & FLAG_QUIET))
Packit Service 622062
			printf("Reading SMBIOS/DMI data from file %s.\n",
Packit Service 622062
			       opt.dumpfile);
Packit Service e18529
		if ((buf = mem_chunk(0, 0x20, opt.dumpfile)) == NULL)
Packit Service e18529
		{
Packit Service e18529
			ret = 1;
Packit Service e18529
			goto exit_free;
Packit Service e18529
		}
Packit Service e18529
Packit Service e18529
		if (memcmp(buf, "_SM3_", 5) == 0)
Packit Service e18529
		{
Packit Service e18529
			if (smbios3_decode(buf, opt.dumpfile, 0))
Packit Service e18529
				found++;
Packit Service e18529
		}
Packit Service e18529
		else if (memcmp(buf, "_SM_", 4) == 0)
Packit Service e18529
		{
Packit Service e18529
			if (smbios_decode(buf, opt.dumpfile, 0))
Packit Service e18529
				found++;
Packit Service e18529
		}
Packit Service e18529
		else if (memcmp(buf, "_DMI_", 5) == 0)
Packit Service e18529
		{
Packit Service e18529
			if (legacy_decode(buf, opt.dumpfile, 0))
Packit Service e18529
				found++;
Packit Service e18529
		}
Packit Service e18529
		goto done;
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	/*
Packit Service e18529
	 * First try reading from sysfs tables.  The entry point file could
Packit Service e18529
	 * contain one of several types of entry points, so read enough for
Packit Service e18529
	 * the largest one, then determine what type it contains.
Packit Service e18529
	 */
Packit Service e18529
	size = 0x20;
Packit Service e18529
	if (!(opt.flags & FLAG_NO_SYSFS)
Packit Service e18529
	 && (buf = read_file(0, &size, SYS_ENTRY_FILE)) != NULL)
Packit Service e18529
	{
Packit Service e18529
		if (!(opt.flags & FLAG_QUIET))
Packit Service 622062
			printf("Getting SMBIOS data from sysfs.\n");
Packit Service e18529
		if (size >= 24 && memcmp(buf, "_SM3_", 5) == 0)
Packit Service e18529
		{
Packit Service e18529
			if (smbios3_decode(buf, SYS_TABLE_FILE, FLAG_NO_FILE_OFFSET))
Packit Service e18529
				found++;
Packit Service e18529
		}
Packit Service e18529
		else if (size >= 31 && memcmp(buf, "_SM_", 4) == 0)
Packit Service e18529
		{
Packit Service e18529
			if (smbios_decode(buf, SYS_TABLE_FILE, FLAG_NO_FILE_OFFSET))
Packit Service e18529
				found++;
Packit Service e18529
		}
Packit Service e18529
		else if (size >= 15 && memcmp(buf, "_DMI_", 5) == 0)
Packit Service e18529
		{
Packit Service e18529
			if (legacy_decode(buf, SYS_TABLE_FILE, FLAG_NO_FILE_OFFSET))
Packit Service e18529
				found++;
Packit Service e18529
		}
Packit Service e18529
Packit Service e18529
		if (found)
Packit Service e18529
			goto done;
Packit Service e18529
		if (!(opt.flags & FLAG_QUIET))
Packit Service 622062
			printf("Failed to get SMBIOS data from sysfs.\n");
Packit Service e18529
	}
Packit Service e18529
Packit Service 25e533
	/* Next try EFI (ia64, Intel-based Mac, arm64) */
Packit Service e18529
	efi = address_from_efi(&fp);
Packit Service e18529
	switch (efi)
Packit Service e18529
	{
Packit Service e18529
		case EFI_NOT_FOUND:
Packit Service e18529
			goto memory_scan;
Packit Service e18529
		case EFI_NO_SMBIOS:
Packit Service e18529
			ret = 1;
Packit Service e18529
			goto exit_free;
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	if (!(opt.flags & FLAG_QUIET))
Packit Service 622062
		printf("Found SMBIOS entry point in EFI, reading table from %s.\n",
Packit Service 622062
		       opt.devmem);
Packit Service e18529
	if ((buf = mem_chunk(fp, 0x20, opt.devmem)) == NULL)
Packit Service e18529
	{
Packit Service e18529
		ret = 1;
Packit Service e18529
		goto exit_free;
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	if (memcmp(buf, "_SM3_", 5) == 0)
Packit Service e18529
	{
Packit Service e18529
		if (smbios3_decode(buf, opt.devmem, 0))
Packit Service e18529
			found++;
Packit Service e18529
	}
Packit Service e18529
	else if (memcmp(buf, "_SM_", 4) == 0)
Packit Service e18529
	{
Packit Service e18529
		if (smbios_decode(buf, opt.devmem, 0))
Packit Service e18529
			found++;
Packit Service e18529
	}
Packit Service e18529
	goto done;
Packit Service e18529
Packit Service e18529
memory_scan:
Packit Service 25e533
#if defined __i386__ || defined __x86_64__
Packit Service e18529
	if (!(opt.flags & FLAG_QUIET))
Packit Service 622062
		printf("Scanning %s for entry point.\n", opt.devmem);
Packit Service e18529
	/* Fallback to memory scan (x86, x86_64) */
Packit Service e18529
	if ((buf = mem_chunk(0xF0000, 0x10000, opt.devmem)) == NULL)
Packit Service e18529
	{
Packit Service e18529
		ret = 1;
Packit Service e18529
		goto exit_free;
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	/* Look for a 64-bit entry point first */
Packit Service e18529
	for (fp = 0; fp <= 0xFFE0; fp += 16)
Packit Service e18529
	{
Packit Service e18529
		if (memcmp(buf + fp, "_SM3_", 5) == 0)
Packit Service e18529
		{
Packit Service e18529
			if (smbios3_decode(buf + fp, opt.devmem, 0))
Packit Service e18529
			{
Packit Service e18529
				found++;
Packit Service e18529
				goto done;
Packit Service e18529
			}
Packit Service e18529
		}
Packit Service e18529
	}
Packit Service e18529
Packit Service e18529
	/* If none found, look for a 32-bit entry point */
Packit Service e18529
	for (fp = 0; fp <= 0xFFF0; fp += 16)
Packit Service e18529
	{
Packit Service e18529
		if (memcmp(buf + fp, "_SM_", 4) == 0 && fp <= 0xFFE0)
Packit Service e18529
		{
Packit Service e18529
			if (smbios_decode(buf + fp, opt.devmem, 0))
Packit Service e18529
			{
Packit Service e18529
				found++;
Packit Service e18529
				goto done;
Packit Service e18529
			}
Packit Service e18529
		}
Packit Service e18529
		else if (memcmp(buf + fp, "_DMI_", 5) == 0)
Packit Service e18529
		{
Packit Service e18529
			if (legacy_decode(buf + fp, opt.devmem, 0))
Packit Service e18529
			{
Packit Service e18529
				found++;
Packit Service e18529
				goto done;
Packit Service e18529
			}
Packit Service e18529
		}
Packit Service e18529
	}
Packit Service 25e533
#endif
Packit Service e18529
Packit Service e18529
done:
Packit Service e18529
	if (!found && !(opt.flags & FLAG_QUIET))
Packit Service 622062
		printf("# No SMBIOS nor DMI entry point found, sorry.\n");
Packit Service e18529
Packit Service e18529
	free(buf);
Packit Service e18529
exit_free:
Packit Service e18529
	free(opt.type);
Packit Service e18529
Packit Service e18529
	return ret;
Packit Service e18529
}