Message ID | 1472580896-12246-1-git-send-email-debmc@linux.vnet.ibm.com |
---|---|
State | Accepted |
Headers | show |
On 30/08/16 19:14, Deb McLemore wrote: > Check that the MTD system device for OPAL is properly setup. > > Signed-off-by: Deb McLemore <debmc@linux.vnet.ibm.com> > --- > configure.ac | 2 + > src/Makefile.am | 1 + > src/opal/mtd_info.c | 381 ++++++++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 384 insertions(+) > create mode 100644 src/opal/mtd_info.c > > diff --git a/configure.ac b/configure.ac > index e3e7512..042d45b 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -64,7 +64,9 @@ > AC_CHECK_HEADERS([glib.h]) > AC_CHECK_HEADERS([gio/gio.h]) > AC_CHECK_HEADERS([asm/opal-prd.h]) > + AC_CHECK_HEADERS([mtd/mtd-abi.h]) > AM_CONDITIONAL([HAVE_ASM_OPAL_PRD_H], [test "x$ac_cv_header_asm_opal_prd_h" = "xyes"]) > + AM_CONDITIONAL([HAVE_MTD_ABI_H], [test "x$ac_cv_header_mtd_abi_h" = "xyes"]) > #AC_CHECK_LIB(pcre, pcre_compile) > AC_SEARCH_LIBS([fdt_check_header], [fdt], [ > AC_DEFINE([HAVE_LIBFDT], [1], [Define if we have libfdt]) > diff --git a/src/Makefile.am b/src/Makefile.am > index 137a429..eeef7a8 100644 > --- a/src/Makefile.am > +++ b/src/Makefile.am > @@ -134,6 +134,7 @@ fwts_SOURCES = main.c \ > kernel/olog/olog.c \ > kernel/oops/oops.c \ > kernel/version/version.c \ > + opal/mtd_info.c \ > opal/prd_info.c \ > pci/aspm/aspm.c \ > pci/crs/crs.c \ > diff --git a/src/opal/mtd_info.c b/src/opal/mtd_info.c > new file mode 100644 > index 0000000..bf1de03 > --- /dev/null > +++ b/src/opal/mtd_info.c > @@ -0,0 +1,381 @@ > +/* > + * 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" > + > +#ifdef HAVE_MTD_MTD_ABI_H > +#include <mtd/mtd-abi.h> > +#endif > + > +#ifdef HAVE_LIBFDT > +#include <libfdt.h> > +#endif > + > +#define FDT_FLASH_PATH "/proc/device-tree/chosen/ibm,system-flash" > +#define SYSFS_MTD_PATH "/sys/class/mtd" > + > +bool mtd_present(int fwts_mtd_flags, char *mtd_devnode) > +{ > + return !access(mtd_devnode, fwts_mtd_flags); > +} > + > +int mtd_hdr_query(fwts_framework *fw, char *mtd_devnode) { > + > + /* snippet from skiboot libflash/ffs.h */ > + struct ffs_hdr { > + char magic[8]; > + }; > + int fd = 0; > + ssize_t bytes_read = 0; > + struct ffs_hdr mtd_hdr; > + > + if ((fd = open(mtd_devnode, O_RDONLY)) < 0) { > + fwts_failed(fw, LOG_LEVEL_CRITICAL, "OPAL MTD Info", > + "Cannot get data from MTD device '%s'.", > + mtd_devnode); > + return FWTS_ERROR; > + } > + > + bytes_read = read(fd, &mtd_hdr, sizeof(mtd_hdr) ); > + > + if (bytes_read >= 4) { > + /* FFS_MAGIC from skiboot libflash/ffs.h */ > + if (strncmp(mtd_hdr.magic, "PART", 4) == 0) { > + fwts_log_info(fw, > + "MTD device '%s' header eye-catcher 'PART'" > + " verified.\n", mtd_devnode); > + } else { > + fwts_failed(fw, LOG_LEVEL_CRITICAL, > + "OPAL MTD Info", > + "MTD device '%s' header eye-catcher 'PART'" > + " not able to be" > + " verified. Check the system setup.\n", > + mtd_devnode); > + close(fd); > + return FWTS_ERROR; > + } > + } else { > + fwts_failed(fw, LOG_LEVEL_CRITICAL, "OPAL MTD Info", > + "MTD device '%s' header was unable to be read." > + " Cannot validate the integrity of the MTD." > + " Check the system setup.\n", > + mtd_devnode); > + close(fd); > + return FWTS_ERROR; > + } > + > + close(fd); > + return FWTS_OK; > +} > + > +int mtd_dev_query(fwts_framework *fw, char *mtd_devnode) > +{ > + > +#ifdef HAVE_MTD_MTD_ABI_H > + int fd = 0; > + int fwts_mtd_flags = 0; > + struct mtd_info_user mtd_info; > +#endif > + > + if (!mtd_present(R_OK | W_OK, mtd_devnode)) { > + fwts_failed(fw, LOG_LEVEL_CRITICAL, "OPAL MTD Info", > + "Cannot read or write to MTD device '%s'" > + " check your user privileges.", mtd_devnode); > + return FWTS_ERROR; > + } else { > + fwts_log_info(fw, "MTD device '%s' is verified" > + " and %s is read/write in the file system, the" > + " MTD device itself will be checked later," > + " see MTD Flags.", > + mtd_devnode, mtd_devnode); > + } > + > +#ifdef HAVE_MTD_MTD_ABI_H > + if (strstr(mtd_devnode, "ro")) { > + fwts_mtd_flags = O_RDONLY; > + } else { > + fwts_mtd_flags = O_RDWR; > + } > + > + if ((fd = open(mtd_devnode, fwts_mtd_flags)) < 0) { > + fwts_failed(fw, LOG_LEVEL_CRITICAL, "OPAL MTD Info", > + "Cannot get data from '%s'" > + " device interface.", mtd_devnode); > + return FWTS_ERROR; > + } > + > + if (ioctl(fd, MEMGETINFO, &mtd_info)) { > + close(fd); > + fwts_failed(fw, LOG_LEVEL_CRITICAL, "OPAL MTD Info", > + "Cannot get data from '%s'" > + " device interface.", mtd_devnode); > + return FWTS_ERROR; > + } else { > + fwts_log_info(fw, "MTD device '%s' attributes follow:" > + " MTD Type=%u (3=MTD_NORFLASH)," > + " MTD Flags=%u (1024=MTD_WRITEABLE)," > + " MTD total size=%u bytes," > + " MTD erase size=%u bytes," > + " MTD write size=%u," > + " MTD oob size=%u", > + mtd_devnode, > + mtd_info.type, > + mtd_info.flags, > + mtd_info.size, > + mtd_info.erasesize, > + mtd_info.writesize, > + mtd_info.oobsize); > + close(fd); > + return FWTS_OK; > + } > +} > +#else > + fwts_failed(fw, LOG_LEVEL_CRITICAL, > + "OPAL MTD Info", > + "MTD Info unable to be retrieved" > + " for '%s' due to lack of " > + "mtd-abi.h, check your " > + "configuration and rebuild.", > + mtd_devnode); > + return FWTS_ERROR; > +} > +#endif > + > +static int mtd_info_test1(fwts_framework *fw) > +{ > + char fdt_node_path[PATH_MAX]; > + int count, i, fd; > + ssize_t bytes = 0, bytes_read = 0; > + struct dirent **namelist; > + > + fd = open(FDT_FLASH_PATH, O_RDONLY); > + if (fd < 0) { > + fwts_failed(fw, LOG_LEVEL_CRITICAL, > + "OPAL MTD Info", > + "Failed to open the path %s." > + " Check the installation" > + " for the path %s.\n", > + FDT_FLASH_PATH, > + FDT_FLASH_PATH); > + return FWTS_ERROR; > + } > + bytes_read = read(fd, fdt_node_path, sizeof(fdt_node_path)); > + if (bytes_read < 0) { > + fwts_failed(fw, LOG_LEVEL_CRITICAL, > + "OPAL MTD Info", > + "Failed to get the FDT info." > + " Check the installation " > + "for the path %s.\n", > + FDT_FLASH_PATH); > + close(fd); > + return FWTS_ERROR; > + } > + close(fd); > + fwts_log_info(fw, "MTD Info validated FDT of '%s'.", > + fdt_node_path); > + > + count = scandir(SYSFS_MTD_PATH, &namelist, NULL, alphasort); > + if (count < 0) { > + fwts_failed(fw, LOG_LEVEL_CRITICAL, > + "OPAL MTD Info", > + "Scan for MTD '%s' unable to find any " > + "candidates. Check the installation " > + "for the MTD device config.", > + SYSFS_MTD_PATH); > + } > + > + bytes = 0; > + > + fwts_log_nl(fw); > + fwts_log_info(fw, "STARTING checks of MTD devices"); > + fwts_log_nl(fw); > + > + for (i = 0; i < count; i++) { > + struct dirent *dirent; > + char *sys_device_path; /* /sys/class/device/mtdx */ > + char *mtd_device_path; /* /dev/mtdx */ > + char *driver_path; > + char fdt_node_path_tmp[PATH_MAX]; > + char mtd_driver_path[PATH_MAX]; > + > + memset(fdt_node_path_tmp, 0, sizeof(fdt_node_path_tmp)); > + memset(mtd_driver_path, 0, sizeof(mtd_driver_path)); > + > + dirent = namelist[i]; > + > + if (dirent->d_name[0] == '.' || bytes || > + asprintf(&sys_device_path, > + "%s/%s/device/of_node", > + SYSFS_MTD_PATH, dirent->d_name) < 0) { > + /* asprintf must be last condition so when it */ > + /* evaluates sys_device_path gets allocated */ > + free(namelist[i]); > + continue; > + } > + > + bytes = readlink(sys_device_path, fdt_node_path_tmp, > + sizeof(fdt_node_path_tmp) - 1); > + free(sys_device_path); > + if (bytes < 0) { > + /* if mtd system flash does not have an FDT node */ > + /* just continue */ > + free(namelist[i]); > + /* reset the bytes to continue */ > + bytes = 0; > + continue; > + } > + fdt_node_path_tmp[bytes] = '\0'; > + > + if (strstr(fdt_node_path_tmp, fdt_node_path)) { > + bytes = asprintf(&mtd_device_path, "/dev/%s", > + dirent->d_name); > + if (bytes < 0) { > + free(namelist[i]); > + fwts_failed(fw, LOG_LEVEL_CRITICAL, > + "OPAL MTD Info", > + "Failed to get the device path." > + " Check the installation for the" > + " path '/dev/%s'.", > + dirent->d_name); > + continue; > + } > + mtd_device_path[bytes] = '\0'; > + bytes = 0; > + if (asprintf(&driver_path, > + "%s/%s/device/driver", > + SYSFS_MTD_PATH, dirent->d_name) < 0) { > + fwts_failed(fw, LOG_LEVEL_CRITICAL, > + "OPAL MTD Info", > + "Failed to get the MTD Path." > + " Check the installation " > + "for the path '%s/%s/device/driver'.", > + SYSFS_MTD_PATH, > + dirent->d_name); > + free(mtd_device_path); > + continue; > + } > + bytes = readlink(driver_path, mtd_driver_path, > + sizeof(mtd_driver_path) -1); > + if (bytes < 0) { > + fwts_failed(fw, LOG_LEVEL_CRITICAL, > + "OPAL MTD Info", > + "Failed to get the MTD drive path." > + " Check the installation for the " > + "path %s.", > + driver_path); > + free(mtd_device_path); > + free(driver_path); > + continue; > + } else { > + mtd_driver_path[bytes] = '\0'; > + bytes = 0; > + free(driver_path); > + } > + > + if (strstr(mtd_driver_path, "powernv_flash")) { > + if (!strstr(mtd_device_path, "ro")) { > + if (mtd_dev_query(fw, > + mtd_device_path)) { > + /* failures logged */ > + /* in subroutine */ > + free(mtd_device_path); > + continue; > + } > + if (mtd_hdr_query(fw, > + mtd_device_path)) { > + /* failures logged */ > + /* in subroutine */ > + free(mtd_device_path); > + continue; > + } > + fwts_log_nl(fw); > + } > + free(mtd_device_path); > + } > + } > + > + free(namelist[i]); > + } > + free(namelist); > + > + fwts_log_info(fw, "ENDING checks of MTD devices"); > + fwts_log_nl(fw); > + > + fwts_passed(fw, "OPAL MTD info passed."); > + > + return FWTS_OK; > +} > + > +static int mtd_info_init(fwts_framework *fw) > +{ > + if (fw->fdt) { > +#ifdef HAVE_LIBFDT > + int node; > + /* perform some FDT validation */ > + node = fdt_path_offset(fw->fdt, > + "/ibm,opal/nvram"); > + if (node >= 0) { > + if (!fdt_node_check_compatible(fw->fdt, node, > + "ibm,opal-nvram")) { > + fwts_log_info(fw, > + "MTD Info initialization validated" > + " FDT for 'ibm,opal-nvram'."); > + return FWTS_OK; > + } else { > + return FWTS_SKIP; > + } > + } > +#endif > + } else { > + fwts_log_info(fw, "The OPAL MTD device tree node is not" > + " able to be detected so skipping the mtd_info" > + " test. There may be tools missing such as" > + " libfdt-dev or dtc, check that the packages" > + " are installed and re-build if needed." > + " If this condition persists try running the" > + " dt_base test to further diagnose. If dt_base" > + " test is not available this is probably a" > + " setup problem."); > + return FWTS_SKIP; > + } > + > + /* only run test when fdt node is confirmed */ > + return FWTS_SKIP; > +} > + > +static fwts_framework_minor_test mtd_info_tests[] = { > + { mtd_info_test1, "OPAL MTD Info" }, > + { NULL, NULL } > +}; > + > +static fwts_framework_ops mtd_info_ops = { > + .description = "OPAL MTD Info", > + .init = mtd_info_init, > + .minor_tests = mtd_info_tests > +}; > + > +FWTS_REGISTER_FEATURES("mtd_info", &mtd_info_ops, FWTS_TEST_ANYTIME, > + FWTS_FLAG_BATCH | FWTS_FLAG_ROOT_PRIV, > + FWTS_FW_FEATURE_DEVICETREE); > Thanks Deb! Acked-by: Colin Ian King <colin.king@canonical.com>
On 08/31/2016 02:14 AM, Deb McLemore wrote: > Check that the MTD system device for OPAL is properly setup. > > Signed-off-by: Deb McLemore <debmc@linux.vnet.ibm.com> > --- > configure.ac | 2 + > src/Makefile.am | 1 + > src/opal/mtd_info.c | 381 ++++++++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 384 insertions(+) > create mode 100644 src/opal/mtd_info.c Acked-by: Alex Hung <alex.hung@canonical.com>
diff --git a/configure.ac b/configure.ac index e3e7512..042d45b 100644 --- a/configure.ac +++ b/configure.ac @@ -64,7 +64,9 @@ AC_CHECK_HEADERS([glib.h]) AC_CHECK_HEADERS([gio/gio.h]) AC_CHECK_HEADERS([asm/opal-prd.h]) + AC_CHECK_HEADERS([mtd/mtd-abi.h]) AM_CONDITIONAL([HAVE_ASM_OPAL_PRD_H], [test "x$ac_cv_header_asm_opal_prd_h" = "xyes"]) + AM_CONDITIONAL([HAVE_MTD_ABI_H], [test "x$ac_cv_header_mtd_abi_h" = "xyes"]) #AC_CHECK_LIB(pcre, pcre_compile) AC_SEARCH_LIBS([fdt_check_header], [fdt], [ AC_DEFINE([HAVE_LIBFDT], [1], [Define if we have libfdt]) diff --git a/src/Makefile.am b/src/Makefile.am index 137a429..eeef7a8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -134,6 +134,7 @@ fwts_SOURCES = main.c \ kernel/olog/olog.c \ kernel/oops/oops.c \ kernel/version/version.c \ + opal/mtd_info.c \ opal/prd_info.c \ pci/aspm/aspm.c \ pci/crs/crs.c \ diff --git a/src/opal/mtd_info.c b/src/opal/mtd_info.c new file mode 100644 index 0000000..bf1de03 --- /dev/null +++ b/src/opal/mtd_info.c @@ -0,0 +1,381 @@ +/* + * 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" + +#ifdef HAVE_MTD_MTD_ABI_H +#include <mtd/mtd-abi.h> +#endif + +#ifdef HAVE_LIBFDT +#include <libfdt.h> +#endif + +#define FDT_FLASH_PATH "/proc/device-tree/chosen/ibm,system-flash" +#define SYSFS_MTD_PATH "/sys/class/mtd" + +bool mtd_present(int fwts_mtd_flags, char *mtd_devnode) +{ + return !access(mtd_devnode, fwts_mtd_flags); +} + +int mtd_hdr_query(fwts_framework *fw, char *mtd_devnode) { + + /* snippet from skiboot libflash/ffs.h */ + struct ffs_hdr { + char magic[8]; + }; + int fd = 0; + ssize_t bytes_read = 0; + struct ffs_hdr mtd_hdr; + + if ((fd = open(mtd_devnode, O_RDONLY)) < 0) { + fwts_failed(fw, LOG_LEVEL_CRITICAL, "OPAL MTD Info", + "Cannot get data from MTD device '%s'.", + mtd_devnode); + return FWTS_ERROR; + } + + bytes_read = read(fd, &mtd_hdr, sizeof(mtd_hdr) ); + + if (bytes_read >= 4) { + /* FFS_MAGIC from skiboot libflash/ffs.h */ + if (strncmp(mtd_hdr.magic, "PART", 4) == 0) { + fwts_log_info(fw, + "MTD device '%s' header eye-catcher 'PART'" + " verified.\n", mtd_devnode); + } else { + fwts_failed(fw, LOG_LEVEL_CRITICAL, + "OPAL MTD Info", + "MTD device '%s' header eye-catcher 'PART'" + " not able to be" + " verified. Check the system setup.\n", + mtd_devnode); + close(fd); + return FWTS_ERROR; + } + } else { + fwts_failed(fw, LOG_LEVEL_CRITICAL, "OPAL MTD Info", + "MTD device '%s' header was unable to be read." + " Cannot validate the integrity of the MTD." + " Check the system setup.\n", + mtd_devnode); + close(fd); + return FWTS_ERROR; + } + + close(fd); + return FWTS_OK; +} + +int mtd_dev_query(fwts_framework *fw, char *mtd_devnode) +{ + +#ifdef HAVE_MTD_MTD_ABI_H + int fd = 0; + int fwts_mtd_flags = 0; + struct mtd_info_user mtd_info; +#endif + + if (!mtd_present(R_OK | W_OK, mtd_devnode)) { + fwts_failed(fw, LOG_LEVEL_CRITICAL, "OPAL MTD Info", + "Cannot read or write to MTD device '%s'" + " check your user privileges.", mtd_devnode); + return FWTS_ERROR; + } else { + fwts_log_info(fw, "MTD device '%s' is verified" + " and %s is read/write in the file system, the" + " MTD device itself will be checked later," + " see MTD Flags.", + mtd_devnode, mtd_devnode); + } + +#ifdef HAVE_MTD_MTD_ABI_H + if (strstr(mtd_devnode, "ro")) { + fwts_mtd_flags = O_RDONLY; + } else { + fwts_mtd_flags = O_RDWR; + } + + if ((fd = open(mtd_devnode, fwts_mtd_flags)) < 0) { + fwts_failed(fw, LOG_LEVEL_CRITICAL, "OPAL MTD Info", + "Cannot get data from '%s'" + " device interface.", mtd_devnode); + return FWTS_ERROR; + } + + if (ioctl(fd, MEMGETINFO, &mtd_info)) { + close(fd); + fwts_failed(fw, LOG_LEVEL_CRITICAL, "OPAL MTD Info", + "Cannot get data from '%s'" + " device interface.", mtd_devnode); + return FWTS_ERROR; + } else { + fwts_log_info(fw, "MTD device '%s' attributes follow:" + " MTD Type=%u (3=MTD_NORFLASH)," + " MTD Flags=%u (1024=MTD_WRITEABLE)," + " MTD total size=%u bytes," + " MTD erase size=%u bytes," + " MTD write size=%u," + " MTD oob size=%u", + mtd_devnode, + mtd_info.type, + mtd_info.flags, + mtd_info.size, + mtd_info.erasesize, + mtd_info.writesize, + mtd_info.oobsize); + close(fd); + return FWTS_OK; + } +} +#else + fwts_failed(fw, LOG_LEVEL_CRITICAL, + "OPAL MTD Info", + "MTD Info unable to be retrieved" + " for '%s' due to lack of " + "mtd-abi.h, check your " + "configuration and rebuild.", + mtd_devnode); + return FWTS_ERROR; +} +#endif + +static int mtd_info_test1(fwts_framework *fw) +{ + char fdt_node_path[PATH_MAX]; + int count, i, fd; + ssize_t bytes = 0, bytes_read = 0; + struct dirent **namelist; + + fd = open(FDT_FLASH_PATH, O_RDONLY); + if (fd < 0) { + fwts_failed(fw, LOG_LEVEL_CRITICAL, + "OPAL MTD Info", + "Failed to open the path %s." + " Check the installation" + " for the path %s.\n", + FDT_FLASH_PATH, + FDT_FLASH_PATH); + return FWTS_ERROR; + } + bytes_read = read(fd, fdt_node_path, sizeof(fdt_node_path)); + if (bytes_read < 0) { + fwts_failed(fw, LOG_LEVEL_CRITICAL, + "OPAL MTD Info", + "Failed to get the FDT info." + " Check the installation " + "for the path %s.\n", + FDT_FLASH_PATH); + close(fd); + return FWTS_ERROR; + } + close(fd); + fwts_log_info(fw, "MTD Info validated FDT of '%s'.", + fdt_node_path); + + count = scandir(SYSFS_MTD_PATH, &namelist, NULL, alphasort); + if (count < 0) { + fwts_failed(fw, LOG_LEVEL_CRITICAL, + "OPAL MTD Info", + "Scan for MTD '%s' unable to find any " + "candidates. Check the installation " + "for the MTD device config.", + SYSFS_MTD_PATH); + } + + bytes = 0; + + fwts_log_nl(fw); + fwts_log_info(fw, "STARTING checks of MTD devices"); + fwts_log_nl(fw); + + for (i = 0; i < count; i++) { + struct dirent *dirent; + char *sys_device_path; /* /sys/class/device/mtdx */ + char *mtd_device_path; /* /dev/mtdx */ + char *driver_path; + char fdt_node_path_tmp[PATH_MAX]; + char mtd_driver_path[PATH_MAX]; + + memset(fdt_node_path_tmp, 0, sizeof(fdt_node_path_tmp)); + memset(mtd_driver_path, 0, sizeof(mtd_driver_path)); + + dirent = namelist[i]; + + if (dirent->d_name[0] == '.' || bytes || + asprintf(&sys_device_path, + "%s/%s/device/of_node", + SYSFS_MTD_PATH, dirent->d_name) < 0) { + /* asprintf must be last condition so when it */ + /* evaluates sys_device_path gets allocated */ + free(namelist[i]); + continue; + } + + bytes = readlink(sys_device_path, fdt_node_path_tmp, + sizeof(fdt_node_path_tmp) - 1); + free(sys_device_path); + if (bytes < 0) { + /* if mtd system flash does not have an FDT node */ + /* just continue */ + free(namelist[i]); + /* reset the bytes to continue */ + bytes = 0; + continue; + } + fdt_node_path_tmp[bytes] = '\0'; + + if (strstr(fdt_node_path_tmp, fdt_node_path)) { + bytes = asprintf(&mtd_device_path, "/dev/%s", + dirent->d_name); + if (bytes < 0) { + free(namelist[i]); + fwts_failed(fw, LOG_LEVEL_CRITICAL, + "OPAL MTD Info", + "Failed to get the device path." + " Check the installation for the" + " path '/dev/%s'.", + dirent->d_name); + continue; + } + mtd_device_path[bytes] = '\0'; + bytes = 0; + if (asprintf(&driver_path, + "%s/%s/device/driver", + SYSFS_MTD_PATH, dirent->d_name) < 0) { + fwts_failed(fw, LOG_LEVEL_CRITICAL, + "OPAL MTD Info", + "Failed to get the MTD Path." + " Check the installation " + "for the path '%s/%s/device/driver'.", + SYSFS_MTD_PATH, + dirent->d_name); + free(mtd_device_path); + continue; + } + bytes = readlink(driver_path, mtd_driver_path, + sizeof(mtd_driver_path) -1); + if (bytes < 0) { + fwts_failed(fw, LOG_LEVEL_CRITICAL, + "OPAL MTD Info", + "Failed to get the MTD drive path." + " Check the installation for the " + "path %s.", + driver_path); + free(mtd_device_path); + free(driver_path); + continue; + } else { + mtd_driver_path[bytes] = '\0'; + bytes = 0; + free(driver_path); + } + + if (strstr(mtd_driver_path, "powernv_flash")) { + if (!strstr(mtd_device_path, "ro")) { + if (mtd_dev_query(fw, + mtd_device_path)) { + /* failures logged */ + /* in subroutine */ + free(mtd_device_path); + continue; + } + if (mtd_hdr_query(fw, + mtd_device_path)) { + /* failures logged */ + /* in subroutine */ + free(mtd_device_path); + continue; + } + fwts_log_nl(fw); + } + free(mtd_device_path); + } + } + + free(namelist[i]); + } + free(namelist); + + fwts_log_info(fw, "ENDING checks of MTD devices"); + fwts_log_nl(fw); + + fwts_passed(fw, "OPAL MTD info passed."); + + return FWTS_OK; +} + +static int mtd_info_init(fwts_framework *fw) +{ + if (fw->fdt) { +#ifdef HAVE_LIBFDT + int node; + /* perform some FDT validation */ + node = fdt_path_offset(fw->fdt, + "/ibm,opal/nvram"); + if (node >= 0) { + if (!fdt_node_check_compatible(fw->fdt, node, + "ibm,opal-nvram")) { + fwts_log_info(fw, + "MTD Info initialization validated" + " FDT for 'ibm,opal-nvram'."); + return FWTS_OK; + } else { + return FWTS_SKIP; + } + } +#endif + } else { + fwts_log_info(fw, "The OPAL MTD device tree node is not" + " able to be detected so skipping the mtd_info" + " test. There may be tools missing such as" + " libfdt-dev or dtc, check that the packages" + " are installed and re-build if needed." + " If this condition persists try running the" + " dt_base test to further diagnose. If dt_base" + " test is not available this is probably a" + " setup problem."); + return FWTS_SKIP; + } + + /* only run test when fdt node is confirmed */ + return FWTS_SKIP; +} + +static fwts_framework_minor_test mtd_info_tests[] = { + { mtd_info_test1, "OPAL MTD Info" }, + { NULL, NULL } +}; + +static fwts_framework_ops mtd_info_ops = { + .description = "OPAL MTD Info", + .init = mtd_info_init, + .minor_tests = mtd_info_tests +}; + +FWTS_REGISTER_FEATURES("mtd_info", &mtd_info_ops, FWTS_TEST_ANYTIME, + FWTS_FLAG_BATCH | FWTS_FLAG_ROOT_PRIV, + FWTS_FW_FEATURE_DEVICETREE);
Check that the MTD system device for OPAL is properly setup. Signed-off-by: Deb McLemore <debmc@linux.vnet.ibm.com> --- configure.ac | 2 + src/Makefile.am | 1 + src/opal/mtd_info.c | 381 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 384 insertions(+) create mode 100644 src/opal/mtd_info.c