blob: c7b7e06aec24f0672a4107f45cfc519319bd1242 [file] [log] [blame]
johpow0173007872020-07-15 20:01:05 -05001/*
2 * Copyright (c) 2020, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include "CppUTest/TestHarness.h"
8
9extern "C" {
10#include <common/fdt_wrappers.h>
11#include <libfdt.h>
12#include <stdio.h>
13#include <string.h>
14}
15
16#define FDT_SUCCESS (0)
17
18#define FILE_NOT_FOUND_HELP \
19" The DTB file used in this test must be generated manually before\n" \
20" running the test suite. There is a script build_dtb.sh found in\n" \
21" tests/lib/fdt/device_trees which can be used to do this."
22
23static int check_translation(const void *fdt, int node, uintptr_t *address)
24{
25 const char *prop;
26 int len, ret;
27 uintptr_t addr;
28
29 prop = (const char *)fdt_getprop(fdt, node, "compatible", &len);
30 if (!prop) {
31 return 3;
32 }
33
34 ret = fdt_get_reg_props_by_index(fdt, node, 0, &addr, NULL);
35 if (ret)
36 {
37 return 4;
38 }
39 addr = fdtw_translate_address(fdt, node, addr);
40
41 *address = addr;
42 return 0;
43}
44
45static uint64_t read_check_address (unsigned char *prop)
46{
47 uint64_t res = 0;
48 /* Address field is stored as 4 big endian uint32_t values. */
49 for (int i = 0; i < 8; i++)
50 {
51 res = res | ((uint64_t)prop[i] << (56-(i*8)));
52 }
53 return res;
54}
55
56static int run_test(const char *name, const char *dtb_path, const char *dev,
57 uintptr_t expected)
58{
59 FILE *dtb;
60 size_t size;
61 int offs;
62 int ret;
63 int len;
64 uintptr_t address;
65 unsigned char *prop;
66 void *fdt_buffer;
67
68 printf("FDT Translation Test Case: %s\n", name);
69 printf(" DTB file: %s\n", dtb_path);
70 if (dev != NULL)
71 {
72 printf(" Device: %s\n", dev);
73 }
74 else
75 {
76 printf(" Device: stdout\n");
77 }
78
79 /* Read DTB file into buffer */
80 dtb = fopen(dtb_path, "rb");
81 if (dtb == NULL)
82 {
83 printf(" [ERROR] Could not open device tree binary \"%s\"\n",
84 dtb_path);
85 printf("%s", FILE_NOT_FOUND_HELP);
86 return -1;
87 }
88
89 /* Get size and allocate buffer. */
90 fseek(dtb, 0, SEEK_END);
91 size = ftell(dtb);
92 fdt_buffer = malloc(size);
93 if (fdt_buffer == NULL)
94 {
95 printf(" [ERROR] Could not allocate file buffer.\n");
96 return -1;
97 }
98 rewind(dtb);
99
100 /* Read file into buffer and close it. */
101 if(fread(fdt_buffer, 1, size, dtb) != size)
102 {
103 printf(" [ERROR] Could not read input file.\n");
104 free(fdt_buffer);
105 return -1;
106 }
107 fclose(dtb);
108
109 ret = fdt_check_header(fdt_buffer);
110 if (ret) {
111 printf(" [ERROR] Invalid DTB header.\n");
112 free(fdt_buffer);
113 return ret;
114 }
115
116 if (dev != NULL)
117 {
118 /* If a specific device is given, look for it. */
119 offs = fdt_node_offset_by_compatible(fdt_buffer, -1, dev);
120 }
121 else
122 {
123 /* If no device specified, look for stdout node. */
124 offs = fdt_get_stdout_node_offset(fdt_buffer);
125 }
126 if (offs < 0) {
127 printf(" [ERROR] Could not find requested node.\n");
128 ret = offs;
129 free(fdt_buffer);
130 return ret;
131 }
132
133 /* Get address of device. */
134 ret = check_translation(fdt_buffer, offs, &address);
135 if (ret != 0)
136 {
137 free(fdt_buffer);
138 return ret;
139 }
140
141 /* Verify address translation. */
142 if (expected == 0)
143 {
144 /* Retrieve expected result from DTB "address" property. */
145 prop = (unsigned char *)fdt_getprop(fdt_buffer, offs, "address",
146 &len);
147 if ((prop == NULL) || (len != 16))
148 {
149 printf(" [ERROR] Expected len %d, got %d\n", 16, len);
150 free(fdt_buffer);
151 return -1;
152 }
153 expected = read_check_address(prop);
154 }
155
156 printf(" Expected: 0x%0lX\n", expected);
157 printf(" Found: 0x%0lX\n", address);
158 if (address != expected)
159 {
160 printf(" TEST FAILED\n");
161 free(fdt_buffer);
162 return -1;
163 }
164
165 printf(" TEST SUCCEEDED\n");
166 free(fdt_buffer);
167 return 0;
168}
169
170TEST_GROUP(fdt)
171{
172 /* Nothing to declare here. */
173};
174
175TEST(fdt, test_fvp)
176{
177 int result = run_test("test_fvp", TFA_FVP_DTB_PATH, "arm,sp804",
178 0x1C110000);
179 CHECK_EQUAL(result, 0);
180}
181
182TEST(fdt, test_juno_r1_a)
183{
184 /* Search for stdout with NULL compatible string. */
185 int result = run_test("test_juno_r1_a", LINUX64_JUNO_R1_DTB, NULL,
186 0x7FF80000);
187 CHECK_EQUAL(result, 0);
188}
189
190TEST(fdt, test_juno_r1_b)
191{
192 int result = run_test("test_juno_r1_b", LINUX64_JUNO_R1_DTB,
193 "arm,sp804", 0x1C110000);
194 CHECK_EQUAL(result, 0);
195}
196
197TEST(fdt, test_sun50i)
198{
199 int result = run_test("test_sun50i_pine64_plus",
200 LINUX64_SUN50I_PINE64_PLUS_DTB,
201 "allwinner,sun50i-a64-de2-rotate",
202 0x01020000);
203 CHECK_EQUAL(result, 0);
204}
205
206TEST(fdt, test_atlas)
207{
208 int result = run_test("test_atlas_7_evb", LINUX32_ATLAS7_EVB_DTB,
209 "sirf,prima2-pwm", 0x18630000);
210 CHECK_EQUAL(result, 0);
211}
212
213TEST(fdt, test_bcm2837)
214{
215 int result = run_test("test_bcm2837_rpi_3", LINUX32_BCM2837_RPI_3_B_DTB,
216 "brcm,bcm2835-txp", 0x3F004000);
217 CHECK_EQUAL(result, 0);
218}
219
220TEST(fdt, test_generic)
221{
222 int failcount = 0;
223 int i = 0;
224 char device[15] = {0};
225
226 /* Count from 1 to 11 */
227 for (int i = 1; i < 12; i++)
228 {
229 sprintf(device, "acme,device%d", i);
230 if (run_test("test_generic", TEST_DTB, device, 0) != 0)
231 {
232 failcount++;
233 }
234 }
235
236 CHECK_EQUAL(failcount, 0);
237}