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