ACK: [PATCH 2/4] opal: mem_info: Add OPAL MEM Info validation
Colin Ian King
colin.king at canonical.com
Fri Nov 11 09:45:33 UTC 2016
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 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);
>
Acked-by: Colin Ian King <colin.king at canonical.com>
More information about the fwts-devel
mailing list