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