Add missing files in f807af192828222dee7a5c9f94d999673bb4d8a1 import.
This commit is contained in:
parent
bae61446cf
commit
ab1c86b34d
24
Makefile.utils
Normal file
24
Makefile.utils
Normal 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
38
dtdiff
Normal 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
162
fdtdump.c
Normal 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
366
fdtget.c
Normal 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
362
fdtput.c
Normal 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
84
libfdt/fdt_empty_tree.c
Normal 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
8
tests/appendprop.dts
Normal 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
71
tests/appendprop1.c
Normal 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
65
tests/appendprop2.c
Normal 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
16
tests/boot-cpuid.dts
Normal 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
50
tests/char_literal.c
Normal 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
5
tests/char_literal.dts
Normal file
@ -0,0 +1,5 @@
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
char-literal-cells = <'\r' 'b' '\0' '\'' '\xff'>;
|
||||
};
|
1
tests/dependencies.cmp
Normal file
1
tests/dependencies.cmp
Normal file
@ -0,0 +1 @@
|
||||
dependencies.test.dtb: dependencies.dts deps_inc1.dtsi deps_inc2.dtsi
|
6
tests/dependencies.dts
Normal file
6
tests/dependencies.dts
Normal file
@ -0,0 +1,6 @@
|
||||
/dts-v1/;
|
||||
|
||||
/include/ "deps_inc1.dtsi"
|
||||
|
||||
/ {
|
||||
};
|
1
tests/deps_inc1.dtsi
Normal file
1
tests/deps_inc1.dtsi
Normal file
@ -0,0 +1 @@
|
||||
/include/ "deps_inc2.dtsi"
|
1
tests/deps_inc2.dtsi
Normal file
1
tests/deps_inc2.dtsi
Normal file
@ -0,0 +1 @@
|
||||
/* Empty */
|
164
tests/dtb_reverse.c
Normal file
164
tests/dtb_reverse.c
Normal 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();
|
||||
}
|
224
tests/dtbs_equal_unordered.c
Normal file
224
tests/dtbs_equal_unordered.c
Normal 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
30
tests/dtc-fails.sh
Executable 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
24
tests/fdtget-runtest.sh
Executable 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
39
tests/fdtput-runtest.sh
Executable 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
1
tests/include5a.dts
Normal file
@ -0,0 +1 @@
|
||||
= /bits/ 64 <0xdeadbeef01abcdef>
|
117
tests/integer-expressions.c
Normal file
117
tests/integer-expressions.c
Normal 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
15
tests/label_repeated.dts
Normal file
@ -0,0 +1,15 @@
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
l0: prop = "foo";
|
||||
|
||||
l1: node {
|
||||
};
|
||||
};
|
||||
|
||||
/ {
|
||||
l0: prop = "foo";
|
||||
|
||||
l1: node {
|
||||
};
|
||||
};
|
35
tests/lorem.txt
Normal file
35
tests/lorem.txt
Normal 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
42
tests/multilabel.dts
Normal 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;
|
||||
};
|
||||
};
|
66
tests/multilabel_merge.dts
Normal file
66
tests/multilabel_merge.dts
Normal 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;
|
||||
};
|
||||
|
||||
};
|
10
tests/nonexist-node-ref2.dts
Normal file
10
tests/nonexist-node-ref2.dts
Normal 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
15
tests/reuse-label.dts
Normal 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
10
tests/reuse-label1.dts
Normal file
@ -0,0 +1,10 @@
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
label: node1 {
|
||||
prop = "foo";
|
||||
};
|
||||
label: node2 {
|
||||
prop = "bar";
|
||||
};
|
||||
};
|
6
tests/reuse-label2.dts
Normal file
6
tests/reuse-label2.dts
Normal file
@ -0,0 +1,6 @@
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
label: property1 = "foo";
|
||||
label: property2 = "bar";
|
||||
};
|
9
tests/reuse-label3.dts
Normal file
9
tests/reuse-label3.dts
Normal file
@ -0,0 +1,9 @@
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
label: property = "foo";
|
||||
|
||||
label: node {
|
||||
property = "foo";
|
||||
};
|
||||
};
|
5
tests/reuse-label4.dts
Normal file
5
tests/reuse-label4.dts
Normal file
@ -0,0 +1,5 @@
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
property = label: "foo" label:;
|
||||
};
|
6
tests/reuse-label5.dts
Normal file
6
tests/reuse-label5.dts
Normal file
@ -0,0 +1,6 @@
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
prop1 = label: "foo";
|
||||
prop2 = "bar" label:;
|
||||
};
|
6
tests/reuse-label6.dts
Normal file
6
tests/reuse-label6.dts
Normal file
@ -0,0 +1,6 @@
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
label: prop1 = "foo";
|
||||
prop2 = "bar" label:;
|
||||
};
|
4
tests/search_dir/search_test.dtsi
Normal file
4
tests/search_dir/search_test.dtsi
Normal file
@ -0,0 +1,4 @@
|
||||
/include/ "search_test2.dtsi"
|
||||
|
||||
/ {
|
||||
};
|
3
tests/search_dir/search_test2.dtsi
Normal file
3
tests/search_dir/search_test2.dtsi
Normal file
@ -0,0 +1,3 @@
|
||||
|
||||
/ {
|
||||
};
|
6
tests/search_dir_b/search_paths_subdir.dts
Normal file
6
tests/search_dir_b/search_paths_subdir.dts
Normal file
@ -0,0 +1,6 @@
|
||||
/dts-v1/;
|
||||
|
||||
/include/ "search_test_c.dtsi"
|
||||
|
||||
/ {
|
||||
};
|
4
tests/search_dir_b/search_test_b.dtsi
Normal file
4
tests/search_dir_b/search_test_b.dtsi
Normal file
@ -0,0 +1,4 @@
|
||||
/include/ "search_test_b2.dtsi"
|
||||
|
||||
/ {
|
||||
};
|
5
tests/search_dir_b/search_test_b2.dtsi
Normal file
5
tests/search_dir_b/search_test_b2.dtsi
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
/include/ "search_test.dtsi"
|
||||
|
||||
/ {
|
||||
};
|
2
tests/search_dir_b/search_test_c.dtsi
Normal file
2
tests/search_dir_b/search_test_c.dtsi
Normal file
@ -0,0 +1,2 @@
|
||||
/ {
|
||||
};
|
6
tests/search_paths.dts
Normal file
6
tests/search_paths.dts
Normal file
@ -0,0 +1,6 @@
|
||||
/dts-v1/;
|
||||
|
||||
/include/ "search_test.dtsi"
|
||||
|
||||
/ {
|
||||
};
|
6
tests/search_paths_b.dts
Normal file
6
tests/search_paths_b.dts
Normal file
@ -0,0 +1,6 @@
|
||||
/dts-v1/;
|
||||
|
||||
/include/ "search_test_b.dtsi"
|
||||
|
||||
/ {
|
||||
};
|
84
tests/sized_cells.c
Normal file
84
tests/sized_cells.c
Normal 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
11
tests/sized_cells.dts
Normal 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>;
|
||||
};
|
44
tests/test_tree1_merge.dts
Normal file
44
tests/test_tree1_merge.dts
Normal 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>;
|
||||
};
|
||||
};
|
||||
};
|
42
tests/test_tree1_merge_labelled.dts
Normal file
42
tests/test_tree1_merge_labelled.dts
Normal 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>;
|
||||
};
|
42
tests/test_tree1_merge_path.dts
Normal file
42
tests/test_tree1_merge_path.dts
Normal 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>;
|
||||
};
|
36
tests/test_tree1_wrong1.dts
Normal file
36
tests/test_tree1_wrong1.dts
Normal 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 {
|
||||
};
|
||||
};
|
||||
};
|
36
tests/test_tree1_wrong2.dts
Normal file
36
tests/test_tree1_wrong2.dts
Normal 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 {
|
||||
};
|
||||
};
|
||||
};
|
36
tests/test_tree1_wrong3.dts
Normal file
36
tests/test_tree1_wrong3.dts
Normal 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 {
|
||||
};
|
||||
};
|
||||
};
|
34
tests/test_tree1_wrong4.dts
Normal file
34
tests/test_tree1_wrong4.dts
Normal 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>;
|
||||
};
|
||||
};
|
||||
};
|
37
tests/test_tree1_wrong5.dts
Normal file
37
tests/test_tree1_wrong5.dts
Normal 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 {
|
||||
};
|
||||
};
|
||||
};
|
38
tests/test_tree1_wrong6.dts
Normal file
38
tests/test_tree1_wrong6.dts
Normal 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 {
|
||||
};
|
||||
};
|
||||
};
|
39
tests/test_tree1_wrong7.dts
Normal file
39
tests/test_tree1_wrong7.dts
Normal 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 {
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
37
tests/test_tree1_wrong8.dts
Normal file
37
tests/test_tree1_wrong8.dts
Normal 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 {
|
||||
};
|
||||
};
|
||||
};
|
38
tests/test_tree1_wrong9.dts
Normal file
38
tests/test_tree1_wrong9.dts
Normal 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
128
tests/utilfdt_test.c
Normal 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();
|
||||
}
|
Loading…
Reference in New Issue
Block a user