Add missing files in f807af192828222dee7a5c9f94d999673bb4d8a1 import.

This commit is contained in:
Warner Losh 2012-07-24 04:12:44 +00:00
parent bae61446cf
commit ab1c86b34d
58 changed files with 2802 additions and 0 deletions

24
Makefile.utils Normal file
View File

@ -0,0 +1,24 @@
#
# This is not a complete Makefile of itself. Instead, it is designed to
# be easily embeddable into other systems of Makefiles.
#
FDTDUMP_SRCS = \
fdtdump.c \
util.c
FDTDUMP_OBJS = $(FDTDUMP_SRCS:%.c=%.o)
FDTGET_SRCS = \
fdtget.c \
util.c
FDTGET_OBJS = $(FDTGET_SRCS:%.c=%.o)
FDTPUT_SRCS = \
fdtput.c \
util.c
FDTPUT_OBJS = $(FDTPUT_SRCS:%.c=%.o)

38
dtdiff Normal file
View File

@ -0,0 +1,38 @@
#! /bin/bash
# This script uses the bash <(...) extension.
# If you want to change this to work with a generic /bin/sh, make sure
# you fix that.
DTC=dtc
source_and_sort () {
DT="$1"
if [ -d "$DT" ]; then
IFORMAT=fs
elif [ -f "$DT" ]; then
case "$DT" in
*.dts)
IFORMAT=dts
;;
*.dtb)
IFORMAT=dtb
;;
esac
fi
if [ -z "$IFORMAT" ]; then
echo "Unrecognized format for $DT" >&2
exit 2
fi
$DTC -I $IFORMAT -O dts -qq -f -s -o - "$DT"
}
if [ $# != 2 ]; then
echo "Usage: dtdiff <device tree> <device tree>" >&2
exit 1
fi
diff -u <(source_and_sort "$1") <(source_and_sort "$2")

162
fdtdump.c Normal file
View File

@ -0,0 +1,162 @@
/*
* fdtdump.c - Contributed by Pantelis Antoniou <pantelis.antoniou AT gmail.com>
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <fdt.h>
#include <libfdt_env.h>
#include "util.h"
#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
#define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a))))
#define GET_CELL(p) (p += 4, *((const uint32_t *)(p-4)))
static void print_data(const char *data, int len)
{
int i;
const char *p = data;
/* no data, don't print */
if (len == 0)
return;
if (util_is_printable_string(data, len)) {
printf(" = \"%s\"", (const char *)data);
} else if ((len % 4) == 0) {
printf(" = <");
for (i = 0; i < len; i += 4)
printf("0x%08x%s", fdt32_to_cpu(GET_CELL(p)),
i < (len - 4) ? " " : "");
printf(">");
} else {
printf(" = [");
for (i = 0; i < len; i++)
printf("%02x%s", *p++, i < len - 1 ? " " : "");
printf("]");
}
}
static void dump_blob(void *blob)
{
struct fdt_header *bph = blob;
uint32_t off_mem_rsvmap = fdt32_to_cpu(bph->off_mem_rsvmap);
uint32_t off_dt = fdt32_to_cpu(bph->off_dt_struct);
uint32_t off_str = fdt32_to_cpu(bph->off_dt_strings);
struct fdt_reserve_entry *p_rsvmap =
(struct fdt_reserve_entry *)((char *)blob + off_mem_rsvmap);
const char *p_struct = (const char *)blob + off_dt;
const char *p_strings = (const char *)blob + off_str;
uint32_t version = fdt32_to_cpu(bph->version);
uint32_t totalsize = fdt32_to_cpu(bph->totalsize);
uint32_t tag;
const char *p, *s, *t;
int depth, sz, shift;
int i;
uint64_t addr, size;
depth = 0;
shift = 4;
printf("/dts-v1/;\n");
printf("// magic:\t\t0x%x\n", fdt32_to_cpu(bph->magic));
printf("// totalsize:\t\t0x%x (%d)\n", totalsize, totalsize);
printf("// off_dt_struct:\t0x%x\n", off_dt);
printf("// off_dt_strings:\t0x%x\n", off_str);
printf("// off_mem_rsvmap:\t0x%x\n", off_mem_rsvmap);
printf("// version:\t\t%d\n", version);
printf("// last_comp_version:\t%d\n",
fdt32_to_cpu(bph->last_comp_version));
if (version >= 2)
printf("// boot_cpuid_phys:\t0x%x\n",
fdt32_to_cpu(bph->boot_cpuid_phys));
if (version >= 3)
printf("// size_dt_strings:\t0x%x\n",
fdt32_to_cpu(bph->size_dt_strings));
if (version >= 17)
printf("// size_dt_struct:\t0x%x\n",
fdt32_to_cpu(bph->size_dt_struct));
printf("\n");
for (i = 0; ; i++) {
addr = fdt64_to_cpu(p_rsvmap[i].address);
size = fdt64_to_cpu(p_rsvmap[i].size);
if (addr == 0 && size == 0)
break;
printf("/memreserve/ %llx %llx;\n",
(unsigned long long)addr, (unsigned long long)size);
}
p = p_struct;
while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) {
/* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */
if (tag == FDT_BEGIN_NODE) {
s = p;
p = PALIGN(p + strlen(s) + 1, 4);
if (*s == '\0')
s = "/";
printf("%*s%s {\n", depth * shift, "", s);
depth++;
continue;
}
if (tag == FDT_END_NODE) {
depth--;
printf("%*s};\n", depth * shift, "");
continue;
}
if (tag == FDT_NOP) {
printf("%*s// [NOP]\n", depth * shift, "");
continue;
}
if (tag != FDT_PROP) {
fprintf(stderr, "%*s ** Unknown tag 0x%08x\n", depth * shift, "", tag);
break;
}
sz = fdt32_to_cpu(GET_CELL(p));
s = p_strings + fdt32_to_cpu(GET_CELL(p));
if (version < 16 && sz >= 8)
p = PALIGN(p, 8);
t = p;
p = PALIGN(p + sz, 4);
printf("%*s%s", depth * shift, "", s);
print_data(t, sz);
printf(";\n");
}
}
int main(int argc, char *argv[])
{
char *buf;
if (argc < 2) {
fprintf(stderr, "supply input filename\n");
return 5;
}
buf = utilfdt_read(argv[1]);
if (buf)
dump_blob(buf);
else
return 10;
return 0;
}

366
fdtget.c Normal file
View File

