1 /* 2 * libfdt - Flat Device Tree manipulation 3 * Testcase common utility functions 4 * Copyright (C) 2006 David Gibson, IBM Corporation. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public License 8 * as published by the Free Software Foundation; either version 2.1 of 9 * the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, but 12 * WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21 #define _GNU_SOURCE /* for strsignal() in glibc. FreeBSD has it either way */ 22 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <stdint.h> 26 #include <limits.h> 27 #include <string.h> 28 #include <errno.h> 29 #include <signal.h> 30 #include <unistd.h> 31 #include <fcntl.h> 32 33 #include <libfdt.h> 34 35 #include "tests.h" 36 37 int verbose_test = 1; 38 char *test_name; 39 40 void __attribute__((weak)) cleanup(void) 41 { 42 } 43 44 static void sigint_handler(int signum, siginfo_t *si, void *uc) 45 { 46 cleanup(); 47 fprintf(stderr, "%s: %s (pid=%d)\n", test_name, 48 strsignal(signum), getpid()); 49 exit(RC_BUG); 50 } 51 52 void test_init(int argc, char *argv[]) 53 { 54 int err; 55 struct sigaction sa_int = { 56 .sa_sigaction = sigint_handler, 57 }; 58 59 test_name = argv[0]; 60 61 err = sigaction(SIGINT, &sa_int, NULL); 62 if (err) 63 FAIL("Can't install SIGINT handler"); 64 65 if (getenv("QUIET_TEST")) 66 verbose_test = 0; 67 68 verbose_printf("Starting testcase \"%s\", pid %d\n", 69 test_name, getpid()); 70 } 71 72 void check_mem_rsv(void *fdt, int n, uint64_t addr, uint64_t size) 73 { 74 int err; 75 uint64_t addr_v, size_v; 76 77 err = fdt_get_mem_rsv(fdt, n, &addr_v, &size_v); 78 if (err < 0) 79 FAIL("fdt_get_mem_rsv(%d): %s", n, fdt_strerror(err)); 80 if ((addr_v != addr) || (size_v != size)) 81 FAIL("fdt_get_mem_rsv() returned (0x%llx,0x%llx) " 82 "instead of (0x%llx,0x%llx)", 83 (unsigned long long)addr_v, (unsigned long long)size_v, 84 (unsigned long long)addr, (unsigned long long)size); 85 } 86 87 void check_property(void *fdt, int nodeoffset, const char *name, 88 int len, const void *val) 89 { 90 const struct fdt_property *prop; 91 int retlen; 92 uint32_t tag, nameoff, proplen; 93 const char *propname; 94 95 verbose_printf("Checking property \"%s\"...", name); 96 prop = fdt_get_property(fdt, nodeoffset, name, &retlen); 97 verbose_printf("pointer %p\n", prop); 98 if (! prop) 99 FAIL("Error retreiving \"%s\" pointer: %s", name, 100 fdt_strerror(retlen)); 101 102 tag = fdt32_to_cpu(prop->tag); 103 nameoff = fdt32_to_cpu(prop->nameoff); 104 proplen = fdt32_to_cpu(prop->len); 105 106 if (tag != FDT_PROP) 107 FAIL("Incorrect tag 0x%08x on property \"%s\"", tag, name); 108 109 propname = fdt_string(fdt, nameoff); 110 if (!propname || !streq(propname, name)) 111 FAIL("Property name mismatch \"%s\" instead of \"%s\"", 112 propname, name); 113 if (proplen != retlen) 114 FAIL("Length retrieved for \"%s\" by fdt_get_property()" 115 " differs from stored length (%d != %d)", 116 name, retlen, proplen); 117 if (proplen != len) 118 FAIL("Size mismatch on property \"%s\": %d insead of %d", 119 name, proplen, len); 120 if (memcmp(val, prop->data, len) != 0) 121 FAIL("Data mismatch on property \"%s\"", name); 122 } 123 124 const void *check_getprop(void *fdt, int nodeoffset, const char *name, 125 int len, const void *val) 126 { 127 const void *propval; 128 int proplen; 129 130 propval = fdt_getprop(fdt, nodeoffset, name, &proplen); 131 if (! propval) 132 FAIL("fdt_getprop(\"%s\"): %s", name, fdt_strerror(proplen)); 133 134 if (proplen != len) 135 FAIL("Size mismatch on property \"%s\": %d insead of %d", 136 name, proplen, len); 137 if (memcmp(val, propval, len) != 0) 138 FAIL("Data mismatch on property \"%s\"", name); 139 140 return propval; 141 } 142 143 int nodename_eq(const char *s1, const char *s2) 144 { 145 int len = strlen(s2); 146 147 if (strncmp(s1, s2, len) != 0) 148 return 0; 149 if (s1[len] == '\0') 150 return 1; 151 else if (!memchr(s2, '@', len) && (s1[len] == '@')) 152 return 1; 153 else 154 return 0; 155 } 156 157 #define CHUNKSIZE 128 158 159 void *load_blob(const char *filename) 160 { 161 char *blob; 162 int ret = utilfdt_read_err(filename, &blob); 163 164 if (ret) 165 CONFIG("Couldn't open blob from \"%s\": %s", filename, 166 strerror(ret)); 167 return blob; 168 } 169 170 void *load_blob_arg(int argc, char *argv[]) 171 { 172 if (argc != 2) 173 CONFIG("Usage: %s <dtb file>", argv[0]); 174 return load_blob(argv[1]); 175 } 176 177 void save_blob(const char *filename, void *fdt) 178 { 179 int ret = utilfdt_write_err(filename, fdt); 180 181 if (ret) 182 CONFIG("Couldn't write blob to \"%s\": %s", filename, 183 strerror(ret)); 184 } 185 186 void *open_blob_rw(void *blob) 187 { 188 int err; 189 void *buf = blob; 190 191 err = fdt_open_into(blob, buf, fdt_totalsize(blob)); 192 if (err == -FDT_ERR_NOSPACE) { 193 /* Ran out of space converting to v17 */ 194 int newsize = fdt_totalsize(blob) + 8; 195 196 buf = xmalloc(newsize); 197 err = fdt_open_into(blob, buf, newsize); 198 } 199 if (err) 200 FAIL("fdt_open_into(): %s", fdt_strerror(err)); 201 return buf; 202 } 203