diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/Makefile | 1 | ||||
| -rw-r--r-- | lib/fdtdec_test.c | 226 | 
2 files changed, 227 insertions, 0 deletions
| diff --git a/lib/Makefile b/lib/Makefile index 4b5734a21..a0fec60a1 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -40,6 +40,7 @@ COBJS-y += crc32.o  COBJS-y += display_options.o  COBJS-y += errno.o  COBJS-$(CONFIG_OF_CONTROL) += fdtdec.o +COBJS-$(CONFIG_TEST_FDTDEC) += fdtdec_test.o  COBJS-$(CONFIG_GZIP) += gunzip.o  COBJS-y += hashtable.o  COBJS-$(CONFIG_LMB) += lmb.o diff --git a/lib/fdtdec_test.c b/lib/fdtdec_test.c new file mode 100644 index 000000000..497be8e3f --- /dev/null +++ b/lib/fdtdec_test.c @@ -0,0 +1,226 @@ +/* + * Some very basic tests for fdtdec, accessed through test_fdtdec command. + * They are easiest to use with sandbox. + * + * Copyright (c) 2011 The Chromium OS Authors. + * See file CREDITS for list of people who contributed to this + * project. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <fdtdec.h> +#include <libfdt.h> +#include <malloc.h> +#include <os.h> + +/* The size of our test fdt blob */ +#define FDT_SIZE	(16 * 1024) + +/** + * Check if an operation failed, and if so, print an error + * + * @param oper_name	Name of operation + * @param err		Error code to check + * + * @return 0 if ok, -1 if there was an error + */ +static int fdt_checkerr(const char *oper_name, int err) +{ +	if (err) { +		printf("%s: %s: %s\n", __func__, oper_name, fdt_strerror(err)); +		return -1; +	} + +	return 0; +} + +/** + * Check the result of an operation and if incorrect, print an error + * + * @param oper_name	Name of operation + * @param expected	Expected value + * @param value		Actual value + * + * @return 0 if ok, -1 if there was an error + */ +static int checkval(const char *oper_name, int expected, int value) +{ +	if (expected != value) { +		printf("%s: %s: expected %d, but returned %d\n", __func__, +		       oper_name, expected, value); +		return -1; +	} + +	return 0; +} + +#define CHECK(op)	if (fdt_checkerr(#op, op)) return -1 +#define CHECKVAL(op, expected)	\ +	if (checkval(#op, expected, op)) \ +		return -1 +#define CHECKOK(op)	CHECKVAL(op, 0) + +/* maximum number of nodes / aliases to generate */ +#define MAX_NODES	20 + +/* + * Make a test fdt + * + * @param fdt		Device tree pointer + * @param size		Size of device tree blob + * @param aliases	Specifies alias assignments. Format is a list of items + *			separated by space. Items are #a where + *				# is the alias number + *				a is the node to point to + * @param nodes		Specifies nodes to generate (a=0, b=1), upper case + *			means to create a disabled node + */ +static int make_fdt(void *fdt, int size, const char *aliases, +		    const char *nodes) +{ +	char name[20], value[20]; +	const char *s; +	int fd; + +	CHECK(fdt_create(fdt, size)); +	CHECK(fdt_finish_reservemap(fdt)); +	CHECK(fdt_begin_node(fdt, "")); + +	CHECK(fdt_begin_node(fdt, "aliases")); +	for (s = aliases; *s;) { +		sprintf(name, "i2c%c", *s); +		sprintf(value, "/i2c%d@0", s[1] - 'a'); +		CHECK(fdt_property_string(fdt, name, value)); +		s += 2 + (s[2] != '\0'); +	} +	CHECK(fdt_end_node(fdt)); + +	for (s = nodes; *s; s++) { +		sprintf(value, "i2c%d@0", (*s & 0xdf) - 'A'); +		CHECK(fdt_begin_node(fdt, value)); +		CHECK(fdt_property_string(fdt, "compatible", +			fdtdec_get_compatible(COMPAT_UNKNOWN))); +		if (*s <= 'Z') +			CHECK(fdt_property_string(fdt, "status", "disabled")); +		CHECK(fdt_end_node(fdt)); +	} + +	CHECK(fdt_end_node(fdt)); +	CHECK(fdt_finish(fdt)); +	CHECK(fdt_pack(fdt)); +#if defined(DEBUG) && defined(CONFIG_SANDBOX) +	fd = os_open("/tmp/fdtdec-text.dtb", OS_O_CREAT | OS_O_WRONLY); +	if (fd == -1) { +		printf("Could not open .dtb file to write\n"); +		return -1; +	} +	os_write(fd, fdt, size); +	os_close(fd); +#endif +	return 0; +} + +static int run_test(const char *aliases, const char *nodes, const char *expect) +{ +	int list[MAX_NODES]; +	const char *s; +	void *blob; +	int i; + +	blob = malloc(FDT_SIZE); +	if (!blob) { +		printf("%s: out of memory\n", __func__); +		return 1; +	} + +	printf("aliases=%s, nodes=%s, expect=%s: ", aliases, nodes, expect); +	CHECKVAL(make_fdt(blob, FDT_SIZE, aliases, nodes), 0); +	CHECKVAL(fdtdec_find_aliases_for_id(blob, "i2c", +			COMPAT_UNKNOWN, +			list, ARRAY_SIZE(list)), strlen(expect)); + +	/* Check we got the right ones */ +	for (i = 0, s = expect; *s; s++, i++) { +		int want = *s; +		const char *name; +		int got = ' '; + +		name = list[i] ? fdt_get_name(blob, list[i], NULL) : NULL; +		if (name) +			got = name[3] + 'a' - '0'; + +		if (got != want) { +			printf("Position %d: Expected '%c', got '%c' ('%s')\n", +			       i, want, got, name); +			return 1; +		} +	} + +	printf("pass\n"); +	return 0; +} + +static int do_test_fdtdec(cmd_tbl_t *cmdtp, int flag, int argc, +			  char * const argv[]) +{ +	/* basic tests */ +	CHECKOK(run_test("", "", "")); +	CHECKOK(run_test("1e 3d", "", "")); + +	/* +	 * 'a' represents 0, 'b' represents 1, etc. +	 * The first character is the alias number, the second is the node +	 * number. So the params mean: +	 * 0a 1b	: point alias 0 to node 0 (a), alias 1 to node 1(b) +	 * ab		: to create nodes 0 and 1 (a and b) +	 * ab		: we expect the function to return two nodes, in +	 *		  the order 0, 1 +	 */ +	CHECKOK(run_test("0a 1b", "ab", "ab")); + +	CHECKOK(run_test("0a 1c", "ab", "ab")); +	CHECKOK(run_test("1c", "ab", "ab")); +	CHECKOK(run_test("1b", "ab", "ab")); +	CHECKOK(run_test("0b", "ab", "ba")); +	CHECKOK(run_test("0b 2d", "dbc", "bcd")); +	CHECKOK(run_test("0d 3a 1c 2b", "dbac", "dcba")); + +	/* things with holes */ +	CHECKOK(run_test("1b 3d", "dbc", "cb d")); +	CHECKOK(run_test("1e 3d", "dbc", "bc d")); + +	/* no aliases */ +	CHECKOK(run_test("", "dbac", "dbac")); + +	/* disabled nodes */ +	CHECKOK(run_test("0d 3a 1c 2b", "dBac", "dc a")); +	CHECKOK(run_test("0b 2d", "DBc", "c")); +	CHECKOK(run_test("0b 4d 2c", "DBc", "  c")); + +	/* conflicting aliases - first one gets it */ +	CHECKOK(run_test("2a 1a 0a", "a", "  a")); +	CHECKOK(run_test("0a 1a 2a", "a", "a")); + +	printf("Test passed\n"); +	return 0; +} + +U_BOOT_CMD( +	test_fdtdec, 3, 1, do_test_fdtdec, +	"test_fdtdec", +	"Run tests for fdtdec library"); |