Message ID | 1478836928-8761-1-git-send-email-debmc@linux.vnet.ibm.com |
---|---|
State | Accepted |
Headers | show |
On 11/11/16 04:02, Deb McLemore wrote: > Check that the MEM devices are properly setup in the device tree. > > Signed-off-by: Deb McLemore <debmc@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@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@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); > Acked-by: Colin Ian King <colin.king@canonical.com>
On 2016-11-10 08:02 PM, Deb McLemore wrote: > Check that the MEM devices are properly setup in the device tree. > > Signed-off-by: Deb McLemore <debmc@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@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@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); > Acked-by: Alex Hung <alex.hung@canonical.com>
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@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@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);
Check that the MEM devices are properly setup in the device tree. Signed-off-by: Deb McLemore <debmc@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