[PATCH 2/4] opal: mem_info: Add OPAL MEM Info validation
Deb McLemore
debmc at linux.vnet.ibm.com
Fri Nov 11 04:02:08 UTC 2016
Check that the MEM 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/mem_info.c | 448 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 451 insertions(+)
create mode 100644 src/opal/mem_info.c
diff --git a/src/Makefile.am b/src/Makefile.am
index b2604e3..9c2975b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -24,6 +24,8 @@ if HAVE_LIBFDT
dt_tests = \
devicetree/dt_base/dt_base.c \
devicetree/dt_sysinfo/dt_sysinfo.c
+mem_tests = \
+ opal/mem_info.c
endif
if HAVE_LIBFDT
@@ -158,6 +160,7 @@ fwts_SOURCES = main.c \
uefi/esrtdump/esrtdump.c \
uefi/esrt/esrt.c \
$(pci_tests) \
+ $(mem_tests) \
$(dt_tests)
fwts_LDFLAGS = -lm `pkg-config --libs glib-2.0 gio-2.0`
diff --git a/src/opal/mem_info.c b/src/opal/mem_info.c
new file mode 100644
index 0000000..749b422
--- /dev/null
+++ b/src/opal/mem_info.c
@@ -0,0 +1,448 @@
+/*
+ * 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_dimm_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, "/memory-buffer");
+ 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 MEM 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 MEM 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 MEM 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 MEM Info",
+ "Property of \"%s\" for \"%s\" was not"
+ " able to be retrieved. Check the "
+ "installation for the MEM device "
+ "config for missing nodes in the device"
+ " tree if you expect MEM devices.",
+ property,
+ my_path);
+ }
+ } else {
+ failures ++;
+ fwts_log_nl(fw);
+ fwts_failed(fw, LOG_LEVEL_CRITICAL,
+ "OPAL MEM Info",
+ "Failed to get node for memory-buffer"
+ " \"%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 MEM 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 process_dimm(fwts_framework *fw,
+ char *my_string,
+ char *my_dir)
+{
+ int count, i, failures = 0;
+ struct dirent **namelist;
+ bool found = false;
+
+ count = scandir(my_dir, &namelist, NULL, alphasort);
+ if (count < 0) {
+ fwts_log_nl(fw);
+ fwts_failed(fw, LOG_LEVEL_CRITICAL,
+ "OPAL MEM Info",
+ "Scan for MEM devices in '%s' is unable to find any "
+ "candidates. Check the installation "
+ "for the MEM device config for missing nodes"
+ " in the device tree if you expect MEM devices.",
+ my_dir);
+ return FWTS_ERROR;
+ }
+
+ for (i = 0; i < count; i++) {
+ struct dirent *dirent;
+ char *my_buffer;
+ char *my_path;
+
+ dirent = namelist[i];
+
+ if (dirent->d_name[0] == '.' ||
+ asprintf(&my_buffer,
+ "%s",
+ dirent->d_name) < 0) {
+ /* asprintf must be last condition so when it */
+ /* evaluates my_buffer gets allocated */
+ free(namelist[i]);
+ continue;
+ }
+
+ if (strstr(my_buffer, my_string)) {
+ found = true;
+ if (asprintf(&my_path,
+ "%s/%s",
+ my_dir,
+ my_buffer) < 0 ) {
+ fwts_log_nl(fw);
+ fwts_failed(fw, LOG_LEVEL_CRITICAL,
+ "OPAL MEM Info",
+ "Internal"
+ " processing problem at"
+ " my_link \"%s\", please"
+ " check the system for"
+ " setup issues.",
+ my_buffer);
+ free(my_buffer);
+ free(namelist[i]);
+ continue;
+ }
+ if (get_dimm_property(fw, my_path, false,
+ DT_PROPERTY_OPAL_SLOT_LOC)) {
+ failures ++;
+ }
+
+ if (get_dimm_property(fw, my_path, false,
+ DT_PROPERTY_OPAL_PART_NUM)) {
+ failures ++;
+ }
+
+ if (get_dimm_property(fw, my_path, false,
+ DT_PROPERTY_OPAL_SERIAL_NUM)) {
+ failures ++;
+ }
+
+ if (get_dimm_property(fw, my_path, true,
+ DT_PROPERTY_OPAL_MANUFACTURER_ID)) {
+ failures ++;
+ }
+
+ if (get_dimm_property(fw, my_path, false,
+ DT_PROPERTY_OPAL_STATUS)) {
+ failures ++;
+ }
+ free(my_buffer);
+ free(namelist[i]);
+ }
+ }
+ free(namelist);
+
+ if (!found) {
+ failures ++;
+ fwts_log_nl(fw);
+ fwts_failed(fw, LOG_LEVEL_CRITICAL,
+ "OPAL MEM Info",
+ "No MEM devices (memory-buffer) were found"
+ " in \"%s\". Check the system for setup"
+ " issues.",
+ DT_FS_PATH);
+ }
+
+ if (failures) {
+ return FWTS_ERROR;
+ } else {
+ return FWTS_OK;
+ }
+}
+
+static int process_mba(fwts_framework *fw,
+ char *my_string,
+ char *my_dir)
+{
+ int count, i, failures = 0;
+ struct dirent **namelist;
+ bool found = false;
+
+ count = scandir(my_dir, &namelist, NULL, alphasort);
+ if (count < 0) {
+ fwts_log_nl(fw);
+ fwts_failed(fw, LOG_LEVEL_CRITICAL,
+ "OPAL MEM Info",
+ "Scan for MEM devices for \"%s\" in \"%s\" is"
+ " unable to find any candidates. Check the"
+ " installation for the MEM device config for missing"
+ " nodes in the device tree if you expect MEM devices.",
+ my_string,
+ my_dir);
+ return FWTS_ERROR;
+ }
+
+ for (i = 0; i < count; i++) {
+ struct dirent *dirent;
+ char *my_buffer;
+ char *my_path;
+
+ dirent = namelist[i];
+
+ if (dirent->d_name[0] == '.' ||
+ asprintf(&my_buffer,
+ "%s",
+ dirent->d_name) < 0) {
+ /* asprintf must be last condition so when it */
+ /* evaluates my_buffer gets allocated */
+ free(namelist[i]);
+ continue;
+ }
+
+ if (strstr(my_buffer, my_string)) {
+ found = true;
+ if (asprintf(&my_path,
+ "%s/%s",
+ my_dir,
+ my_buffer) < 0 ) {
+ fwts_log_nl(fw);
+ fwts_failed(fw, LOG_LEVEL_CRITICAL,
+ "OPAL MEM Info",
+ "Internal"
+ " processing problem at"
+ " my_link \"%s\", please"
+ " check the system for"
+ " setup issues.",
+ my_buffer);
+ free(my_buffer);
+ free(namelist[i]);
+ continue;
+ }
+ if (process_dimm(fw, "dimm", my_path)) {
+ failures ++;
+ }
+ free(my_buffer);
+ free(namelist[i]);
+ }
+ }
+ free(namelist);
+
+ if (!found) {
+ fwts_log_nl(fw);
+ fwts_failed(fw, LOG_LEVEL_CRITICAL,
+ "OPAL MEM Info",
+ "Failed to find any device"
+ " tree nodes for mba at X from \"%s\"."
+ " Check the installation "
+ "for the MEM device config for missing nodes"
+ " in the device tree if you expect MEM devices.",
+ my_dir);
+ }
+
+ if ((!found) || (failures)) {
+ return FWTS_ERROR;
+ } else {
+ return FWTS_OK;
+ }
+
+}
+
+static int get_linux_mem_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_log_nl(fw);
+ fwts_failed(fw, LOG_LEVEL_CRITICAL,
+ "OPAL MEM Info",
+ "Scan for MEM devices in '%s' is unable to find any "
+ "candidates. Check the installation "
+ "for the MEM device config for missing nodes"
+ " in the device tree if you expect MEM devices.",
+ DT_FS_PATH);
+ return FWTS_ERROR;
+ }
+
+ fwts_log_nl(fw);
+ fwts_log_info(fw, "STARTING checks of MEM devices");
+
+ for (i = 0; i < count; i++) {
+ struct dirent *dirent;
+ char *mem_buffer;
+ char *mba_path;
+
+ dirent = namelist[i];
+
+ if (dirent->d_name[0] == '.' ||
+ asprintf(&mem_buffer,
+ "%s",
+ dirent->d_name) < 0) {
+ /* asprintf must be last condition so when it */
+ /* evaluates mem_buffer gets allocated */
+ free(namelist[i]);
+ continue;
+ }
+
+ if (strstr(mem_buffer, "memory-buffer")) {
+ found = true;
+ if (asprintf(&mba_path,
+ "%s/%s",
+ DT_FS_PATH,
+ mem_buffer) < 0 ) {
+ fwts_log_nl(fw);
+ fwts_failed(fw, LOG_LEVEL_CRITICAL,
+ "OPAL MEM Info",
+ "Internal"
+ " processing problem at"
+ " mem_buffer \"%s\", please"
+ " check the system for"
+ " setup issues.",
+ mem_buffer);
+ free(mem_buffer);
+ free(namelist[i]);
+ continue;
+ }
+ if (process_mba(fw, "mba", mba_path)) {
+ failures ++;
+ }
+ free(mem_buffer);
+ free(namelist[i]);
+ }
+ }
+ free(namelist);
+
+ fwts_log_nl(fw);
+ fwts_log_info(fw, "ENDING checks of MEM devices");
+ fwts_log_nl(fw);
+
+ if (!found) {
+ failures ++;
+ fwts_failed(fw, LOG_LEVEL_CRITICAL,
+ "OPAL MEM Info",
+ "No MEM devices (memory-buffer 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 mem_info_test1(fwts_framework *fw)
+{
+
+ if (get_linux_mem_devices(fw)) {
+
+ /* errors logged earlier */
+ return FWTS_ERROR;
+ } else {
+ return FWTS_OK;
+ }
+}
+
+static int mem_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 PCI Info"
+ " checks.");
+ return FWTS_SKIP;
+ } else {
+ return FWTS_OK;
+ }
+}
+
+static fwts_framework_minor_test mem_info_tests[] = {
+ { mem_info_test1, "OPAL MEM Info" },
+ { NULL, NULL }
+};
+
+static fwts_framework_ops mem_info_ops = {
+ .description = "OPAL MEM Info",
+ .init = mem_info_init,
+ .minor_tests = mem_info_tests
+};
+
+FWTS_REGISTER_FEATURES("mem_info", &mem_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