@ -0,0 +1,366 @@
/*
* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
*
* Portions from U-Boot cmd_fdt.c (C) Copyright 2007
* Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
* Based on code written by:
* Pantelis Antoniou <pantelis.antoniou@gmail.com> and
* Matthew McClintock <msm@freescale.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <assert.h>
#include <ctype.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libfdt.h>
#include "util.h"
enum display_mode {
MODE_SHOW_VALUE, /* show values for node properties */
MODE_LIST_PROPS, /* list the properties for a node */
MODE_LIST_SUBNODES, /* list the subnodes of a node */
};
/* Holds information which controls our output and options */
struct display_info {
int type; /* data type (s/i/u/x or 0 for default) */
int size; /* data size (1/2/4) */
enum display_mode mode; /* display mode that we are using */
const char *default_val; /* default value if node/property not found */
};
static void report_error(const char *where, int err)
{
fprintf(stderr, "Error at '%s': %s\n", where, fdt_strerror(err));
}
/**
* Displays data of a given length according to selected options
*
* If a specific data type is provided in disp, then this is used. Otherwise
* we try to guess the data type / size from the contents.
*
* @param disp Display information / options
* @param data Data to display
* @param len Maximum length of buffer
* @return 0 if ok, -1 if data does not match format
*/
static int show_data(struct display_info *disp, const char *data, int len)
{
int i, size;
const uint8_t *p = (const uint8_t *)data;
const char *s;
int value;
int is_string;
char fmt[3];
/* no data, don't print */
if (len == 0)
return 0;
is_string = (disp->type) == 's' ||
(!disp->type && util_is_printable_string(data, len));
if (is_string) {
if (data[len - 1] != '\0') {
fprintf(stderr, "Unterminated string\n");
return -1;
}
for (s = data; s - data < len; s += strlen(s) + 1) {
if (s != data)
printf(" ");
printf("%s", (const char *)s);
}
return 0;
}
size = disp->size;
if (size == -1) {
size = (len % 4) == 0 ? 4 : 1;
} else if (len % size) {
fprintf(stderr, "Property length must be a multiple of "
"selected data size\n");
return -1;
}
fmt[0] = '%';
fmt[1] = disp->type ? disp->type : 'd';
fmt[2] = '\0';
for (i = 0; i < len; i += size, p += size) {
if (i)
printf(" ");
value = size == 4 ? fdt32_to_cpu(*(const uint32_t *)p) :
size == 2 ? (*p << 8) | p[1] : *p;
printf(fmt, value);
}
return 0;
}
/**
* List all properties in a node, one per line.
*
* @param blob FDT blob
* @param node Node to display
* @return 0 if ok, or FDT_ERR... if not.
*/
static int list_properties(const void *blob, int node)
{
const struct fdt_property *data;
const char *name;
int prop;
prop = fdt_first_property_offset(blob, node);
do {
/* Stop silently when there are no more properties */
if (prop < 0)
return prop == -FDT_ERR_NOTFOUND ? 0 : prop;
data = fdt_get_property_by_offset(blob, prop, NULL);
name = fdt_string(blob, fdt32_to_cpu(data->nameoff));
if (name)
puts(name);
prop = fdt_next_property_offset(blob, prop);
} while (1);
}
#define MAX_LEVEL 32 /* how deeply nested we will go */
/**
* List all subnodes in a node, one per line
*
* @param blob FDT blob
* @param node Node to display
* @return 0 if ok, or FDT_ERR... if not.
*/
static int list_subnodes(const void *blob, int node)
{
int nextoffset; /* next node offset from libfdt */
uint32_t tag; /* current tag */
int level = 0; /* keep track of nesting level */
const char *pathp;
int depth = 1; /* the assumed depth of this node */
while (level >= 0) {
tag = fdt_next_tag(blob, node, &nextoffset);
switch (tag) {
case FDT_BEGIN_NODE:
pathp = fdt_get_name(blob, node, NULL);
if (level <= depth) {
if (pathp == NULL)
pathp = "/* NULL pointer error */";
if (*pathp == '\0')
pathp = "/"; /* root is nameless */
if (level == 1)
puts(pathp);
}
level++;
if (level >= MAX_LEVEL) {
printf("Nested too deep, aborting.\n");
return 1;
}
break;
case FDT_END_NODE:
level--;
if (level == 0)
level = -1; /* exit the loop */
break;
case FDT_END:
return 1;
case FDT_PROP:
break;
default:
if (level <= depth)
printf("Unknown tag 0x%08X\n", tag);
return 1;
}
node = nextoffset;
}
return 0;
}
/**
* Show the data for a given node (and perhaps property) according to the
* display option provided.
*
* @param blob FDT blob
* @param disp Display information / options
* @param node Node to display
* @param property Name of property to display, or NULL if none
* @return 0 if ok, -ve on error
*/
static int show_data_for_item(const void *blob, struct display_info *disp,
int node, const char *property)
{
const void *value = NULL;
int len, err = 0;
switch (disp->mode) {
case MODE_LIST_PROPS:
err = list_properties(blob, node);
break;
case MODE_LIST_SUBNODES:
err = list_subnodes(blob, node);
break;
default:
assert(property);
value = fdt_getprop(blob, node, property, &len);
if (value) {
if (show_data(disp, value, len))
err = -1;
else
printf("\n");
} else if (disp->default_val) {
puts(disp->default_val);
} else {
report_error(property, len);
err = -1;
}
break;
}
return err;
}
/**
* Run the main fdtget operation, given a filename and valid arguments
*
* @param disp Display information / options
* @param filename Filename of blob file
* @param arg List of arguments to process
* @param arg_count Number of arguments
* @param return 0 if ok, -ve on error
*/
static int do_fdtget(struct display_info *disp, const char *filename,
char **arg, int arg_count, int args_per_step)
{
char *blob;
const char *prop;
int i, node;
blob = utilfdt_read(filename);
if (!blob)
return -1;
for (i = 0; i + args_per_step <= arg_count; i += args_per_step) {
node = fdt_path_offset(blob, arg[i]);
if (node < 0) {
if (disp->default_val) {
puts(disp->default_val);
continue;
} else {
report_error(arg[i], node);
return -1;
}
}
prop = args_per_step == 1 ? NULL : arg[i + 1];
if (show_data_for_item(blob, disp, node, prop))
return -1;
}
return 0;
}
static const char *usage_msg =
"fdtget - read values from device tree\n"
"\n"
"Each value is printed on a new line.\n\n"
"Usage:\n"
" fdtget <options> <dt file> [<node> <property>]...\n"
" fdtget -p <options> <dt file> [<node> ]...\n"
"Options:\n"
"\t-t <type>\tType of data\n"
"\t-p\t\tList properties for each node\n"
"\t-l\t\tList subnodes for each node\n"
"\t-d\t\tDefault value to display when the property is "
"missing\n"
"\t-h\t\tPrint this help\n\n"
USAGE_TYPE_MSG;
static void usage(const char *msg)
{
if (msg)
fprintf(stderr, "Error: %s\n\n", msg);
fprintf(stderr, "%s", usage_msg);
exit(2);
}
int main(int argc, char *argv[])
{
char *filename = NULL;
struct display_info disp;
int args_per_step = 2;
/* set defaults */
memset(&disp, '\0', sizeof(disp));
disp.size = -1;
disp.mode = MODE_SHOW_VALUE;
for (;;) {
int c = getopt(argc, argv, "d:hlpt:");
if (c == -1)
break;
switch (c) {
case 'h':
case '?':
usage(NULL);
case 't':
if (utilfdt_decode_type(optarg, &disp.type,
&disp.size))
usage("Invalid type string");
break;
case 'p':
disp.mode = MODE_LIST_PROPS;
args_per_step = 1;
break;
case 'l':
disp.mode = MODE_LIST_SUBNODES;
args_per_step = 1;
break;
case 'd':
disp.default_val = optarg;
break;
}
}
if (optind < argc)
filename = argv[optind++];
if (!filename)
usage("Missing filename");
argv += optind;
argc -= optind;
/* Allow no arguments, and silently succeed */
if (!argc)
return 0;
/* Check for node, property arguments */
if (args_per_step == 2 && (argc % 2))
usage("Must have an even number of arguments");
if (do_fdtget(&disp, filename, argv, argc, args_per_step))
return 1;
return 0;
}

362
fdtput.c Normal file
View File

