[PATCH 04/12] sbbr/dmicheck: Add SMBIOS test cases as per SBBR.
Supreeth Venkatesh
supreeth.venkatesh at arm.com
Mon Mar 6 17:56:22 UTC 2017
On Fri, 2017-03-03 at 11:37 -0700, Jeffrey Hugo wrote:
> 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.den0044
> > b/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 "DMIStringIndexOutOfR
> > ange"
> > +#define DMI_ILLEGAL_MAPPED_ADDR_RANGE "DMIIllegalMappedAddr
> > Range"
> > +#define DMI_MGMT_CTRL_HOST_TYPE "DMIMgmtCtrlHostTyp
> > e"
> > +#define DMI_INVALID_ENTRY_LENGTH "DMIInvalidEntryLength"
> > +#define DMI_INVALID_HARDWARE_ENTRY "DMIInvalidHardwareEntry
> > "
> > +#define DMI_RESERVED_VALUE_USED "DMIReservedValueUs
> > ed"
> > +
> > +#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", "00000
> > 00" },
> > + { "DMISerialNumber", "Serial Number", "00000
> > 000" },
> > + { "DMISerialNumber", "Serial Number", "00000
> > 0000" },
> > + { "DMISerialNumber", "Serial Number", "00000
> > 00000" },
> > + { "DMISerialNumber", "Serial Number", "0x000
> > 00000" },
> > + { "DMISerialNumber", "Serial Number", "0x000
> > 0000000000000" },
> > + { "DMISerialNumber", "Serial Number", "01234
> > 5678" },
> > + { "DMISerialNumber", "Serial Number", "01234
> > 56789" },
> > + { "DMISerialNumber", "Serial Number", "01234
> > 567890" },
> > + { "DMISerialNumber", "Serial Number", "01234
> > 5678900" },
> > + { "DMISerialNumber", "Serial Number", "01234
> > 56789000" },
> > + { "DMISerialNumber", "Serial Number", "Syste
> > m 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", "Chass
> > is Serial Number" },
> > + { "DMISerialNumber", "Serial Number", "<cut
> > out>" },
> > + { "DMISerialNumber", "Serial Number", "Empty
> > " },
> > + { "DMISerialNumber", "Serial Number", "[Empt
> > y]" },
> > + { "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", "NotSu
> > pport" },
> > + { "DMISerialNumber", "Serial Number", "Not
> > Supported by CPU" },
> > + { "DMISerialNumber", "Serial Number", "Not
> > Supported" },
> > + { "DMISerialNumber", "Serial Number", "OEM
> > Chassis Serial Number" },
> > + { "DMISerialNumber", "Serial Number", "OEM_D
> > efine1" },
> > + { "DMISerialNumber", "Serial Number", "OEM_D
> > efine2" },
> > + { "DMISerialNumber", "Serial Number", "OEM_D
> > efine3" },
> > + { "DMISerialNumber", "Serial Number", "SerNu
> > m0" },
> > + { "DMISerialNumber", "Serial Number", "SerNu
> > m00" },
> > + { "DMISerialNumber", "Serial Number", "SerNu
> > m01" },
> > + { "DMISerialNumber", "Serial Number", "SerNu
> > m02" },
> > + { "DMISerialNumber", "Serial Number", "SerNu
> > m03" },
> > + { "DMISerialNumber", "Serial Number", "SerNu
> > m1" },
> > + { "DMISerialNumber", "Serial Number", "SerNu
> > m2" },
> > + { "DMISerialNumber", "Serial Number", "SerNu
> > m3" },
> > + { "DMISerialNumber", "Serial Number", "SerNu
> > m4" },
> > + { "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", "Unkno
> > w" },
> > + { "DMISerialNumber", "Serial Number", "Unkno
> > wn" },
> > + { "DMISerialNumber", "Serial Number", "XXXXX
> > XXXXXXX" },
> > + { "DMISerialNumber", "Serial Number", "XXXXX
> > XXXXXX" },
> > + { "DMISerialNumber", "Serial Number", "XXXXX
> > XXXXX" },
> > + { "DMISerialNumber", "Serial Number", "XXXXX
> > XXXX" },
> > + { "DMISerialNumber", "Serial Number", "XXXXX
> > XXX" },
> > + { "DMISerialNumber", "Serial Number", "XXXXX
> > X" },
> > + { "DMISerialNumber", "Serial Number", "XXXXX
> > " },
> > + { "DMISerialNumber", NULL, "
> > Chassis Serial Number" },
> > + { "DMIAssetTag", "Asset Tag", "00000
> > 00000" },
> > + { "DMIAssetTag", "Asset Tag", "0x000
> > 00000" },
> > + { "DMIAssetTag", "Asset Tag", "12345
> > 67890" },
> > + { "DMIAssetTag", "Asset Tag", "12345
> > 6789000" },
> > + { "DMIAssetTag", "Asset Tag", "98765
> > 43210" },
> > + { "DMIAssetTag", "Asset Tag", "A1_As
> > setTagNum0" },
> > + { "DMIAssetTag", "Asset Tag", "A1_As
> > setTagNum1" },
> > + { "DMIAssetTag", "Asset Tag", "A1_As
> > setTagNum2" },
> > + { "DMIAssetTag", "Asset Tag", "A1_As
> > setTagNum3" },
> > + { "DMIAssetTag", "Asset Tag", "ABCDE
> > FGHIJKLM" },
> > + { "DMIAssetTag", "Asset Tag", "Asset
> > -1234567890" },
> > + { "DMIAssetTag", "Asset Tag", "Asset
> > Tag" },
> > + { "DMIAssetTag", "Asset Tag", "Asset
> > Tag:" },
> > + { "DMIAssetTag", "Asset Tag", "Asset
> > TagNum0" },
> > + { "DMIAssetTag", "Asset Tag", "Asset
> > TagNum1" },
> > + { "DMIAssetTag", "Asset Tag", "Asset
> > TagNum2" },
> > + { "DMIAssetTag", "Asset Tag", "Asset
> > TagNum3" },
> > + { "DMIAssetTag", "Asset Tag", "Asset
> > TagNum4" },
> > + { "DMIAssetTag", "Asset Tag", "Asset
> > tracking" },
> > + { "DMIAssetTag", "Asset Tag", "ATN12
> > 345678901234567" },
> > + { "DMIAssetTag", "Asset Tag", "Base
> > Board Asset Tag#" },
> > + { "DMIAssetTag", "Asset Tag", "Base
> > Board Asset Tag" },
> > + { "DMIAssetTag", "Asset Tag", "Chass
> > is 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_D
> > efine0" },
> > + { "DMIAssetTag", "Asset Tag", "OEM_D
> > efine1" },
> > + { "DMIAssetTag", "Asset Tag", "OEM_D
> > efine2" },
> > + { "DMIAssetTag", "Asset Tag", "OEM_D
> > efine3" },
> > + { "DMIAssetTag", "Asset Tag", "OEM_D
> > efine4" },
> > + { "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", "Unkno
> > wn" },
> > + { "DMIAssetTag", "Asset Tag", "XXXXX
> > XXXXXXX" },
> > + { "DMIAssetTag", "Asset Tag", "XXXXX
> > XXXXXX" },
> > + { "DMIAssetTag", "Asset Tag", "XXXXX
> > XXXXX" },
> > + { "DMIAssetTag", "Asset Tag", "XXXXX
> > XXXX" },
> > + { "DMIAssetTag", "Asset Tag", "XXXXX
> > XXX" },
> > + { "DMIAssetTag", "Asset Tag", "XXXXX
> > XX" },
> > + { "DMIAssetTag", "Asset Tag", "XXXXX
> > X" },
> > + { "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_BO
> > X },
> > + { "Mini Tower", FWTS_SMBIOS_CHASSIS_MINI_TO
> > WER },
> > + { "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_ST
> > ATION },
> > + { "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_BO
> > X},
> > + { "Server Chassis", FWTS_SMBIOS_CHASSIS_MAIN_SERVER
> > _CHASSIS },
> > + { "Expansion Chassis", FWTS_SMBIOS_CHASSIS_EXPANISO
> > N_CHASSIS },
> > + { "Sub Chassis", FWTS_SMBIOS_CHASSIS_SUB_CHASSIS },
> > + { "Bus Expansion Chassis",
> > FWTS_SMBIOS_CHASSIS_BUS_EXPANSION_CHASSIS },
> > + { "Peripheral Chassis", FWTS_SMBIOS_CHASSIS_PERIPHE
> > RAL_CHASSIS },
> > + { "Raid Chassis", FWTS_SMBIOS_CHASSIS_RAID_CHASSIS
> > },
> > + { "Rack Mount Chassis", FWTS_SMBIOS_CHASSIS_RACK_MO
> > UNT_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_EN
> > CLOSURE },
> > + { "Tablet", FWTS_SMBIOS_CHASSIS_TABLET },
> > + { "Convertible", FWTS_SMBIOS_CHASSIS_CONVERTIBLE },
> > + { "Detachable", FWTS_SMBIOS_CHASSIS_DETACHA
> > BLE },
> > +};
> > +
> > +/* 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.
>
Thank you very much for testing it on your platform. Appreciate it.
As per earlier discussion, I think Leif or someone mentioned that "/sys
is definitely the preferable method to access both ACPI and SMBIOS, and
the only one that should be used on any ARM system."
Hence, I have removed mmap /dev/mem, this may be reason behind failure
you are getting in your platform. I will recheck with the kernel folks
and based on their inputs, we can add back /dev/mem support or not.
More information about the fwts-devel
mailing list