[PATCH] [V2] opal: mtd: Add OPAL MTD Validation

Deb McLemore debmc at linux.vnet.ibm.com
Tue Aug 30 17:36:47 UTC 2016


Hi Colin,

See replies in line and some follow-up clarifications.

On 08/30/2016 12:24 PM, Colin Ian King wrote:
> Thanks deb,
>
> I've re-reviewed the patch and it builds OK w/o any static analysis
> issues too.  However, I have just a couple of minor nit-picks;
> apologies, I should have spotted those on the first review.
>
> Colin
>
> On 30/08/16 17:49, Deb McLemore wrote:
>> Check that the MTD system device for OPAL is properly setup.
>>
>> Signed-off-by: Deb McLemore <debmc at linux.vnet.ibm.com>
>> ---
>>   configure.ac        |   2 +
>>   src/Makefile.am     |   1 +
>>   src/opal/mtd_info.c | 379 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 382 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..edb25fa
>> --- /dev/null
>> +++ b/src/opal/mtd_info.c
>> @@ -0,0 +1,379 @@
>> +/*
>> + * 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));
> do we expect bytes_read to be sizeof(fdt_node_path) if successful too?
On success, bytes_read will be the number of bytes actually read
>> +	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 */
> minor nitpick, can the two comments above be indented by 1 tab
Done
>
>> +			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);
> minor nitpick - the above has the indentation from what I can tell.
Can you clarify this comment, not sure what is requested ?
>
>> +				}
>> +				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);
>>

-- 
==========================================
Deb McLemore
IBM OpenPower - IBM Systems
(512) 286 9980

debmc at us.ibm.com
debmc at linux.vnet.ibm.com - (plain text)
==========================================




More information about the fwts-devel mailing list