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