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