@ -0,0 +1,362 @@
/*
* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <assert.h>
#include <ctype.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libfdt.h>
#include "util.h"
/* These are the operations we support */
enum oper_type {
OPER_WRITE_PROP, /* Write a property in a node */
OPER_CREATE_NODE, /* Create a new node */
};
struct display_info {
enum oper_type oper; /* operation to perform */
int type; /* data type (s/i/u/x or 0 for default) */
int size; /* data size (1/2/4) */
int verbose; /* verbose output */
int auto_path; /* automatically create all path components */
};
/**
* Report an error with a particular node.
*
* @param name Node name to report error on
* @param namelen Length of node name, or -1 to use entire string
* @param err Error number to report (-FDT_ERR_...)
*/
static void report_error(const char *name, int namelen, int err)
{
if (namelen == -1)
namelen = strlen(name);
fprintf(stderr, "Error at '%1.*s': %s\n", namelen, name,
fdt_strerror(err));
}
/**
* Encode a series of arguments in a property value.
*
* @param disp Display information / options
* @param arg List of arguments from command line
* @param arg_count Number of arguments (may be 0)
* @param valuep Returns buffer containing value
* @param *value_len Returns length of value encoded
*/
static int encode_value(struct display_info *disp, char **arg, int arg_count,
char **valuep, int *value_len)
{
char *value = NULL; /* holding area for value */
int value_size = 0; /* size of holding area */
char *ptr; /* pointer to current value position */
int len; /* length of this cell/string/byte */
int ival;
int upto; /* the number of bytes we have written to buf */
char fmt[3];
upto = 0;
if (disp->verbose)
fprintf(stderr, "Decoding value:\n");
fmt[0] = '%';
fmt[1] = disp->type ? disp->type : 'd';
fmt[2] = '\0';
for (; arg_count > 0; arg++, arg_count--, upto += len) {
/* assume integer unless told otherwise */
if (disp->type == 's')
len = strlen(*arg) + 1;
else
len = disp->size == -1 ? 4 : disp->size;
/* enlarge our value buffer by a suitable margin if needed */
if (upto + len > value_size) {
value_size = (upto + len) + 500;
value = realloc(value, value_size);
if (!value) {
fprintf(stderr, "Out of mmory: cannot alloc "
"%d bytes\n", value_size);
return -1;
}
}
ptr = value + upto;
if (disp->type == 's') {
memcpy(ptr, *arg, len);
if (disp->verbose)
fprintf(stderr, "\tstring: '%s'\n", ptr);
} else {
int *iptr = (int *)ptr;
sscanf(*arg, fmt, &ival);
if (len == 4)
*iptr = cpu_to_fdt32(ival);
else
*ptr = (uint8_t)ival;
if (disp->verbose) {
fprintf(stderr, "\t%s: %d\n",
disp->size == 1 ? "byte" :
disp->size == 2 ? "short" : "int",
ival);
}
}
}
*value_len = upto;
*valuep = value;
if (disp->verbose)
fprintf(stderr, "Value size %d\n", upto);
return 0;
}
static int store_key_value(void *blob, const char *node_name,
const char *property, const char *buf, int len)
{
int node;
int err;
node = fdt_path_offset(blob, node_name);
if (node < 0) {
report_error(node_name, -1, node);
return -1;
}
err = fdt_setprop(blob, node, property, buf, len);
if (err) {
report_error(property, -1, err);
return -1;
}
return 0;
}
/**
* Create paths as needed for all components of a path
*
* Any components of the path that do not exist are created. Errors are
* reported.
*
* @param blob FDT blob to write into
* @param in_path Path to process
* @return 0 if ok, -1 on error
*/
static int create_paths(void *blob, const char *in_path)
{
const char *path = in_path;
const char *sep;
int node, offset = 0;
/* skip leading '/' */
while (*path == '/')
path++;
for (sep = path; *sep; path = sep + 1, offset = node) {
/* equivalent to strchrnul(), but it requires _GNU_SOURCE */
sep = strchr(path, '/');
if (!sep)
sep = path + strlen(path);
node = fdt_subnode_offset_namelen(blob, offset, path,
sep - path);
if (node == -FDT_ERR_NOTFOUND) {
node = fdt_add_subnode_namelen(blob, offset, path,
sep - path);
}
if (node < 0) {
report_error(path, sep - path, node);
return -1;
}
}
return 0;
}
/**
* Create a new node in the fdt.
*
* This will overwrite the node_name string. Any error is reported.
*
* TODO: Perhaps create fdt_path_offset_namelen() so we don't need to do this.
*
* @param blob FDT blob to write into
* @param node_name Name of node to create
* @return new node offset if found, or -1 on failure
*/
static int create_node(void *blob, const char *node_name)
{
int node = 0;
char *p;
p = strrchr(node_name, '/');
if (!p) {
report_error(node_name, -1, -FDT_ERR_BADPATH);
return -1;
}
*p = '\0';
if (p > node_name) {
node = fdt_path_offset(blob, node_name);
if (node < 0) {
report_error(node_name, -1, node);
return -1;
}
}
node = fdt_add_subnode(blob, node, p + 1);
if (node < 0) {
report_error(p + 1, -1, node);
return -1;
}
return 0;
}
static int do_fdtput(struct display_info *disp, const char *filename,
char **arg, int arg_count)
{
char *value;
char *blob;
int len, ret = 0;
blob = utilfdt_read(filename);
if (!blob)
return -1;
switch (disp->oper) {
case OPER_WRITE_PROP:
/*
* Convert the arguments into a single binary value, then
* store them into the property.
*/
assert(arg_count >= 2);
if (disp->auto_path && create_paths(blob, *arg))
return -1;
if (encode_value(disp, arg + 2, arg_count - 2, &value, &len) ||
store_key_value(blob, *arg, arg[1], value, len))
ret = -1;
break;
case OPER_CREATE_NODE:
for (; ret >= 0 && arg_count--; arg++) {
if (disp->auto_path)
ret = create_paths(blob, *arg);
else
ret = create_node(blob, *arg);
}
break;
}
if (ret >= 0)
ret = utilfdt_write(filename, blob);
free(blob);
return ret;
}
static const char *usage_msg =
"fdtput - write a property value to a device tree\n"
"\n"
"The command line arguments are joined together into a single value.\n"
"\n"
"Usage:\n"
" fdtput <options> <dt file> <node> <property> [<value>...]\n"
" fdtput -c <options> <dt file> [<node>...]\n"
"Options:\n"
"\t-c\t\tCreate nodes if they don't already exist\n"
"\t-p\t\tAutomatically create nodes as needed for the node path\n"
"\t-t <type>\tType of data\n"
"\t-v\t\tVerbose: display each value decoded from command line\n"
"\t-h\t\tPrint this help\n\n"
USAGE_TYPE_MSG;
static void usage(const char *msg)
{
if (msg)
fprintf(stderr, "Error: %s\n\n", msg);
fprintf(stderr, "%s", usage_msg);
exit(2);
}
int main(int argc, char *argv[])
{
struct display_info disp;
char *filename = NULL;
memset(&disp, '\0', sizeof(disp));
disp.size = -1;
disp.oper = OPER_WRITE_PROP;
for (;;) {
int c = getopt(argc, argv, "chpt:v");
if (c == -1)
break;
/*
* TODO: add options to:
* - delete property
* - delete node (optionally recursively)
* - rename node
* - pack fdt before writing
* - set amount of free space when writing
* - expand fdt if value doesn't fit
*/
switch (c) {
case 'c':
disp.oper = OPER_CREATE_NODE;
break;
case 'h':
case '?':
usage(NULL);
case 'p':
disp.auto_path = 1;
break;
case 't':
if (utilfdt_decode_type(optarg, &disp.type,
&disp.size))
usage("Invalid type string");
break;
case 'v':
disp.verbose = 1;
break;
}
}
if (optind < argc)
filename = argv[optind++];
if (!filename)
usage("Missing filename");
argv += optind;
argc -= optind;
if (disp.oper == OPER_WRITE_PROP) {
if (argc < 1)
usage("Missing node");
if (argc < 2)
usage("Missing property");
}
if (do_fdtput(&disp, filename, argv, argc))
return 1;
return 0;
}

84
libfdt/fdt_empty_tree.c Normal file
View File

@ -0,0 +1,84 @@
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2012 David Gibson, IBM Corporation.
*
* libfdt is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
*
* a) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
* Alternatively,
*
* b) Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"
#include <fdt.h>
#include <libfdt.h>
#include "libfdt_internal.h"
int fdt_create_empty_tree(void *buf, int bufsize)
{
int err;
err = fdt_create(buf, bufsize);
if (err)
return err;
err = fdt_finish_reservemap(buf);
if (err)
return err;
err = fdt_begin_node(buf, "");
if (err)
return err;
err = fdt_end_node(buf);
if (err)
return err;
err = fdt_finish(buf);
if (err)
return err;
return fdt_open_into(buf, buf, bufsize);
}

8
tests/appendprop.dts Normal file
View File

@ -0,0 +1,8 @@
/dts-v1/;
/ {
prop-str = "hello world", "nastystring: \a\b\t\n\v\f\r\\\"";
prop-int64 = /bits/ 64 <0xdeadbeef01abcdef 0xdeadbeef01abcdef>;
prop-int = <0xdeadbeef 123456789>;
prop-bytes = [00010203040001020304];
};

71
tests/appendprop1.c Normal file
View File

@ -0,0 +1,71 @@
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_appendprop()
* Copyright (C) 2006 David Gibson, IBM Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdint.h>
#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
#include "testdata.h"
#define SPACE 65536
#define CHECK(code) \
{ \
err = (code); \
if (err) \
FAIL(#code ": %s", fdt_strerror(err)); \
}
int main(int argc, char *argv[])
{
void *fdt;
int err;
uint8_t bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04};
test_init(argc, argv);
/* Create an empty tree first */
fdt = xmalloc(SPACE);
CHECK(fdt_create(fdt, SPACE));
CHECK(fdt_finish_reservemap(fdt));
CHECK(fdt_begin_node(fdt, ""));
CHECK(fdt_end_node(fdt));
CHECK(fdt_finish(fdt));
/* Now use appendprop to add properties */
CHECK(fdt_open_into(fdt, fdt, SPACE));
CHECK(fdt_appendprop(fdt, 0, "prop-bytes", bytes, sizeof(bytes)));
CHECK(fdt_appendprop_cell(fdt, 0, "prop-int", TEST_VALUE_1));
CHECK(fdt_appendprop_u64(fdt, 0, "prop-int64", TEST_VALUE64_1));
CHECK(fdt_appendprop_string(fdt, 0, "prop-str", TEST_STRING_1));
CHECK(fdt_pack(fdt));
save_blob("appendprop1.test.dtb", fdt);
PASS();
}

65
tests/appendprop2.c Normal file
View File

