Blame dmidecode.c

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