[PATCH 3/4] opal: cpu_info: Add OPAL CPU Info validation

Deb McLemore debmc at linux.vnet.ibm.com
Fri Nov 11 04:02:36 UTC 2016


Check that the CPU devices are properly setup in the device tree.

Signed-off-by: Deb McLemore <debmc at linux.vnet.ibm.com>
---
 src/Makefile.am     |   3 +
 src/opal/cpu_info.c | 276 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 279 insertions(+)
 create mode 100644 src/opal/cpu_info.c

diff --git a/src/Makefile.am b/src/Makefile.am
index 9c2975b..c1eb285 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -26,6 +26,8 @@ dt_tests = \
 	devicetree/dt_sysinfo/dt_sysinfo.c
 mem_tests = \
 	opal/mem_info.c
+cpu_tests = \
+	opal/cpu_info.c
 endif
 
 if HAVE_LIBFDT
@@ -161,6 +163,7 @@ fwts_SOURCES = main.c 				\
 	uefi/esrt/esrt.c			\
 	$(pci_tests)				\
 	$(mem_tests)				\
+	$(cpu_tests)				\
 	$(dt_tests)
 
 fwts_LDFLAGS = -lm `pkg-config --libs glib-2.0 gio-2.0`
diff --git a/src/opal/cpu_info.c b/src/opal/cpu_info.c
new file mode 100644
index 0000000..9953c90
--- /dev/null
+++ b/src/opal/cpu_info.c
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2010-2016 Canonical
+ * Some of this work - Copyright (C) 2016 IBM
+ *
+ * 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.
+ *
+ */
+
+#define _GNU_SOURCE /* added for asprintf */
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+
+#include "fwts.h"
+
+#include <libfdt.h>
+
+static int get_xscom_property(fwts_framework *fw,
+			char *my_path,
+			bool hex,
+			char *property)
+{
+	int node, prop_len, failures = 0;
+	const char *prop_buf;
+	char *prop_string = NULL;
+
+	prop_string = strstr(my_path, "/xscom");
+	if (prop_string) {
+		node = fdt_path_offset(fw->fdt, prop_string);
+		if (node >= 0) {
+			prop_buf = fdt_getprop(fw->fdt, node,
+					property,
+					&prop_len);
+			if ((prop_len > 0) && (prop_buf)) {
+				fwts_log_nl(fw);
+				if ((hex) && (prop_len == 4)) {
+					fwts_passed(fw,
+						"OPAL CPU Info Property of"
+						"\"%s\" for \"%s\" is "
+						"\"0x%02X%02X%02X%02X\".",
+						property,
+						my_path,
+						prop_buf[0],
+						prop_buf[1],
+						prop_buf[2],
+						prop_buf[3]);
+				} else if (!hex) {
+					if (check_property_printable(fw,
+						property,
+						prop_buf,
+						prop_len)) {
+							failures ++;
+					}
+					fwts_passed(fw,
+						"OPAL CPU Info Property of"
+						" \"%s\" for \"%s\" "
+						"is \"%s\".",
+						property,
+						my_path,
+						prop_buf);
+				} else {
+					failures ++;
+					fwts_log_nl(fw);
+					fwts_failed(fw,
+						LOG_LEVEL_CRITICAL,
+						"OPAL CPU Info",
+						"Property of "
+						"\"%s\" for \"%s\" is not"
+						" properly formatted."
+						" Check your installation"
+						" for proper device tree "
+						"nodes.",
+						property,
+						my_path);
+				}
+			} else {
+				failures ++;
+				fwts_log_nl(fw);
+				fwts_failed(fw,
+					LOG_LEVEL_CRITICAL,
+					"OPAL CPU Info",
+					"Property of \"%s\" for \"%s\" was"
+					" not able to be retrieved. Check the"
+					" installation for the CPU device"
+					" config for missing nodes in the"
+					" device tree if you expect CPU"
+					" devices.",
+					property,
+					my_path);
+			}
+		} else {
+			failures ++;
+			fwts_log_nl(fw);
+			fwts_failed(fw, LOG_LEVEL_CRITICAL,
+				"OPAL CPU Info",
+				"Failed to get node for xscom"
+				" \"%s/%s\", please check the system for"
+				" setup issues.",
+				my_path, property);
+		}
+	} else {
+		failures ++;
+		fwts_log_nl(fw);
+		fwts_failed(fw, LOG_LEVEL_CRITICAL,
+			"OPAL CPU Info",
+			"Internal processing problem at strstr"
+			" my_path of \"%s\" for \"%s\", please check the"
+			" system for setup issues.",
+			my_path,
+			property);
+	}
+	if (failures) {
+		return FWTS_ERROR;
+	} else {
+		return FWTS_OK;
+	}
+}
+
+static int get_linux_xscom_devices(fwts_framework *fw)
+{
+	int count, i, failures = 0;
+	struct dirent **namelist;
+	bool found = false;
+
+	count = scandir(DT_FS_PATH, &namelist, NULL, alphasort);
+	if (count < 0) {
+		fwts_failed(fw, LOG_LEVEL_CRITICAL,
+			"OPAL CPU Info",
+			"Scan for CPU devices in '%s' is unable to find any"
+			" candidates. Check the installation for the CPU"
+			" device config for missing nodes in the device tree"
+			" (xscom at X) if you expect CPU devices.",
+			DT_FS_PATH);
+		return FWTS_ERROR;
+	}
+
+	fwts_log_nl(fw);
+	fwts_log_info(fw, "STARTING checks of CPU'S");
+
+	for (i = 0; i < count; i++) {
+		struct dirent *dirent;
+		char *cpus;
+		char *xscom_path;
+
+		dirent = namelist[i];
+
+		if (dirent->d_name[0] == '.' ||
+			asprintf(&cpus,
+				"%s",
+				dirent->d_name) < 0) {
+			/* asprintf must be last condition so when it */
+			/* evaluates cpus gets allocated */
+			free(namelist[i]);
+			continue;
+		}
+
+		if (strstr(cpus, "xscom")) {
+			found = true;
+			if (asprintf(&xscom_path,
+				"%s/%s",
+				DT_FS_PATH,
+				cpus) < 0 ) {
+				fwts_log_nl(fw);
+				fwts_failed(fw, LOG_LEVEL_CRITICAL,
+					"OPAL CPU Info",
+					"Internal processing problem at"
+					" cpus \"%s\", please"
+					" check the system for"
+					" setup issues.",
+					cpus);
+				free(cpus);
+				free(namelist[i]);
+				continue;
+			}
+			if (get_xscom_property(fw, xscom_path, false,
+						DT_PROPERTY_OPAL_SLOT_LOC)) {
+				failures ++;
+			}
+
+			if (get_xscom_property(fw, xscom_path, false,
+						DT_PROPERTY_OPAL_PART_NUM)) {
+				failures ++;
+			}
+
+			if (get_xscom_property(fw, xscom_path, false,
+						DT_PROPERTY_OPAL_SERIAL_NUM)) {
+				failures ++;
+			}
+
+			if (get_xscom_property(fw, xscom_path, false,
+						DT_PROPERTY_OPAL_VENDOR)) {
+				failures ++;
+			}
+
+			if (get_xscom_property(fw, xscom_path, false,
+						DT_PROPERTY_OPAL_BOARD_INFO)) {
+				failures ++;
+			}
+			fwts_log_nl(fw);
+			free(cpus);
+			free(namelist[i]);
+		}
+	}
+	free(namelist);
+
+	fwts_log_nl(fw);
+	fwts_log_info(fw, "ENDING checks of CPU's");
+	fwts_log_nl(fw);
+
+	if (!found) {
+		failures ++;
+		fwts_failed(fw, LOG_LEVEL_CRITICAL,
+			"OPAL CPU Info",
+			"No CPU devices (xscom at X) were found in \"%s\"."
+			" Check the system for setup issues.",
+			DT_FS_PATH);
+	}
+
+	if (failures) {
+		return FWTS_ERROR;
+	} else {
+		return FWTS_OK;
+	}
+
+}
+
+static int cpu_info_test1(fwts_framework *fw)
+{
+	if (get_linux_xscom_devices(fw)) {
+
+		/* errors logged earlier */
+		return FWTS_ERROR;
+	} else {
+		return FWTS_OK;
+	}
+}
+
+static int cpu_info_init(fwts_framework *fw)
+{
+	if (fw->firmware_type != FWTS_FIRMWARE_OPAL) {
+		fwts_skipped(fw,
+			"The firmware type detected was not set"
+			" to OPAL so skipping the OPAL CPU Info"
+			" checks.");
+		return FWTS_SKIP;
+	} else {
+		return FWTS_OK;
+	}
+}
+
+static fwts_framework_minor_test cpu_info_tests[] = {
+	{ cpu_info_test1, "OPAL CPU Info" },
+	{ NULL, NULL }
+};
+
+static fwts_framework_ops cpu_info_ops = {
+	.description = "OPAL CPU Info",
+	.init        = cpu_info_init,
+	.minor_tests = cpu_info_tests
+};
+
+FWTS_REGISTER_FEATURES("cpu_info", &cpu_info_ops, FWTS_TEST_ANYTIME,
+		FWTS_FLAG_BATCH | FWTS_FLAG_ROOT_PRIV,
+		FWTS_FW_FEATURE_DEVICETREE);
-- 
2.7.4




More information about the fwts-devel mailing list