[PATCH 04/12] sbbr/dmicheck: Add SMBIOS test cases as per SBBR.

Jeffrey Hugo jhugo at codeaurora.org
Fri Mar 3 18:37:27 UTC 2017


On 3/2/2017 3:26 PM, Supreeth Venkatesh wrote:
> Server Base Boot Requirements (SBBR) specification is intended for SBSA-
> compliant 64-bit ARMv8 servers.
> It defines the base firmware requirements for out-of-box support of any
> ARM SBSA-compatible Operating System or hypervisor.
> The requirements in this specification are expected to be minimal yet
> complete for booting a multi-core ARMv8 server platform, while leaving
> plenty of room for OEM or ODM innovations and design details.
> For more information, download the SBBR specification here:
> http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0044b/index.html
>
> This change introduces test cases as per SBBR specification to SMBIOS
> structures. These test cases may be subset/superset of dmicheck tests
> already existing. However, to preserve "sbbr" classification, new file
> is created, even when most of the code is re-used from dmicheck.
>
> Signed-off-by: Supreeth Venkatesh <supreeth.venkatesh at arm.com>
> ---
>  src/sbbr/dmicheck/dmicheck.c | 1625 ++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 1625 insertions(+)
>  create mode 100644 src/sbbr/dmicheck/dmicheck.c
>
> diff --git a/src/sbbr/dmicheck/dmicheck.c b/src/sbbr/dmicheck/dmicheck.c
> new file mode 100644
> index 0000000..32728fa
> --- /dev/null
> +++ b/src/sbbr/dmicheck/dmicheck.c
> @@ -0,0 +1,1625 @@
> +/*
> + * Copyright (C) 2010-2017 Canonical
> + * Copyright (C) 2017      ARM Ltd
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
> + *
> + */
> +
> +#include <stdbool.h>
> +#include <string.h>
> +#include <stdlib.h>
> +#include <inttypes.h>
> +
> +#include "fwts.h"
> +
> +#if defined(FWTS_HAS_SBBR)
> +
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <string.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <unistd.h>
> +#include <limits.h>
> +#include <fcntl.h>
> +
> +#define DMI_VERSION			(0x0300)
> +#define VERSION_MAJOR(v)		((v) >> 8)
> +#define VERSION_MINOR(v)		((v) & 0xff)
> +
> +#define SMBIOS_END_OF_TABLE		(127)
> +
> +#define DMI_NO_TABLE			"DMINoTable"
> +#define DMI_NO_TABLE_HEADER		"DMINoTableHeader"
> +#define DMI_BAD_TABLE_LENGTH		"DMIBadTableLength"
> +#define DMI_BAD_UUID			"DMIBadUUID"
> +#define DMI_STRUCT_COUNT		"DMIStructCount"
> +#define DMI_VALUE_OUT_OF_RANGE		"DMIValueOutOfRange"
> +#define DMI_STRING_INDEX_OUT_OF_RANGE	"DMIStringIndexOutOfRange"
> +#define DMI_ILLEGAL_MAPPED_ADDR_RANGE	"DMIIllegalMappedAddrRange"
> +#define DMI_MGMT_CTRL_HOST_TYPE		"DMIMgmtCtrlHostType"
> +#define DMI_INVALID_ENTRY_LENGTH	"DMIInvalidEntryLength"
> +#define DMI_INVALID_HARDWARE_ENTRY	"DMIInvalidHardwareEntry"
> +#define DMI_RESERVED_VALUE_USED		"DMIReservedValueUsed"
> +
> +#define GET_UINT16(x) (uint16_t)(*(const uint16_t *)(x))
> +#define GET_UINT32(x) (uint32_t)(*(const uint32_t *)(x))
> +#define GET_UINT64(x) (uint64_t)(*(const uint64_t *)(x))
> +
> +#define CHASSIS_OTHER			0x00
> +#define CHASSIS_DESKTOP			0x01
> +#define CHASSIS_WORKSTATION		0x02
> +#define CHASSIS_MOBILE			0x04
> +#define CHASSIS_SERVER			0x08
> +
> +typedef struct {
> +	const char *label;
> +	const char *field;
> +	const char *value;
> +} fwts_dmi_pattern;
> +
> +typedef struct {
> +	uint16_t   old;
> +	uint16_t   new;
> +} fwts_dmi_version;
> +
> +typedef struct {
> +	const char *name;
> +	uint8_t   original;
> +} fwts_chassis_type_map;
> +
> +typedef struct {
> +	uint8_t	type;
> +	uint8_t	offset;
> +} fwts_dmi_used_by_kernel;
> +
> +static bool smbios30_found = false;
> +
> +/*
> + *  Table derived by scanning thousands of DMI table dumps from bug reports
> + */
> +static const fwts_dmi_pattern dmi_patterns[] = {
> +	{ "DMISerialNumber",	"Serial Number",	"0000000" },
> +	{ "DMISerialNumber",	"Serial Number",	"00000000" },
> +	{ "DMISerialNumber",	"Serial Number",	"000000000" },
> +	{ "DMISerialNumber",	"Serial Number",	"0000000000" },
> +	{ "DMISerialNumber",	"Serial Number",	"0x00000000" },
> +	{ "DMISerialNumber",	"Serial Number",	"0x0000000000000000" },
> +	{ "DMISerialNumber",	"Serial Number",	"012345678" },
> +	{ "DMISerialNumber",	"Serial Number",	"0123456789" },
> +	{ "DMISerialNumber",	"Serial Number",	"01234567890" },
> +	{ "DMISerialNumber",	"Serial Number",	"012345678900" },
> +	{ "DMISerialNumber",	"Serial Number",	"0123456789000" },
> +	{ "DMISerialNumber",	"Serial Number",	"System Serial Number" },
> +	{ "DMISerialNumber",	"Serial Number",	"MB-1234567890" },
> +	{ "DMISerialNumber",	"Serial Number",	"NB-1234567890" },
> +	{ "DMISerialNumber",	"Serial Number",	"NB-0123456789" },
> +	{ "DMISerialNumber",	"Serial Number",	"Base Board Serial Number" },
> +	{ "DMISerialNumber",	"Serial Number",	"Chassis Serial Number" },
> +	{ "DMISerialNumber",	"Serial Number",	"<cut out>" },
> +	{ "DMISerialNumber",	"Serial Number",	"Empty" },
> +	{ "DMISerialNumber",	"Serial Number",	"[Empty]" },
> +	{ "DMISerialNumber",	"Serial Number",	"NA" },
> +	{ "DMISerialNumber",	"Serial Number",	"N/A" },
> +	{ "DMISerialNumber",	"Serial Number",	"None" },
> +	{ "DMISerialNumber",	"Serial Number",	"None1" },
> +	{ "DMISerialNumber",	"Serial Number",	"Not Available" },
> +	{ "DMISerialNumber",	"Serial Number",	"Not Specified" },
> +	{ "DMISerialNumber",	"Serial Number",	"NotSupport" },
> +	{ "DMISerialNumber",	"Serial Number",	"Not Supported by CPU" },
> +	{ "DMISerialNumber",	"Serial Number",	"Not Supported" },
> +	{ "DMISerialNumber",	"Serial Number",	"OEM Chassis Serial Number" },
> +	{ "DMISerialNumber",	"Serial Number",	"OEM_Define1" },
> +	{ "DMISerialNumber",	"Serial Number",	"OEM_Define2" },
> +	{ "DMISerialNumber",	"Serial Number",	"OEM_Define3" },
> +	{ "DMISerialNumber",	"Serial Number",	"SerNum0" },
> +	{ "DMISerialNumber",	"Serial Number",	"SerNum00" },
> +	{ "DMISerialNumber",	"Serial Number",	"SerNum01" },
> +	{ "DMISerialNumber",	"Serial Number",	"SerNum02" },
> +	{ "DMISerialNumber",	"Serial Number",	"SerNum03" },
> +	{ "DMISerialNumber",	"Serial Number",	"SerNum1" },
> +	{ "DMISerialNumber",	"Serial Number",	"SerNum2" },
> +	{ "DMISerialNumber",	"Serial Number",	"SerNum3" },
> +	{ "DMISerialNumber",	"Serial Number",	"SerNum4" },
> +	{ "DMISerialNumber",	"Serial Number",	"TBD by ODM" },
> +	{ "DMISerialNumber",	"Serial Number",	"To Be Defined By O.E.M" },
> +	{ "DMISerialNumber",	"Serial Number",	"To be filled by O.E.M." },
> +	{ "DMISerialNumber",	"Serial Number",	"To Be Filled By O.E.M." },
> +	{ "DMISerialNumber",	"Serial Number",	"Unknow" },
> +	{ "DMISerialNumber",	"Serial Number",	"Unknown" },
> +	{ "DMISerialNumber",	"Serial Number",	"XXXXXXXXXXXX" },
> +	{ "DMISerialNumber",	"Serial Number",	"XXXXXXXXXXX" },
> +	{ "DMISerialNumber",	"Serial Number",	"XXXXXXXXXX" },
> +	{ "DMISerialNumber",	"Serial Number",	"XXXXXXXXX" },
> +	{ "DMISerialNumber",	"Serial Number",	"XXXXXXXX" },
> +	{ "DMISerialNumber",	"Serial Number",	"XXXXXX" },
> +	{ "DMISerialNumber",	"Serial Number",	"XXXXX" },
> +	{ "DMISerialNumber",	NULL,			"Chassis Serial Number" },
> +	{ "DMIAssetTag",	"Asset Tag",		"0000000000" },
> +	{ "DMIAssetTag",	"Asset Tag",		"0x00000000" },
> +	{ "DMIAssetTag",	"Asset Tag",		"1234567890" },
> +	{ "DMIAssetTag",	"Asset Tag",		"123456789000" },
> +	{ "DMIAssetTag",	"Asset Tag",		"9876543210" },
> +	{ "DMIAssetTag",	"Asset Tag",		"A1_AssetTagNum0" },
> +	{ "DMIAssetTag",	"Asset Tag",		"A1_AssetTagNum1" },
> +	{ "DMIAssetTag",	"Asset Tag",		"A1_AssetTagNum2" },
> +	{ "DMIAssetTag",	"Asset Tag",		"A1_AssetTagNum3" },
> +	{ "DMIAssetTag",	"Asset Tag",		"ABCDEFGHIJKLM" },
> +	{ "DMIAssetTag",	"Asset Tag",		"Asset-1234567890" },
> +	{ "DMIAssetTag",	"Asset Tag",		"Asset Tag" },
> +	{ "DMIAssetTag",	"Asset Tag",		"Asset Tag:" },
> +	{ "DMIAssetTag",	"Asset Tag",		"AssetTagNum0" },
> +	{ "DMIAssetTag",	"Asset Tag",		"AssetTagNum1" },
> +	{ "DMIAssetTag",	"Asset Tag",		"AssetTagNum2" },
> +	{ "DMIAssetTag",	"Asset Tag",		"AssetTagNum3" },
> +	{ "DMIAssetTag",	"Asset Tag",		"AssetTagNum4" },
> +	{ "DMIAssetTag",	"Asset Tag",		"Asset tracking" },
> +	{ "DMIAssetTag",	"Asset Tag",		"ATN12345678901234567" },
> +	{ "DMIAssetTag",	"Asset Tag",		"Base Board Asset Tag#" },
> +	{ "DMIAssetTag",	"Asset Tag",		"Base Board Asset Tag" },
> +	{ "DMIAssetTag",	"Asset Tag",		"Chassis Asset Tag" },
> +	{ "DMIAssetTag",	"Asset Tag",		"<cut out>" },
> +	{ "DMIAssetTag",	"Asset Tag",		"Fill By OEM" },
> +	{ "DMIAssetTag",	"Asset Tag",		"N/A" },
> +	{ "DMIAssetTag",	"Asset Tag",		"No Asset Information" },
> +	{ "DMIAssetTag",	"Asset Tag",		"No Asset Tag" },
> +	{ "DMIAssetTag",	"Asset Tag",		"None" },
> +	{ "DMIAssetTag",	"Asset Tag",		"Not Available" },
> +	{ "DMIAssetTag",	"Asset Tag",		"Not Specified" },
> +	{ "DMIAssetTag",	"Asset Tag",		"OEM_Define0" },
> +	{ "DMIAssetTag",	"Asset Tag",		"OEM_Define1" },
> +	{ "DMIAssetTag",	"Asset Tag",		"OEM_Define2" },
> +	{ "DMIAssetTag",	"Asset Tag",		"OEM_Define3" },
> +	{ "DMIAssetTag",	"Asset Tag",		"OEM_Define4" },
> +	{ "DMIAssetTag",	"Asset Tag",		"TBD by ODM" },
> +	{ "DMIAssetTag",	"Asset Tag",		"To Be Defined By O.E.M" },
> +	{ "DMIAssetTag",	"Asset Tag",		"To be filled by O.E.M." },
> +	{ "DMIAssetTag",	"Asset Tag",		"To Be Filled By O.E.M." },
> +	{ "DMIAssetTag",	"Asset Tag",		"Unknown" },
> +	{ "DMIAssetTag",	"Asset Tag",		"XXXXXXXXXXXX" },
> +	{ "DMIAssetTag",	"Asset Tag",		"XXXXXXXXXXX" },
> +	{ "DMIAssetTag",	"Asset Tag",		"XXXXXXXXXX" },
> +	{ "DMIAssetTag",	"Asset Tag",		"XXXXXXXXX" },
> +	{ "DMIAssetTag",	"Asset Tag",		"XXXXXXXX" },
> +	{ "DMIAssetTag",	"Asset Tag",		"XXXXXXX" },
> +	{ "DMIAssetTag",	"Asset Tag",		"XXXXXX" },
> +	{ "DMIChassisVendor",	NULL,			"Chassis Manufacture" },
> +	{ "DMIChassisVersion",	NULL,			"Chassis Version" },
> +	{ "DMIProductVersion",	NULL,			"System Version" },
> +	{ "DMIBadDefault",	NULL,			"To Be Defined By O.E.M" },
> +	{ "DMIBadDefault",	NULL,			"To be filled by O.E.M." },
> +	{ "DMIBadDefault",	NULL,			"To Be Filled By O.E.M." },
> +	{ NULL,			NULL,			NULL }
> +};
> +
> +static const char *uuid_patterns[] = {
> +	"0A0A0A0A-0A0A-0A0A-0A0A-0A0A0A0A0A0A",
> +	NULL,
> +};
> +
> +static const fwts_chassis_type_map fwts_dmi_chassis_type[] = {
> +	{ "Invalid",		FWTS_SMBIOS_CHASSIS_INVALID },
> +	{ "Other",		FWTS_SMBIOS_CHASSIS_OTHER },
> +	{ "Unknown",		FWTS_SMBIOS_CHASSIS_UNKNOWN },
> +	{ "Desktop",		FWTS_SMBIOS_CHASSIS_DESKTOP },
> +	{ "Low Profile Desktop",FWTS_SMBIOS_CHASSIS_LOW_PROFILE_DESKTOP },
> +	{ "Pizza Box",		FWTS_SMBIOS_CHASSIS_PIZZA_BOX },
> +	{ "Mini Tower",		FWTS_SMBIOS_CHASSIS_MINI_TOWER },
> +	{ "Chassis Tower",	FWTS_SMBIOS_CHASSIS_TOWER },
> +	{ "Portable",		FWTS_SMBIOS_CHASSIS_PORTABLE },
> +	{ "Laptop",		FWTS_SMBIOS_CHASSIS_LAPTOP },
> +	{ "Notebook",		FWTS_SMBIOS_CHASSIS_NOTEBOOK },
> +	{ "Handheld",		FWTS_SMBIOS_CHASSIS_HANDHELD },
> +	{ "Docking Station",	FWTS_SMBIOS_CHASSIS_DOCKING_STATION },
> +	{ "All In One",		FWTS_SMBIOS_CHASSIS_ALL_IN_ONE },
> +	{ "Sub Notebook",	FWTS_SMBIOS_CHASSIS_SUB_NOTEBOOK },
> +	{ "Space Saving",	FWTS_SMBIOS_CHASSIS_SPACE_SAVING },
> +	{ "Lunch Box",		FWTS_SMBIOS_CHASSIS_LUNCH_BOX},
> +	{ "Server Chassis",	FWTS_SMBIOS_CHASSIS_MAIN_SERVER_CHASSIS },
> +	{ "Expansion Chassis",	FWTS_SMBIOS_CHASSIS_EXPANISON_CHASSIS },
> +	{ "Sub Chassis",	FWTS_SMBIOS_CHASSIS_SUB_CHASSIS },
> +	{ "Bus Expansion Chassis", FWTS_SMBIOS_CHASSIS_BUS_EXPANSION_CHASSIS },
> +	{ "Peripheral Chassis",	FWTS_SMBIOS_CHASSIS_PERIPHERAL_CHASSIS },
> +	{ "Raid Chassis",	FWTS_SMBIOS_CHASSIS_RAID_CHASSIS },
> +	{ "Rack Mount Chassis",	FWTS_SMBIOS_CHASSIS_RACK_MOUNT_CHASSIS },
> +	{ "Sealed Case PC",	FWTS_SMBIOS_CHASSIS_SEALED_CASE_PC },
> +	{ "Multi System Chassis",FWTS_SMBIOS_CHASSIS_MULTI_SYSTEM_CHASSIS },
> +	{ "Compact PCI",	FWTS_SMBIOS_CHASSIS_COMPACT_PCI },
> +	{ "Advanced TCA",	FWTS_SMBIOS_CHASSIS_ADVANCED_TCA },
> +	{ "Blade",		FWTS_SMBIOS_CHASSIS_BLADE },
> +	{ "Enclosure",		FWTS_SMBIOS_CHASSIS_BLADE_ENCLOSURE },
> +	{ "Tablet",		FWTS_SMBIOS_CHASSIS_TABLET },
> +	{ "Convertible",	FWTS_SMBIOS_CHASSIS_CONVERTIBLE },
> +	{ "Detachable",		FWTS_SMBIOS_CHASSIS_DETACHABLE },
> +};
> +
> +/* Remapping table from buggy version numbers to correct values */
> +static const fwts_dmi_version dmi_versions[] = {
> +	{ 0x021f, 0x0203 },
> +	{ 0x0221, 0x0203 },
> +	{ 0x0233, 0x0206 },
> +	{ 0, 0 }
> +};
> +
> +#define FIELD_ANY	0xff
> +#define TYPE_EOD	0xff
> +#define ANCHOR_SIZE 8
> +
> +/*
> + *  DMI decoded fields used by the kernel, i.e. fields
> + *  we care that work,
> + *	see drivers/firmware/dmi_scan.c, dmi_decode()
> + */
> +static fwts_dmi_used_by_kernel dmi_used_by_kernel_table[] = {
> +	/* Type 0 BIOS Information fields */
> +	{ 0, 4 },
> +	{ 0, 5 },
> +	{ 0, 8 },
> +	/* Type 1, System Information */
> +	{ 1, 4 },
> +	{ 1, 5 },
> +	{ 1, 6 },
> +	{ 1, 7 },
> +	{ 1, 8 },
> +	/* Type 2, Base Board Information */
> +	{ 2, 4 },
> +	{ 2, 5 },
> +	{ 2, 6 },
> +	{ 2, 7 },
> +	{ 2, 8 },
> +	/* Type 3, Chassis Information */
> +	{ 3, 4 },
> +	{ 3, 5 },
> +	{ 3, 6 },
> +	{ 3, 7 },
> +	{ 3, 8 },
> +	/* Type 10, Onboard Devices Information */
> +	{ 10, FIELD_ANY },
> +	/* Type 11, OEM Strings */
> +	{ 11, FIELD_ANY },
> +	/* Type 38, IPMI Device Information */
> +	{ 38, FIELD_ANY },
> +	/* Type 41, Onboard Devices Extended Information */
> +	{ 41, FIELD_ANY },
> +	/* End */
> +	{ TYPE_EOD, 0xff },
> +};
> +
> +static int dmi_load_file(const char* filename, void *buf, size_t size)
> +{
> +	int fd;
> +	ssize_t ret;
> +
> +	if ((fd = open(filename, O_RDONLY)) < 0)
> +		return FWTS_ERROR;
> +	ret = read(fd, buf, size);
> +	(void)close(fd);
> +	if (ret != (ssize_t)size)
> +		return FWTS_ERROR;
> +	return FWTS_OK;
> +}
> +
> +static void* dmi_table_smbios30(fwts_framework *fw, fwts_smbios30_entry *entry)
> +{
> +	size_t length = (size_t)entry->struct_table_max_size;
> +	void *table;
> +	char anchor[ANCHOR_SIZE];
> +
> +	/* 64 bit entry sanity check on length */
> +	if ((length == 0) || (length > 0xffffff)) {
> +		fwts_log_info(fw, "SMBIOS table size of %zu bytes looks "
> +			"suspicious",  length);
> +		return NULL;
> +	}
> +
> +	if (dmi_load_file("/sys/firmware/dmi/tables/smbios_entry_point", anchor, sizeof("_SM3_")) == FWTS_OK
> +			&& strncmp(anchor, "_SM3_", sizeof("_SM3_")) == 0) {
> +		table = malloc(length);
> +		if (!table)
> +			return NULL;
> +		if (dmi_load_file("/sys/firmware/dmi/tables/DMI", table, length) == FWTS_OK) {
> +			fwts_log_info(fw, "SMBIOS30 table loaded from /sys/firmware/dmi/tables/DMI\n");
> +			return table;
> +		}
> +		free(table);
> +	}
> +
> +	fwts_log_error(fw, "Cannot mmap SMBIOS 3.0 table from %16.16" PRIx64 "..%16.16" PRIx64 ".",
> +			entry->struct_table_address, entry->struct_table_address + entry->struct_table_max_size);
> +	return NULL;
> +}

This appears broken on my platform.  The standard dmitest works fine. 
This test outputs:

PASSED: Test 1, SMBIOS30 Table Entry Point Checksum is valid.
PASSED: Test 1, SMBIOS30 Table Entry Point Length is valid.
Cannot mmap SMBIOS 3.0 table from 0000000004e50000..0000000004e529c4.

Test 2 of 3: Test DMI/SMBIOS3 tables for errors.
Cannot mmap SMBIOS 3.0 table from 0000000004e50000..0000000004e529c4.

Test 3 of 3: Test ARM SBBR SMBIOS structure requirements.
Cannot mmap SMBIOS 3.0 table from 0000000004e50000..0000000004e529c4.

-- 
Jeffrey Hugo
Qualcomm Datacenter Technologies as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.



More information about the fwts-devel mailing list