13da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson/* 23da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson * libfdt - Flat Device Tree manipulation 33da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson * Testcase common utility functions 43da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson * Copyright (C) 2006 David Gibson, IBM Corporation. 53da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson * 63da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson * This library is free software; you can redistribute it and/or 73da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson * modify it under the terms of the GNU Lesser General Public License 83da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson * as published by the Free Software Foundation; either version 2.1 of 93da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson * the License, or (at your option) any later version. 103da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson * 113da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson * This library is distributed in the hope that it will be useful, but 123da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson * WITHOUT ANY WARRANTY; without even the implied warranty of 133da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 143da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson * Lesser General Public License for more details. 153da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson * 163da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson * You should have received a copy of the GNU Lesser General Public 173da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson * License along with this library; if not, write to the Free Software 183da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 193da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson */ 203da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson 21cdcb415851dc6c3e9550f27139c933fcaeb2d6a7David Gibson#define _GNU_SOURCE /* for strsignal() in glibc. FreeBSD has it either way */ 223da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson 233da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson#include <stdio.h> 243da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson#include <stdlib.h> 25857f54e79f74429af20c2b5ecc00ee98af6a3b8bDavid Gibson#include <stdint.h> 263da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson#include <limits.h> 273da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson#include <string.h> 283da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson#include <errno.h> 293da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson#include <signal.h> 303da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson#include <unistd.h> 314e6221c171377324cc3e80a9c2260b9788335d87David Gibson#include <fcntl.h> 323da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson 333da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson#include <libfdt.h> 343da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson 353da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson#include "tests.h" 363da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson 373da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibsonint verbose_test = 1; 383da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibsonchar *test_name; 393da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson 403da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibsonvoid __attribute__((weak)) cleanup(void) 413da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson{ 423da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson} 433da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson 443da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibsonstatic void sigint_handler(int signum, siginfo_t *si, void *uc) 453da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson{ 463da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson cleanup(); 473da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson fprintf(stderr, "%s: %s (pid=%d)\n", test_name, 483da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson strsignal(signum), getpid()); 493da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson exit(RC_BUG); 503da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson} 513da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson 523da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibsonvoid test_init(int argc, char *argv[]) 533da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson{ 543da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson int err; 553da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson struct sigaction sa_int = { 563da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson .sa_sigaction = sigint_handler, 573da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson }; 583da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson 593da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson test_name = argv[0]; 603da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson 613da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson err = sigaction(SIGINT, &sa_int, NULL); 623da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson if (err) 633da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson FAIL("Can't install SIGINT handler"); 643da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson 653da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson if (getenv("QUIET_TEST")) 663da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson verbose_test = 0; 673da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson 683da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson verbose_printf("Starting testcase \"%s\", pid %d\n", 693da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson test_name, getpid()); 703da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson} 713da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson 72fd1bf3a5ae46962528ef89a824261a88830758a2David Gibsonvoid check_mem_rsv(void *fdt, int n, uint64_t addr, uint64_t size) 73fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson{ 74fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson int err; 75fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson uint64_t addr_v, size_v; 76fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson 77fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson err = fdt_get_mem_rsv(fdt, n, &addr_v, &size_v); 78fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson if (err < 0) 79fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson FAIL("fdt_get_mem_rsv(%d): %s", n, fdt_strerror(err)); 80fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson if ((addr_v != addr) || (size_v != size)) 81fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson FAIL("fdt_get_mem_rsv() returned (0x%llx,0x%llx) " 82fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson "instead of (0x%llx,0x%llx)", 83fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson (unsigned long long)addr_v, (unsigned long long)size_v, 84fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson (unsigned long long)addr, (unsigned long long)size); 85fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson} 86fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson 8773d60926a05814b8864c86c435e272b386513b0eDavid Gibsonvoid check_property(void *fdt, int nodeoffset, const char *name, 883da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson int len, const void *val) 893da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson{ 903da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson const struct fdt_property *prop; 915434fcc7e05e86b61530999d48548e6f18036cf7David Gibson int retlen; 923da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson uint32_t tag, nameoff, proplen; 933da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson const char *propname; 943da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson 953da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson verbose_printf("Checking property \"%s\"...", name); 965434fcc7e05e86b61530999d48548e6f18036cf7David Gibson prop = fdt_get_property(fdt, nodeoffset, name, &retlen); 973da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson verbose_printf("pointer %p\n", prop); 983da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson if (! prop) 995434fcc7e05e86b61530999d48548e6f18036cf7David Gibson FAIL("Error retreiving \"%s\" pointer: %s", name, 1005434fcc7e05e86b61530999d48548e6f18036cf7David Gibson fdt_strerror(retlen)); 1013da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson 1023da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson tag = fdt32_to_cpu(prop->tag); 1033da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson nameoff = fdt32_to_cpu(prop->nameoff); 1043da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson proplen = fdt32_to_cpu(prop->len); 1053da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson 1063da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson if (tag != FDT_PROP) 1073da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson FAIL("Incorrect tag 0x%08x on property \"%s\"", tag, name); 1083da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson 1093da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson propname = fdt_string(fdt, nameoff); 1103da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson if (!propname || !streq(propname, name)) 1113da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson FAIL("Property name mismatch \"%s\" instead of \"%s\"", 1123da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson propname, name); 1135434fcc7e05e86b61530999d48548e6f18036cf7David Gibson if (proplen != retlen) 1145434fcc7e05e86b61530999d48548e6f18036cf7David Gibson FAIL("Length retrieved for \"%s\" by fdt_get_property()" 1155434fcc7e05e86b61530999d48548e6f18036cf7David Gibson " differs from stored length (%d != %d)", 1165434fcc7e05e86b61530999d48548e6f18036cf7David Gibson name, retlen, proplen); 1173da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson if (proplen != len) 1183da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson FAIL("Size mismatch on property \"%s\": %d insead of %d", 1193da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson name, proplen, len); 1203da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson if (memcmp(val, prop->data, len) != 0) 1213da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson FAIL("Data mismatch on property \"%s\"", name); 1223da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson} 1233da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson 124a6c76f923dcc42102fac58375eaca28057811c20David Gibsonconst void *check_getprop(void *fdt, int nodeoffset, const char *name, 125a6c76f923dcc42102fac58375eaca28057811c20David Gibson int len, const void *val) 1263da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson{ 127a6c76f923dcc42102fac58375eaca28057811c20David Gibson const void *propval; 1283da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson int proplen; 1293da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson 1303da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson propval = fdt_getprop(fdt, nodeoffset, name, &proplen); 131a7ee95ded6a0d64c1c259b9c6fea090e19ca81f8David Gibson if (! propval) 1325434fcc7e05e86b61530999d48548e6f18036cf7David Gibson FAIL("fdt_getprop(\"%s\"): %s", name, fdt_strerror(proplen)); 1333da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson 1343da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson if (proplen != len) 1353da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson FAIL("Size mismatch on property \"%s\": %d insead of %d", 1363da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson name, proplen, len); 1373da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson if (memcmp(val, propval, len) != 0) 1383da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson FAIL("Data mismatch on property \"%s\"", name); 1393da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson 1403da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson return propval; 1413da0f9a10dfa9b615d06c350c7b9fe29f360a6eDavid Gibson} 1424e6221c171377324cc3e80a9c2260b9788335d87David Gibson 143d2a9da045897c37071597d9aa473964717b14735David Gibsonint nodename_eq(const char *s1, const char *s2) 144d2a9da045897c37071597d9aa473964717b14735David Gibson{ 145d2a9da045897c37071597d9aa473964717b14735David Gibson int len = strlen(s2); 146d2a9da045897c37071597d9aa473964717b14735David Gibson 147d2a9da045897c37071597d9aa473964717b14735David Gibson if (strncmp(s1, s2, len) != 0) 148d2a9da045897c37071597d9aa473964717b14735David Gibson return 0; 149d2a9da045897c37071597d9aa473964717b14735David Gibson if (s1[len] == '\0') 150d2a9da045897c37071597d9aa473964717b14735David Gibson return 1; 151d2a9da045897c37071597d9aa473964717b14735David Gibson else if (!memchr(s2, '@', len) && (s1[len] == '@')) 152d2a9da045897c37071597d9aa473964717b14735David Gibson return 1; 153d2a9da045897c37071597d9aa473964717b14735David Gibson else 154d2a9da045897c37071597d9aa473964717b14735David Gibson return 0; 155d2a9da045897c37071597d9aa473964717b14735David Gibson} 156d2a9da045897c37071597d9aa473964717b14735David Gibson 1574e6221c171377324cc3e80a9c2260b9788335d87David Gibson#define CHUNKSIZE 128 1584e6221c171377324cc3e80a9c2260b9788335d87David Gibson 1594e6221c171377324cc3e80a9c2260b9788335d87David Gibsonvoid *load_blob(const char *filename) 1604e6221c171377324cc3e80a9c2260b9788335d87David Gibson{ 1611c25c0d520dee58bfd86626a07036fe9febfebe6Simon Glass char *blob; 1625543b88d5e3047b781552eb431bc2e3bdd9ade06Jon Loeliger int ret = utilfdt_read_err(filename, &blob); 1634e6221c171377324cc3e80a9c2260b9788335d87David Gibson 1641c25c0d520dee58bfd86626a07036fe9febfebe6Simon Glass if (ret) 1651c25c0d520dee58bfd86626a07036fe9febfebe6Simon Glass CONFIG("Couldn't open blob from \"%s\": %s", filename, 1661c25c0d520dee58bfd86626a07036fe9febfebe6Simon Glass strerror(ret)); 1671c25c0d520dee58bfd86626a07036fe9febfebe6Simon Glass return blob; 1684e6221c171377324cc3e80a9c2260b9788335d87David Gibson} 1694e6221c171377324cc3e80a9c2260b9788335d87David Gibson 1704e6221c171377324cc3e80a9c2260b9788335d87David Gibsonvoid *load_blob_arg(int argc, char *argv[]) 1714e6221c171377324cc3e80a9c2260b9788335d87David Gibson{ 1724e6221c171377324cc3e80a9c2260b9788335d87David Gibson if (argc != 2) 1734e6221c171377324cc3e80a9c2260b9788335d87David Gibson CONFIG("Usage: %s <dtb file>", argv[0]); 1744e6221c171377324cc3e80a9c2260b9788335d87David Gibson return load_blob(argv[1]); 1754e6221c171377324cc3e80a9c2260b9788335d87David Gibson} 176063693a9e42aea7beb7c6f49ecd8a8dc5ed1c387David Gibson 17773d60926a05814b8864c86c435e272b386513b0eDavid Gibsonvoid save_blob(const char *filename, void *fdt) 178063693a9e42aea7beb7c6f49ecd8a8dc5ed1c387David Gibson{ 1791c25c0d520dee58bfd86626a07036fe9febfebe6Simon Glass int ret = utilfdt_write_err(filename, fdt); 1801c25c0d520dee58bfd86626a07036fe9febfebe6Simon Glass 1811c25c0d520dee58bfd86626a07036fe9febfebe6Simon Glass if (ret) 1821c25c0d520dee58bfd86626a07036fe9febfebe6Simon Glass CONFIG("Couldn't write blob to \"%s\": %s", filename, 1831c25c0d520dee58bfd86626a07036fe9febfebe6Simon Glass strerror(ret)); 184063693a9e42aea7beb7c6f49ecd8a8dc5ed1c387David Gibson} 185a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson 186a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibsonvoid *open_blob_rw(void *blob) 187a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson{ 188a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson int err; 189a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson void *buf = blob; 190a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson 191a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson err = fdt_open_into(blob, buf, fdt_totalsize(blob)); 192a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson if (err == -FDT_ERR_NOSPACE) { 193a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson /* Ran out of space converting to v17 */ 194a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson int newsize = fdt_totalsize(blob) + 8; 195a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson 196a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson buf = xmalloc(newsize); 197a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson err = fdt_open_into(blob, buf, newsize); 198a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson } 199a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson if (err) 200a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson FAIL("fdt_open_into(): %s", fdt_strerror(err)); 201a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson return buf; 202a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson} 203