@ -0,0 +1,65 @@
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_appendprop()
* Copyright (C) 2006 David Gibson, IBM Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdint.h>
#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
#include "testdata.h"
#define SPACE 65536
#define CHECK(code) \
{ \
err = (code); \
if (err) \
FAIL(#code ": %s", fdt_strerror(err)); \
}
int main(int argc, char *argv[])
{
void *fdt, *buf;
int err;
uint8_t bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04};
test_init(argc, argv);
fdt = load_blob_arg(argc, argv);
buf = xmalloc(SPACE);
CHECK(fdt_open_into(fdt, buf, SPACE));
fdt = buf;
CHECK(fdt_appendprop(fdt, 0, "prop-bytes", bytes, sizeof(bytes)));
CHECK(fdt_appendprop_cell(fdt, 0, "prop-int", TEST_VALUE_2));
CHECK(fdt_appendprop_u64(fdt, 0, "prop-int64", TEST_VALUE64_1));
CHECK(fdt_appendprop_string(fdt, 0, "prop-str", TEST_STRING_2));
CHECK(fdt_pack(fdt));
save_blob("appendprop2.test.dtb", fdt);
PASS();
}

16
tests/boot-cpuid.dts Normal file
View File

@ -0,0 +1,16 @@
/dts-v1/;
/ {
cpus {
cpu@10 {
device_type = "cpu";
compatible = "fake-cpu";
reg = <0x10>;
};
cpu@11 {
device_type = "cpu";
compatible = "fake-cpu";
reg = <0x11>;
};
};
};

50
tests/char_literal.c Normal file
View File

@ -0,0 +1,50 @@
/*
* libfdt - Flat Device Tree manipulation
* Testcase for character literals in dtc
* Copyright (C) 2006 David Gibson, IBM Corporation.
* Copyright (C) 2011 The Chromium Authors. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
#include "testdata.h"
int main(int argc, char *argv[])
{
void *fdt;
uint32_t expected_cells[5];
expected_cells[0] = cpu_to_fdt32((unsigned char)TEST_CHAR1);
expected_cells[1] = cpu_to_fdt32((unsigned char)TEST_CHAR2);
expected_cells[2] = cpu_to_fdt32((unsigned char)TEST_CHAR3);
expected_cells[3] = cpu_to_fdt32((unsigned char)TEST_CHAR4);
expected_cells[4] = cpu_to_fdt32((unsigned char)TEST_CHAR5);
test_init(argc, argv);
fdt = load_blob_arg(argc, argv);
check_getprop(fdt, 0, "char-literal-cells",
sizeof(expected_cells), expected_cells);
PASS();
}

5
tests/char_literal.dts Normal file
View File

@ -0,0 +1,5 @@
/dts-v1/;
/ {
char-literal-cells = <'\r' 'b' '\0' '\'' '\xff'>;
};

1
tests/dependencies.cmp Normal file
View File

@ -0,0 +1 @@
dependencies.test.dtb: dependencies.dts deps_inc1.dtsi deps_inc2.dtsi

6
tests/dependencies.dts Normal file
View File

@ -0,0 +1,6 @@
/dts-v1/;
/include/ "deps_inc1.dtsi"
/ {
};

1
tests/deps_inc1.dtsi Normal file
View File

@ -0,0 +1 @@
/include/ "deps_inc2.dtsi"

1
tests/deps_inc2.dtsi Normal file
View File

@ -0,0 +1 @@
/* Empty */

164
tests/dtb_reverse.c Normal file
View File

