1dc254f38SSimon Glass /* 2dc254f38SSimon Glass * Some very basic tests for fdtdec, accessed through test_fdtdec command. 3dc254f38SSimon Glass * They are easiest to use with sandbox. 4dc254f38SSimon Glass * 5dc254f38SSimon Glass * Copyright (c) 2011 The Chromium OS Authors. 6*1a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 7dc254f38SSimon Glass */ 8dc254f38SSimon Glass 9dc254f38SSimon Glass #include <common.h> 10dc254f38SSimon Glass #include <fdtdec.h> 11dc254f38SSimon Glass #include <libfdt.h> 12dc254f38SSimon Glass #include <malloc.h> 13dc254f38SSimon Glass #include <os.h> 14dc254f38SSimon Glass 15dc254f38SSimon Glass /* The size of our test fdt blob */ 16dc254f38SSimon Glass #define FDT_SIZE (16 * 1024) 17dc254f38SSimon Glass 18dc254f38SSimon Glass /** 19dc254f38SSimon Glass * Check if an operation failed, and if so, print an error 20dc254f38SSimon Glass * 21dc254f38SSimon Glass * @param oper_name Name of operation 22dc254f38SSimon Glass * @param err Error code to check 23dc254f38SSimon Glass * 24dc254f38SSimon Glass * @return 0 if ok, -1 if there was an error 25dc254f38SSimon Glass */ 26dc254f38SSimon Glass static int fdt_checkerr(const char *oper_name, int err) 27dc254f38SSimon Glass { 28dc254f38SSimon Glass if (err) { 29dc254f38SSimon Glass printf("%s: %s: %s\n", __func__, oper_name, fdt_strerror(err)); 30dc254f38SSimon Glass return -1; 31dc254f38SSimon Glass } 32dc254f38SSimon Glass 33dc254f38SSimon Glass return 0; 34dc254f38SSimon Glass } 35dc254f38SSimon Glass 36dc254f38SSimon Glass /** 37dc254f38SSimon Glass * Check the result of an operation and if incorrect, print an error 38dc254f38SSimon Glass * 39dc254f38SSimon Glass * @param oper_name Name of operation 40dc254f38SSimon Glass * @param expected Expected value 41dc254f38SSimon Glass * @param value Actual value 42dc254f38SSimon Glass * 43dc254f38SSimon Glass * @return 0 if ok, -1 if there was an error 44dc254f38SSimon Glass */ 45dc254f38SSimon Glass static int checkval(const char *oper_name, int expected, int value) 46dc254f38SSimon Glass { 47dc254f38SSimon Glass if (expected != value) { 48dc254f38SSimon Glass printf("%s: %s: expected %d, but returned %d\n", __func__, 49dc254f38SSimon Glass oper_name, expected, value); 50dc254f38SSimon Glass return -1; 51dc254f38SSimon Glass } 52dc254f38SSimon Glass 53dc254f38SSimon Glass return 0; 54dc254f38SSimon Glass } 55dc254f38SSimon Glass 56dc254f38SSimon Glass #define CHECK(op) if (fdt_checkerr(#op, op)) return -1 57dc254f38SSimon Glass #define CHECKVAL(op, expected) \ 58dc254f38SSimon Glass if (checkval(#op, expected, op)) \ 59dc254f38SSimon Glass return -1 60dc254f38SSimon Glass #define CHECKOK(op) CHECKVAL(op, 0) 61dc254f38SSimon Glass 62dc254f38SSimon Glass /* maximum number of nodes / aliases to generate */ 63dc254f38SSimon Glass #define MAX_NODES 20 64dc254f38SSimon Glass 65dc254f38SSimon Glass /* 66dc254f38SSimon Glass * Make a test fdt 67dc254f38SSimon Glass * 68dc254f38SSimon Glass * @param fdt Device tree pointer 69dc254f38SSimon Glass * @param size Size of device tree blob 70dc254f38SSimon Glass * @param aliases Specifies alias assignments. Format is a list of items 71dc254f38SSimon Glass * separated by space. Items are #a where 72dc254f38SSimon Glass * # is the alias number 73dc254f38SSimon Glass * a is the node to point to 74dc254f38SSimon Glass * @param nodes Specifies nodes to generate (a=0, b=1), upper case 75dc254f38SSimon Glass * means to create a disabled node 76dc254f38SSimon Glass */ 77dc254f38SSimon Glass static int make_fdt(void *fdt, int size, const char *aliases, 78dc254f38SSimon Glass const char *nodes) 79dc254f38SSimon Glass { 80dc254f38SSimon Glass char name[20], value[20]; 81dc254f38SSimon Glass const char *s; 82dc254f38SSimon Glass int fd; 83dc254f38SSimon Glass 84dc254f38SSimon Glass CHECK(fdt_create(fdt, size)); 85dc254f38SSimon Glass CHECK(fdt_finish_reservemap(fdt)); 86dc254f38SSimon Glass CHECK(fdt_begin_node(fdt, "")); 87dc254f38SSimon Glass 88dc254f38SSimon Glass CHECK(fdt_begin_node(fdt, "aliases")); 89dc254f38SSimon Glass for (s = aliases; *s;) { 90dc254f38SSimon Glass sprintf(name, "i2c%c", *s); 91dc254f38SSimon Glass sprintf(value, "/i2c%d@0", s[1] - 'a'); 92dc254f38SSimon Glass CHECK(fdt_property_string(fdt, name, value)); 93dc254f38SSimon Glass s += 2 + (s[2] != '\0'); 94dc254f38SSimon Glass } 95dc254f38SSimon Glass CHECK(fdt_end_node(fdt)); 96dc254f38SSimon Glass 97dc254f38SSimon Glass for (s = nodes; *s; s++) { 98dc254f38SSimon Glass sprintf(value, "i2c%d@0", (*s & 0xdf) - 'A'); 99dc254f38SSimon Glass CHECK(fdt_begin_node(fdt, value)); 100dc254f38SSimon Glass CHECK(fdt_property_string(fdt, "compatible", 101dc254f38SSimon Glass fdtdec_get_compatible(COMPAT_UNKNOWN))); 102dc254f38SSimon Glass if (*s <= 'Z') 103dc254f38SSimon Glass CHECK(fdt_property_string(fdt, "status", "disabled")); 104dc254f38SSimon Glass CHECK(fdt_end_node(fdt)); 105dc254f38SSimon Glass } 106dc254f38SSimon Glass 107dc254f38SSimon Glass CHECK(fdt_end_node(fdt)); 108dc254f38SSimon Glass CHECK(fdt_finish(fdt)); 109dc254f38SSimon Glass CHECK(fdt_pack(fdt)); 110dc254f38SSimon Glass #if defined(DEBUG) && defined(CONFIG_SANDBOX) 111dc254f38SSimon Glass fd = os_open("/tmp/fdtdec-text.dtb", OS_O_CREAT | OS_O_WRONLY); 112dc254f38SSimon Glass if (fd == -1) { 113dc254f38SSimon Glass printf("Could not open .dtb file to write\n"); 114dc254f38SSimon Glass return -1; 115dc254f38SSimon Glass } 116dc254f38SSimon Glass os_write(fd, fdt, size); 117dc254f38SSimon Glass os_close(fd); 118dc254f38SSimon Glass #endif 119dc254f38SSimon Glass return 0; 120dc254f38SSimon Glass } 121dc254f38SSimon Glass 122dc254f38SSimon Glass static int run_test(const char *aliases, const char *nodes, const char *expect) 123dc254f38SSimon Glass { 124dc254f38SSimon Glass int list[MAX_NODES]; 125dc254f38SSimon Glass const char *s; 126dc254f38SSimon Glass void *blob; 127dc254f38SSimon Glass int i; 128dc254f38SSimon Glass 129dc254f38SSimon Glass blob = malloc(FDT_SIZE); 130dc254f38SSimon Glass if (!blob) { 131dc254f38SSimon Glass printf("%s: out of memory\n", __func__); 132dc254f38SSimon Glass return 1; 133dc254f38SSimon Glass } 134dc254f38SSimon Glass 135dc254f38SSimon Glass printf("aliases=%s, nodes=%s, expect=%s: ", aliases, nodes, expect); 136dc254f38SSimon Glass CHECKVAL(make_fdt(blob, FDT_SIZE, aliases, nodes), 0); 137dc254f38SSimon Glass CHECKVAL(fdtdec_find_aliases_for_id(blob, "i2c", 138dc254f38SSimon Glass COMPAT_UNKNOWN, 139dc254f38SSimon Glass list, ARRAY_SIZE(list)), strlen(expect)); 140dc254f38SSimon Glass 141dc254f38SSimon Glass /* Check we got the right ones */ 142dc254f38SSimon Glass for (i = 0, s = expect; *s; s++, i++) { 143dc254f38SSimon Glass int want = *s; 144dc254f38SSimon Glass const char *name; 145dc254f38SSimon Glass int got = ' '; 146dc254f38SSimon Glass 147dc254f38SSimon Glass name = list[i] ? fdt_get_name(blob, list[i], NULL) : NULL; 148dc254f38SSimon Glass if (name) 149dc254f38SSimon Glass got = name[3] + 'a' - '0'; 150dc254f38SSimon Glass 151dc254f38SSimon Glass if (got != want) { 152dc254f38SSimon Glass printf("Position %d: Expected '%c', got '%c' ('%s')\n", 153dc254f38SSimon Glass i, want, got, name); 154dc254f38SSimon Glass return 1; 155dc254f38SSimon Glass } 156dc254f38SSimon Glass } 157dc254f38SSimon Glass 158dc254f38SSimon Glass printf("pass\n"); 159dc254f38SSimon Glass return 0; 160dc254f38SSimon Glass } 161dc254f38SSimon Glass 162dc254f38SSimon Glass static int do_test_fdtdec(cmd_tbl_t *cmdtp, int flag, int argc, 163dc254f38SSimon Glass char * const argv[]) 164dc254f38SSimon Glass { 165dc254f38SSimon Glass /* basic tests */ 166dc254f38SSimon Glass CHECKOK(run_test("", "", "")); 167dc254f38SSimon Glass CHECKOK(run_test("1e 3d", "", "")); 168dc254f38SSimon Glass 169dc254f38SSimon Glass /* 170dc254f38SSimon Glass * 'a' represents 0, 'b' represents 1, etc. 171dc254f38SSimon Glass * The first character is the alias number, the second is the node 172dc254f38SSimon Glass * number. So the params mean: 173dc254f38SSimon Glass * 0a 1b : point alias 0 to node 0 (a), alias 1 to node 1(b) 174dc254f38SSimon Glass * ab : to create nodes 0 and 1 (a and b) 175dc254f38SSimon Glass * ab : we expect the function to return two nodes, in 176dc254f38SSimon Glass * the order 0, 1 177dc254f38SSimon Glass */ 178dc254f38SSimon Glass CHECKOK(run_test("0a 1b", "ab", "ab")); 179dc254f38SSimon Glass 180dc254f38SSimon Glass CHECKOK(run_test("0a 1c", "ab", "ab")); 181dc254f38SSimon Glass CHECKOK(run_test("1c", "ab", "ab")); 182dc254f38SSimon Glass CHECKOK(run_test("1b", "ab", "ab")); 183dc254f38SSimon Glass CHECKOK(run_test("0b", "ab", "ba")); 184dc254f38SSimon Glass CHECKOK(run_test("0b 2d", "dbc", "bcd")); 185dc254f38SSimon Glass CHECKOK(run_test("0d 3a 1c 2b", "dbac", "dcba")); 186dc254f38SSimon Glass 187dc254f38SSimon Glass /* things with holes */ 188dc254f38SSimon Glass CHECKOK(run_test("1b 3d", "dbc", "cb d")); 189dc254f38SSimon Glass CHECKOK(run_test("1e 3d", "dbc", "bc d")); 190dc254f38SSimon Glass 191dc254f38SSimon Glass /* no aliases */ 192dc254f38SSimon Glass CHECKOK(run_test("", "dbac", "dbac")); 193dc254f38SSimon Glass 194dc254f38SSimon Glass /* disabled nodes */ 195dc254f38SSimon Glass CHECKOK(run_test("0d 3a 1c 2b", "dBac", "dc a")); 196dc254f38SSimon Glass CHECKOK(run_test("0b 2d", "DBc", "c")); 197dc254f38SSimon Glass CHECKOK(run_test("0b 4d 2c", "DBc", " c")); 198dc254f38SSimon Glass 199dc254f38SSimon Glass /* conflicting aliases - first one gets it */ 200dc254f38SSimon Glass CHECKOK(run_test("2a 1a 0a", "a", " a")); 201dc254f38SSimon Glass CHECKOK(run_test("0a 1a 2a", "a", "a")); 202dc254f38SSimon Glass 203dc254f38SSimon Glass printf("Test passed\n"); 204dc254f38SSimon Glass return 0; 205dc254f38SSimon Glass } 206dc254f38SSimon Glass 207dc254f38SSimon Glass U_BOOT_CMD( 208dc254f38SSimon Glass test_fdtdec, 3, 1, do_test_fdtdec, 209dc254f38SSimon Glass "test_fdtdec", 210dc254f38SSimon Glass "Run tests for fdtdec library"); 211