@ -0,0 +1,164 @@
/*
* libfdt - Flat Device Tree manipulation
* Tests if two given dtbs are structurally equal (including order)
* Copyright (C) 2010 David Gibson, IBM Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <limits.h>
#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
#include "testdata.h"
#define CHECK(code) \
{ \
err = (code); \
if (err) \
FAIL(#code ": %s", fdt_strerror(err)); \
}
static void reverse_reservemap(void *in, void *out, int n)
{
int err;
uint64_t addr, size;
verbose_printf("reverse_reservemap(): %d/%d\n",
n, fdt_num_mem_rsv(in));
if (n < (fdt_num_mem_rsv(in)-1))
reverse_reservemap(in, out, n+1);
CHECK(fdt_get_mem_rsv(in, n, &addr, &size));
CHECK(fdt_add_reservemap_entry(out, addr, size));
verbose_printf("Added entry 0x%llx 0x%llx\n",
(unsigned long long)addr, (unsigned long long)size);
}
static void reverse_properties(void *in, void *out, int offset)
{
int err;
int len;
const char *name;
const void *data;
data = fdt_getprop_by_offset(in, offset, &name, &len);
if (!data)
FAIL("fdt_getprop_by_offset(): %s\n", fdt_strerror(len));
verbose_printf("reverse_properties(): offset=%d name=%s\n",
offset, name);
offset = fdt_next_property_offset(in, offset);
if (offset >= 0)
reverse_properties(in, out, offset);
else if (offset != -FDT_ERR_NOTFOUND)
FAIL("fdt_next_property_offset(): %s\n", fdt_strerror(offset));
CHECK(fdt_property(out, name, data, len));
verbose_printf(" -> output property %s\n", name);
}
static void reverse_node(void *in, void *out, int nodeoffset);
static void reverse_children(void *in, void *out, int offset)
{
int err;
int nextoffset = offset;
int depth = 1;
do {
char path[PATH_MAX];
CHECK(fdt_get_path(in, nextoffset, path, sizeof(path)));
verbose_printf("reverse_children() offset=%d nextoffset=%d [%s]"
" depth=%d\n", offset, nextoffset, path, depth);
nextoffset = fdt_next_node(in, nextoffset, &depth);
} while ((depth >= 0) && (depth != 1));
if (depth == 1)
reverse_children(in, out, nextoffset);
reverse_node(in, out, offset);
}
static void reverse_node(void *in, void *out, int nodeoffset)
{
const char *name = fdt_get_name(in, nodeoffset, NULL);
char path[PATH_MAX];
int err;
int offset;
int depth = 0;
CHECK(fdt_get_path(in, nodeoffset, path, sizeof(path)));
verbose_printf("reverse_node(): nodeoffset=%d [%s]\n",
nodeoffset, path);
CHECK(fdt_begin_node(out, name));
offset = fdt_first_property_offset(in, nodeoffset);
if (offset >= 0)
reverse_properties(in, out, offset);
else if (offset != -FDT_ERR_NOTFOUND)
FAIL("fdt_first_property(): %s\n", fdt_strerror(offset));
offset = fdt_next_node(in, nodeoffset, &depth);
if (depth == 1)
reverse_children(in, out, offset);
CHECK(fdt_end_node(out));
}
int main(int argc, char *argv[])
{
void *in, *out;
char outname[PATH_MAX];
int bufsize;
int err;
test_init(argc, argv);
if (argc != 2)
CONFIG("Usage: %s <dtb file>", argv[0]);
in = load_blob(argv[1]);
sprintf(outname, "%s.reversed.test.dtb", argv[1]);
bufsize = fdt_totalsize(in);
out = xmalloc(bufsize);
CHECK(fdt_create(out, bufsize));
fdt_set_boot_cpuid_phys(out, fdt_boot_cpuid_phys(in));
reverse_reservemap(in, out, 0);
CHECK(fdt_finish_reservemap(out));
reverse_node(in, out, 0);
CHECK(fdt_finish(out));
save_blob(outname, out);
PASS();
}

View File

@ -0,0 +1,224 @@
/*
* libfdt - Flat Device Tree manipulation
* Tests if two given dtbs are structurally equal (including order)
* Copyright (C) 2007 David Gibson, IBM Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <limits.h>
#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
#include "testdata.h"
int notequal; /* = 0 */
#define MISMATCH(fmt, ...) \
do { \
if (notequal) \
PASS(); \
else \
FAIL(fmt, ##__VA_ARGS__); \
} while (0)
#define MATCH() \
do { \
if (!notequal) \
PASS(); \
else \
FAIL("Trees match which shouldn't"); \
} while (0)
#define CHECK(code) \
{ \
err = (code); \
if (err) \
FAIL(#code ": %s", fdt_strerror(err)); \
}
static int mem_rsv_cmp(const void *p1, const void *p2)
{
const struct fdt_reserve_entry *re1 = p1;
const struct fdt_reserve_entry *re2 = p2;
if (re1->address < re2->address)
return -1;
else if (re1->address > re2->address)
return 1;
if (re1->size < re2->size)
return -1;
else if (re1->size > re2->size)
return 1;
return 0;
}
static void compare_mem_rsv(void *fdt1, void *fdt2)
{
int i;
uint64_t addr1, size1, addr2, size2;
int err;
if (fdt_num_mem_rsv(fdt1) != fdt_num_mem_rsv(fdt2))
MISMATCH("Trees have different number of reserve entries");
qsort((char *)fdt1 + fdt_off_mem_rsvmap(fdt1), fdt_num_mem_rsv(fdt1),
sizeof(struct fdt_reserve_entry), mem_rsv_cmp);
qsort((char *)fdt2 + fdt_off_mem_rsvmap(fdt2), fdt_num_mem_rsv(fdt2),
sizeof(struct fdt_reserve_entry), mem_rsv_cmp);
for (i = 0; i < fdt_num_mem_rsv(fdt1); i++) {
CHECK(fdt_get_mem_rsv(fdt1, i, &addr1, &size1));
CHECK(fdt_get_mem_rsv(fdt2, i, &addr2, &size2));
if ((addr1 != addr2) || (size1 != size2))
MISMATCH("Mismatch in reserve entry %d: "
"(0x%llx, 0x%llx) != (0x%llx, 0x%llx)", i,
(unsigned long long)addr1,
(unsigned long long)size1,
(unsigned long long)addr2,
(unsigned long long)size2);
}
}
static void compare_properties(const void *fdt1, int offset1,
const void *fdt2, int offset2)
{
int offset = offset1;
/* Check the properties */
for (offset = fdt_first_property_offset(fdt1, offset1);
offset >= 0;
offset = fdt_next_property_offset(fdt1, offset)) {
const char *name;
int len1, len2;
const void *data1, *data2;
int i;
data1 = fdt_getprop_by_offset(fdt1, offset, &name, &len1);
if (!data1)
FAIL("fdt_getprop_by_offset(): %s\n",
fdt_strerror(len1));
verbose_printf("Property '%s'\n", name);
data2 = fdt_getprop(fdt2, offset2, name, &len2);
if (!data2) {
if (len2 == -FDT_ERR_NOTFOUND)
MISMATCH("Property '%s' missing\n", name);
else
FAIL("fdt_get_property(): %s\n",
fdt_strerror(len2));
}
verbose_printf("len1=%d data1=", len1);
for (i = 0; i < len1; i++)
verbose_printf(" %02x", ((const char *)data1)[i]);
verbose_printf("\nlen2=%d data2=", len2);
for (i = 0; i < len1; i++)
verbose_printf(" %02x", ((const char *)data2)[i]);
verbose_printf("\n");
if (len1 != len2)
MISMATCH("Property '%s' mismatched length %d vs. %d\n",
name, len1, len2);
else if (memcmp(data1, data2, len1) != 0)
MISMATCH("Property '%s' mismatched value\n", name);
}
}
static void compare_node(const void *fdt1, int offset1,
const void *fdt2, int offset2);
static void compare_subnodes(const void *fdt1, int offset1,
const void *fdt2, int offset2,
int recurse)
{
int coffset1, coffset2, depth;
for (depth = 0, coffset1 = offset1;
(coffset1 >= 0) && (depth >= 0);
coffset1 = fdt_next_node(fdt1, coffset1, &depth))
if (depth == 1) {
const char *name = fdt_get_name(fdt1, coffset1, NULL);
verbose_printf("Subnode %s\n", name);
coffset2 = fdt_subnode_offset(fdt2, offset2, name);
if (coffset2 == -FDT_ERR_NOTFOUND)
MISMATCH("Subnode %s missing\n", name);
else if (coffset2 < 0)
FAIL("fdt_subnode_offset(): %s\n",
fdt_strerror(coffset2));
if (recurse)
compare_node(fdt1, coffset1, fdt2, coffset2);
}
}
static void compare_node(const void *fdt1, int offset1,
const void *fdt2, int offset2)
{
int err;
char path1[PATH_MAX], path2[PATH_MAX];
CHECK(fdt_get_path(fdt1, offset1, path1, sizeof(path1)));
CHECK(fdt_get_path(fdt2, offset2, path2, sizeof(path2)));
if (!streq(path1, path2))
TEST_BUG("Path mismatch %s vs. %s\n", path1, path2);
verbose_printf("Checking %s\n", path1);
compare_properties(fdt1, offset1, fdt2, offset2);
compare_properties(fdt2, offset2, fdt1, offset1);
compare_subnodes(fdt1, offset1, fdt2, offset2, 1);
compare_subnodes(fdt2, offset2, fdt1, offset1, 0);
}
int main(int argc, char *argv[])
{
void *fdt1, *fdt2;
uint32_t cpuid1, cpuid2;
test_init(argc, argv);
if ((argc != 3)
&& ((argc != 4) || !streq(argv[1], "-n")))
CONFIG("Usage: %s [-n] <dtb file> <dtb file>", argv[0]);
if (argc == 4)
notequal = 1;
fdt1 = load_blob(argv[argc-2]);
fdt2 = load_blob(argv[argc-1]);
compare_mem_rsv(fdt1, fdt2);
compare_node(fdt1, 0, fdt2, 0);
cpuid1 = fdt_boot_cpuid_phys(fdt1);
cpuid2 = fdt_boot_cpuid_phys(fdt2);
if (cpuid1 != cpuid2)
MISMATCH("boot_cpuid_phys mismatch 0x%x != 0x%x",
cpuid1, cpuid2);
MATCH();
}

30
tests/dtc-fails.sh Executable file
View File

@ -0,0 +1,30 @@
#! /bin/sh
. ./tests.sh
if [ "$1" = "-n" ]; then
NEG="$1"
shift
fi
OUTPUT="$1"
shift
verbose_run $VALGRIND "$DTC" -o "$OUTPUT" "$@"
ret="$?"
FAIL_IF_SIGNAL $ret
if [ -n "$NEG" ]; then
if [ ! -e "$OUTPUT" ]; then
FAIL "Produced no output"
fi
else
if [ -e "$OUTPUT" ]; then
FAIL "Incorrectly produced output"
fi
fi
rm -f "$OUTPUT"
PASS

24
tests/fdtget-runtest.sh Executable file
View File

@ -0,0 +1,24 @@
#! /bin/sh
. ./tests.sh
LOG=tmp.log.$$
EXPECT=tmp.expect.$$
rm -f $LOG $EXPECT
trap "rm -f $LOG $EXPECT" 0
expect="$1"
/bin/echo -e $expect >$EXPECT
shift
verbose_run_log_check "$LOG" $VALGRIND $DTGET "$@"
if cmp $EXPECT $LOG>/dev/null; then
PASS
else
if [ -z "$QUIET_TEST" ]; then
echo "EXPECTED :-:"
cat $EXPECT
fi
FAIL "Results differ from expected"
fi

39
tests/fdtput-runtest.sh Executable file
View File

@ -0,0 +1,39 @@
#! /bin/sh
# Run script for fdtput tests
# We run fdtput to update the device tree, thn fdtget to check it
# Usage
# fdtput-runtest.sh name expected_output dtb_file node property flags value
. ./tests.sh
LOG=tmp.log.$$
EXPECT=tmp.expect.$$
rm -f $LOG $EXPECT
trap "rm -f $LOG $EXPECT" 0
expect="$1"
echo $expect >$EXPECT
dtb="$2"
node="$3"
property="$4"
flags="$5"
shift 5
value="$@"
# First run fdtput
verbose_run_check $VALGRIND "$DTPUT" "$dtb" "$node" "$property" $value $flags
# Now fdtget to read the value
verbose_run_log_check "$LOG" $VALGRIND "$DTGET" "$dtb" "$node" "$property" $flags
if cmp $EXPECT $LOG >/dev/null; then
PASS
else
if [ -z "$QUIET_TEST" ]; then
echo "EXPECTED :-:"
cat $EXPECT
fi
FAIL "Results differ from expected"
fi

1
tests/include5a.dts Normal file
View File

@ -0,0 +1 @@
= /bits/ 64 <0xdeadbeef01abcdef>

117
tests/integer-expressions.c Normal file
View File

@ -0,0 +1,117 @@
/*
* Testcase for dtc expression support
*
* Copyright (C) 2008 David Gibson, IBM Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
#include "testdata.h"
struct test_expr {
const char *expr;
uint32_t result;
} expr_table[] = {
#define TE(expr) { #expr, (expr) }
TE(0xdeadbeef),
TE(-0x21524111),
TE(1+1),
TE(2*3),
TE(4/2),
TE(10/3),
TE(19%4),
TE(1 << 13),
TE(0x1000 >> 4),
TE(3*2+1), TE(3*(2+1)),
TE(1+2*3), TE((1+2)*3),
TE(1 < 2), TE(2 < 1), TE(1 < 1),
TE(1 <= 2), TE(2 <= 1), TE(1 <= 1),
TE(1 > 2), TE(2 > 1), TE(1 > 1),
TE(1 >= 2), TE(2 >= 1), TE(1 >= 1),
TE(1 == 1), TE(1 == 2),
TE(1 != 1), TE(1 != 2),
TE(0xabcdabcd & 0xffff0000),
TE(0xdead4110 ^ 0xf0f0f0f0),
TE(0xabcd0000 | 0x0000abcd),
TE(~0x21524110),
TE(~~0xdeadbeef),
TE(0 && 0), TE(17 && 0), TE(0 && 17), TE(17 && 17),
TE(0 || 0), TE(17 || 0), TE(0 || 17), TE(17 || 17),
TE(!0), TE(!1), TE(!17), TE(!!0), TE(!!17),
TE(0 ? 17 : 39), TE(1 ? 17 : 39), TE(17 ? 0xdeadbeef : 0xabcd1234),
TE(11 * 257 * 1321517ULL),
TE(123456790 - 4/2 + 17%4),
};
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
int main(int argc, char *argv[])
{
void *fdt;
const uint32_t *res;
int reslen;
int i;
test_init(argc, argv);
if ((argc == 3) && (strcmp(argv[1], "-g") == 0)) {
FILE *f = fopen(argv[2], "w");
if (!f)
FAIL("Couldn't open \"%s\" for output: %s\n",
argv[2], strerror(errno));
fprintf(f, "/dts-v1/;\n");
fprintf(f, "/ {\n");
fprintf(f, "\texpressions = <\n");
for (i = 0; i < ARRAY_SIZE(expr_table); i++)
fprintf(f, "\t\t(%s)\n", expr_table[i].expr);
fprintf(f, "\t>;\n");
fprintf(f, "};\n");
fclose(f);
} else {
fdt = load_blob_arg(argc, argv);
res = fdt_getprop(fdt, 0, "expressions", &reslen);
if (!res)
FAIL("Error retreiving expression results: %s\n",
fdt_strerror(reslen));
if (reslen != (ARRAY_SIZE(expr_table) * sizeof(uint32_t)))
FAIL("Unexpected length of results %d instead of %zd\n",
reslen, ARRAY_SIZE(expr_table) * sizeof(uint32_t));
for (i = 0; i < ARRAY_SIZE(expr_table); i++)
if (fdt32_to_cpu(res[i]) != expr_table[i].result)
FAIL("Incorrect result for expression \"%s\","
" 0x%x instead of 0x%x\n",
expr_table[i].expr, fdt32_to_cpu(res[i]),
expr_table[i].result);
}
PASS();
}

15
tests/label_repeated.dts Normal file
View File

@ -0,0 +1,15 @@
/dts-v1/;
/ {
l0: prop = "foo";
l1: node {
};
};
/ {
l0: prop = "foo";
l1: node {
};
};

35
tests/lorem.txt Normal file
View File

@ -0,0 +1,35 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris eros
arcu, egestas non pellentesque non, euismod eu nibh. Proin arcu metus,
dapibus vitae sodales rhoncus, suscipit vel nulla. Etiam lorem est,
aliquam ut fringilla sit amet, condimentum et quam. Duis eu arcu odio,
at pulvinar nisi. Morbi condimentum eros ut turpis rhoncus
pharetra. Pellentesque habitant morbi tristique senectus et netus et
malesuada fames ac turpis egestas. Nam et nulla enim. Etiam fringilla
eleifend neque, at posuere ante lacinia a. Duis orci tortor, dictum ac
gravida ac, euismod eu leo. Sed eget dolor tortor. Pellentesque
venenatis, lectus eu vulputate porta, libero ipsum convallis mi, sit
amet vehicula arcu elit sit amet odio.
Fusce iaculis massa metus, id sagittis diam. Praesent molestie ante
vel odio tincidunt auctor. Cum sociis natoque penatibus et magnis dis
parturient montes, nascetur ridiculus mus. Duis rutrum vehicula nisl
eget condimentum. In in justo nisl. Nullam id arcu at nisl eleifend
pretium. Nulla interdum ligula id elit mollis dictum a sit amet
quam. Nullam iaculis laoreet ipsum at tempus. Vestibulum in cursus
dui. Curabitur porta lectus eget urna bibendum congue eget elementum
nisi. Proin sit amet lectus ut neque iaculis consectetur eu sit amet
nibh. Maecenas rhoncus dolor ac nunc gravida blandit. Fusce sem felis,
aliquam a porttitor a, porta quis odio.
Nunc purus lorem, sollicitudin non ultricies id, porta vitae
enim. Nulla tristique gravida leo ut suscipit. Phasellus vitae turpis
libero. Proin ac purus dolor, in suscipit magna. Sed et enim
arcu. Morbi semper aliquet suscipit. Aenean laoreet condimentum massa,
eu pharetra magna fermentum ut. Morbi euismod convallis tortor, eget
fringilla lacus sagittis non. Nullam bibendum posuere feugiat.
In at pulvinar massa. Mauris nunc lectus, mollis et malesuada
pharetra, cursus sed lacus. Integer dolor urna, interdum a mollis at,
vestibulum non nisl. Sed in urna tortor. Mauris arcu felis, volutpat
quis euismod vel, congue sit amet ipsum. Morbi in aliquet purus. Duis
cras amet.

42
tests/multilabel.dts Normal file
View File

@ -0,0 +1,42 @@
/dts-v1/;
m1: mq: /memreserve/ 0 0x1000;
/ {
p0: pw: prop = "foo";
/* Explicit phandles */
n1: nx: node1 {
linux,phandle = <0x2000>;
ref = <&{/node2}>; /* reference precedes target */
p1: px: lref = <&ny>;
};
ny: n2: node2 {
p2: py: phandle = <0x1>;
ref = <&{/node1}>; /* reference after target */
lref = <&nx>;
};
/* Implicit phandles */
n3: node3 {
p3: ref = <&{/node4}>;
lref = <&n4>;
};
n4: node4 {
p4: prop;
};
/* Explicit phandle with implicit value */
/* This self-reference is the standard way to tag a node as requiring
* a phandle (perhaps for reference by nodes that will be dynamically
* added) without explicitly allocating it a phandle.
* The self-reference requires some special internal handling, though
* so check it actually works */
n5: nz: node5 {
linux,phandle = <&n5>;
phandle = <&nz>;
n1 = &n1;
n2 = &n2;
n3 = &n3;
};
};

View File

@ -0,0 +1,66 @@
/dts-v1/;
m1: mq: /memreserve/ 0 0x1000;
/ {
p0: pw: prop = "foo";
/* Explicit phandles */
n1: node1 {
linux,phandle = <0x2000>;
ref = <&{/node2}>; /* reference precedes target */
p1: lref;
};
node2 {
phandle = <0x1>;
ref = <&{/node1}>; /* reference after target */
lref = <&nx>;
};
/* Implicit phandles */
n3: node3 {
p3: ref = <&{/node4}>;
lref = <&n4>;
};
n4: node4 {
p4: prop = "foo";
};
/* Explicit phandle with implicit value */
/* This self-reference is the standard way to tag a node as requiring
* a phandle (perhaps for reference by nodes that will be dynamically
* added) without explicitly allocating it a phandle.
* The self-reference requires some special internal handling, though
* so check it actually works */
n5: nz: node5 {
linux,phandle = <&n5>;
phandle = <&nz>;
n1 = &n1;
n2 = &n2;
n3 = &n3;
};
};
/ {
/* Append labels (also changes property content) */
nx: node1 {
px: lref = <&ny>;
};
/* Add multiple labels */
ny: n2: node2 {
/* Add a label to a property */
p2: py: phandle = <0x1>;
};
/* Reassigning the same label should be a no-op */
n3: node3 {
p3: ref = <&{/node4}>;
};
/* Redefining a node/property should not remove labels */
node4 {
prop;
};
};

View File

@ -0,0 +1,10 @@
/dts-v1/;
/ {
label: node {
};
};
/* Try to redefine a node using a non-existent label */
&nosuchnode {
};

15
tests/reuse-label.dts Normal file
View File

@ -0,0 +1,15 @@
/dts-v1/;
/ {
label: property1 = "foo";
label: property2 = "bar";
test1 = &label;
label: node1 {
prop = "foo";
};
label: node2 {
prop = "bar";
};
};

10
tests/reuse-label1.dts Normal file
View File

@ -0,0 +1,10 @@
/dts-v1/;
/ {
label: node1 {
prop = "foo";
};
label: node2 {
prop = "bar";
};
};

6
tests/reuse-label2.dts Normal file
View File

@ -0,0 +1,6 @@
/dts-v1/;
/ {
label: property1 = "foo";
label: property2 = "bar";
};

9
tests/reuse-label3.dts Normal file
View File

@ -0,0 +1,9 @@
/dts-v1/;
/ {
label: property = "foo";
label: node {
property = "foo";
};
};

5
tests/reuse-label4.dts Normal file
View File

@ -0,0 +1,5 @@
/dts-v1/;
/ {
property = label: "foo" label:;
};

6
tests/reuse-label5.dts Normal file
View File

@ -0,0 +1,6 @@
/dts-v1/;
/ {
prop1 = label: "foo";
prop2 = "bar" label:;
};

6
tests/reuse-label6.dts Normal file
View File

@ -0,0 +1,6 @@
/dts-v1/;
/ {
label: prop1 = "foo";
prop2 = "bar" label:;
};

View File

@ -0,0 +1,4 @@
/include/ "search_test2.dtsi"
/ {
};

View File

@ -0,0 +1,3 @@
/ {
};

View File

@ -0,0 +1,6 @@
/dts-v1/;
/include/ "search_test_c.dtsi"
/ {
};

View File

@ -0,0 +1,4 @@
/include/ "search_test_b2.dtsi"
/ {
};

View File

@ -0,0 +1,5 @@
/include/ "search_test.dtsi"
/ {
};

View File

@ -0,0 +1,2 @@
/ {
};

6
tests/search_paths.dts Normal file
View File

@ -0,0 +1,6 @@
/dts-v1/;
/include/ "search_test.dtsi"
/ {
};

6
tests/search_paths_b.dts Normal file
View File

@ -0,0 +1,6 @@
/dts-v1/;
/include/ "search_test_b.dtsi"
/ {
};

84
tests/sized_cells.c Normal file
View File

@ -0,0 +1,84 @@
/*
* libfdt - Flat Device Tree manipulation
* Testcase for variable sized cells in dtc
* Copyright (C) 2006 David Gibson, IBM Corporation.
* Copyright (C) 2011 The Chromium Authors. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <fdt.h>
#include <libfdt.h>
#include "tests.h"
#include "testdata.h"
static void check_compare_properties(void *fdt,
char const *name_one,
char const *name_two)
{
const void *propval;
int proplen;
propval = fdt_getprop(fdt, 0, name_one, &proplen);
if (!propval)
FAIL("fdt_getprop(\"%s\"): %s",
name_one,
fdt_strerror(proplen));
check_getprop(fdt, 0, name_two, proplen, propval);
}
int main(int argc, char *argv[])
{
void *fdt;
uint8_t expected_8[6] = {TEST_CHAR1,
TEST_CHAR2,
TEST_CHAR3,
TEST_CHAR4,
TEST_CHAR5,
TEST_VALUE_1 >> 24};
uint16_t expected_16[6];
uint32_t expected_32[6];
uint64_t expected_64[6];
int i;
for (i = 0; i < 5; ++i) {
expected_16[i] = cpu_to_fdt16(expected_8[i]);
expected_32[i] = cpu_to_fdt32(expected_8[i]);
expected_64[i] = cpu_to_fdt64(expected_8[i]);
}
expected_16[5] = cpu_to_fdt16(TEST_VALUE_1 >> 16);
expected_32[5] = cpu_to_fdt32(TEST_VALUE_1);
expected_64[5] = cpu_to_fdt64(TEST_ADDR_1);
test_init(argc, argv);
fdt = load_blob_arg(argc, argv);
check_getprop(fdt, 0, "cells-8b", sizeof(expected_8), expected_8);
check_getprop(fdt, 0, "cells-16b", sizeof(expected_16), expected_16);
check_getprop(fdt, 0, "cells-32b", sizeof(expected_32), expected_32);
check_getprop(fdt, 0, "cells-64b", sizeof(expected_64), expected_64);
check_compare_properties(fdt, "cells-one-16b", "cells-one-32b");
PASS();
}

11
tests/sized_cells.dts Normal file
View File

@ -0,0 +1,11 @@
/dts-v1/;
/ {
cells-8b = /bits/ 8 <'\r' 'b' '\0' '\'' '\xff' 0xde>;
cells-16b = /bits/ 16 <'\r' 'b' '\0' '\'' '\xff' 0xdead>;
cells-32b = /bits/ 32 <'\r' 'b' '\0' '\'' '\xff' 0xdeadbeef>;
cells-64b = /bits/ 64 <'\r' 'b' '\0' '\'' '\xff' 0xdeadbeef00000000>;
cells-one-16b = /bits/ 16 <0x1234 0x5678 0x0 0xffff>;
cells-one-32b = <0x12345678 0x0000ffff>;
};

View File

@ -0,0 +1,44 @@
/dts-v1/;
/memreserve/ 0xdeadbeef00000000 0x100000;
/memreserve/ 123456789 010000;
/ {
compatible = "test_tree1";
prop-int = "wrong!";
prop-str = "hello world";
subnode@1 {
compatible = "subnode1";
subsubnode {
compatible = "subsubnode1", "subsubnode";
prop-int = <0xdeadbeef>;
};
ss1 {
};
};
subnode@2 {
linux,phandle = <0x2000>;
prop-int = <123456789>;
ss2 {
};
};
};
/ {
prop-int = <0xdeadbeef>;
prop-int64 = /bits/ 64 <0xdeadbeef01abcdef>;
subnode@1 {
prop-int = [deadbeef];
};
subnode@2 {
ssn0: subsubnode@0 {
phandle = <0x2001>;
compatible = "subsubnode2", "subsubnode";
prop-int = <0726746425>;
};
};
};

View File

@ -0,0 +1,42 @@
/dts-v1/;
/memreserve/ 0xdeadbeef00000000 0x100000;
/memreserve/ 123456789 010000;
/ {
compatible = "test_tree1";
prop-int = <0xdeadbeef>;
prop-int64 = /bits/ 64 <0xdeadbeef01abcdef>;
prop-str = "hello world";
subnode@1 {
compatible = "subnode1";
prop-int = [deadbeef];
subsubnode {
compatible = "subsubnode1", "subsubnode";
prop-int = <0xdeadbeef>;
};
ss1 {
};
};
subnode@2 {
linux,phandle = <0x2000>;
prop-int = <123456789>;
ssn0: subsubnode@0 {
phandle = <0x2001>;
prop-int = <0xbad>;
};
ss2 {
};
};
};
&ssn0 {
compatible = "subsubnode2", "subsubnode";
prop-int = <0726746425>;
};

View File

@ -0,0 +1,42 @@
/dts-v1/;
/memreserve/ 0xdeadbeef00000000 0x100000;
/memreserve/ 123456789 010000;
/ {
compatible = "test_tree1";
prop-int = <0xdeadbeef>;
prop-int64 = /bits/ 64 <0xdeadbeef01abcdef>;
prop-str = "hello world";
subnode@1 {
compatible = "subnode1";
prop-int = [deadbeef];
subsubnode {
compatible = "subsubnode1", "subsubnode";
prop-int = <0xdeadbeef>;
};
ss1 {
};
};
subnode@2 {
linux,phandle = <0x2000>;
prop-int = <123456789>;
ssn0: subsubnode@0 {
phandle = <0x2001>;
prop-int = <0xbad>;
};
ss2 {
};
};
};
&{/subnode@2/subsubnode@0} {
compatible = "subsubnode2", "subsubnode";
prop-int = <0726746425>;
};

View File

@ -0,0 +1,36 @@
/dts-v1/;
/memreserve/ 123456789 010000;
/ {
compatible = "test_tree1";
prop-int = <0xdeadbeef>;
prop-str = "hello world";
subnode@1 {
compatible = "subnode1";
prop-int = [deadbeef];
subsubnode {
compatible = "subsubnode1", "subsubnode";
prop-int = <0xdeadbeef>;
};
ss1 {
};
};
subnode@2 {
linux,phandle = <0x2000>;
prop-int = <123456789>;
subsubnode@0 {
phandle = <0x2001>;
compatible = "subsubnode2", "subsubnode";
prop-int = <0726746425>;
};
ss2 {
};
};
};

View File

@ -0,0 +1,36 @@
/dts-v1/;
/memreserve/ 0xdeadbeef00000000 0x100000;
/memreserve/ 123456789 010000;
/ {
compatible = "test_tree1";
prop-str = "hello world";
subnode@1 {
compatible = "subnode1";
prop-int = [deadbeef];
subsubnode {
compatible = "subsubnode1", "subsubnode";
prop-int = <0xdeadbeef>;
};
ss1 {
};
};
subnode@2 {
linux,phandle = <0x2000>;
prop-int = <123456789>;
subsubnode@0 {
phandle = <0x2001>;
compatible = "subsubnode2", "subsubnode";
prop-int = <0726746425>;
};
ss2 {
};
};
};

View File

@ -0,0 +1,36 @@
/dts-v1/;
/memreserve/ 0xdeadbeef00000000 0x100000;
/memreserve/ 123456789 010000;
/ {
compatible = "test_tree1";
prop-int = <0xdeadbeef>;
prop-str = "hello world";
subnode@1 {
compatible = "subnode1";
subsubnode {
compatible = "subsubnode1", "subsubnode";
prop-int = <0xdeadbeef>;
};
ss1 {
};
};
subnode@2 {
linux,phandle = <0x2000>;
prop-int = <123456789>;
subsubnode@0 {
phandle = <0x2001>;
compatible = "subsubnode2", "subsubnode";
prop-int = <0726746425>;
};
ss2 {
};
};
};

View File

@ -0,0 +1,34 @@
/dts-v1/;
/memreserve/ 0xdeadbeef00000000 0x100000;
/memreserve/ 123456789 010000;
/ {
compatible = "test_tree1";
prop-int = <0xdeadbeef>;
prop-str = "hello world";
subnode@1 {
compatible = "subnode1";
prop-int = [deadbeef];
subsubnode {
compatible = "subsubnode1", "subsubnode";
prop-int = <0xdeadbeef>;
};
ss1 {
};
};
subnode@2 {
linux,phandle = <0x2000>;
prop-int = <123456789>;
subsubnode@0 {
phandle = <0x2001>;
compatible = "subsubnode2", "subsubnode";
prop-int = <0726746425>;
};
};
};

View File

@ -0,0 +1,37 @@
/dts-v1/;
/memreserve/ 0xdeadbeef00000000 0x100000;
/memreserve/ 123456789 010000;
/ {
compatible = "test_tree1";
prop-int = <0xdeadbefe>;
prop-str = "hello world";
subnode@1 {
compatible = "subnode1";
prop-int = [deadbeef];
subsubnode {
compatible = "subsubnode1", "subsubnode";
prop-int = <0xdeadbeef>;
};
ss1 {
};
};
subnode@2 {
linux,phandle = <0x2000>;
prop-int = <123456789>;
subsubnode@0 {
phandle = <0x2001>;
compatible = "subsubnode2", "subsubnode";
prop-int = <0726746425>;
};
ss2 {
};
};
};

View File

@ -0,0 +1,38 @@
/dts-v1/;
/memreserve/ 0xdeadbeef00000000 0x100000;
/memreserve/ 123456789 010000;
/ {
compatible = "test_tree1";
prop-int = <0xdeadbeef>;
prop-str = "hello world";
subnode@1 {
compatible = "subnode1";
prop-int = [deadbeef];
subsubnode {
compatible = "subsubnode1", "subsubnode";
prop-int = <0xdeadbeef>;
};
ss1 {
extra-prop;
};
};
subnode@2 {
linux,phandle = <0x2000>;
prop-int = <123456789>;
subsubnode@0 {
phandle = <0x2001>;
compatible = "subsubnode2", "subsubnode";
prop-int = <0726746425>;
};
ss2 {
};
};
};

View File

@ -0,0 +1,39 @@
/dts-v1/;
/memreserve/ 0xdeadbeef00000000 0x100000;
/memreserve/ 123456789 010000;
/ {
compatible = "test_tree1";
prop-int = <0xdeadbeef>;
prop-str = "hello world";
subnode@1 {
compatible = "subnode1";
prop-int = [deadbeef];
subsubnode {
compatible = "subsubnode1", "subsubnode";
prop-int = <0xdeadbeef>;
};
ss1 {
};
};
subnode@2 {
linux,phandle = <0x2000>;
prop-int = <123456789>;
subsubnode@0 {
phandle = <0x2001>;
compatible = "subsubnode2", "subsubnode";
prop-int = <0726746425>;
};
ss2 {
extranode {
};
};
};
};

View File

@ -0,0 +1,37 @@
/dts-v1/;
/memreserve/ 0xdeadbeef00000000 0x100000;
/memreserve/ 123456789 010001;
/ {
compatible = "test_tree1";
prop-int = <0xdeadbeef>;
prop-str = "hello world";
subnode@1 {
compatible = "subnode1";
prop-int = [deadbeef];
subsubnode {
compatible = "subsubnode1", "subsubnode";
prop-int = <0xdeadbeef>;
};
ss1 {
};
};
subnode@2 {
linux,phandle = <0x2000>;
prop-int = <123456789>;
subsubnode@0 {
phandle = <0x2001>;
compatible = "subsubnode2", "subsubnode";
prop-int = <0726746425>;
};
ss2 {
};
};
};

View File

@ -0,0 +1,38 @@
/dts-v1/;
/memreserve/ 0xdeadbeef00000000 0x100000;
/memreserve/ 123456789 010000;
/memreserve/ 0 1;
/ {
compatible = "test_tree1";
prop-int = <0xdeadbeef>;
prop-str = "hello world";
subnode@1 {
compatible = "subnode1";
prop-int = [deadbeef];
subsubnode {
compatible = "subsubnode1", "subsubnode";
prop-int = <0xdeadbeef>;
};
ss1 {
};
};
subnode@2 {
linux,phandle = <0x2000>;
prop-int = <123456789>;
subsubnode@0 {
phandle = <0x2001>;
compatible = "subsubnode2", "subsubnode";
prop-int = <0726746425>;
};
ss2 {
};
};
};

128
tests/utilfdt_test.c Normal file
View File

@ -0,0 +1,128 @@
/*
* Copyright 2011 The Chromium Authors, All Rights Reserved.
*
* utilfdt_test - Tests for utilfdt library
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdarg.h>
#include <fdt.h>
#include <libfdt.h>
#include <util.h>
#include "tests.h"
#include "testdata.h"
static void check(const char *fmt, int expect_type, int expect_size)
{
int type;
int size;
if (utilfdt_decode_type(fmt, &type, &size))
FAIL("format '%s': valid format string returned failure", fmt);
if (expect_type != type)
FAIL("format '%s': expected type='%c', got type='%c'", fmt,
expect_type, type);
if (expect_size != size)
FAIL("format '%s': expected size=%d, got size=%d", fmt,
expect_size, size);
}
static void checkfail(const char *fmt)
{
int type;
int size;
if (!utilfdt_decode_type(fmt, &type, &size))
FAIL("format '%s': invalid format string returned success",
fmt);
}
/**
* Add the given modifier to each of the valid sizes, and check that we get
* correct values.
*
* \param modifier Modifer string to use as a prefix
* \param expected_size The size (in bytes) that we expect (ignored for
* strings)
*/
static void check_sizes(char *modifier, int expected_size)
{
char fmt[10], *ptr;
/* set up a string with a hole in it for the format character */
if (strlen(modifier) + 2 >= sizeof(fmt))
FAIL("modifier string '%s' too long", modifier);
strcpy(fmt, modifier);
ptr = fmt + strlen(fmt);
ptr[1] = '\0';
/* now try each format character in turn */
*ptr = 'i';
check(fmt, 'i', expected_size);
*ptr = 'u';
check(fmt, 'u', expected_size);
*ptr = 'x';
check(fmt, 'x', expected_size);
*ptr = 's';
check(fmt, 's', -1);
}
static void test_utilfdt_decode_type(void)
{
char fmt[10];
int ch;
/* check all the valid modifiers and sizes */
check_sizes("", -1);
check_sizes("b", 1);
check_sizes("hh", 1);
check_sizes("h", 2);
check_sizes("l", 4);
/* try every other character */
checkfail("");
for (ch = ' '; ch < 127; ch++) {
if (!strchr("iuxs", ch)) {
*fmt = ch;
fmt[1] = '\0';
checkfail(fmt);
}
}
/* try a few modifiers at the end */
checkfail("sx");
checkfail("ihh");
checkfail("xb");
/* and one for the doomsday archives */
checkfail("He has all the virtues I dislike and none of the vices "
"I admire.");
}
int main(int argc, char *argv[])
{
test_utilfdt_decode_type();
PASS();
}