Skip to content

Commit

Permalink
powerpc: Update in-kernel dtc and libfdt to version 1.2.0
Browse files Browse the repository at this point in the history
Some time ago, a copies of the upstream dtc and libfdt sources were
included in the kernel tree to avoid having these as external
dependencies for building the kernel.  Since then development on the
upstream dtc and libfdt has continued.  This updates the in-kernel
versions to match the recently released upstream dtc version 1.2.0.
This includes a number of bugfixes, many cleanups and a few new
features.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Paul Mackerras <paulus@samba.org>
  • Loading branch information
David Gibson authored and Paul Mackerras committed Aug 20, 2008
1 parent 0ec27c0 commit ed95d74
Show file tree
Hide file tree
Showing 28 changed files with 1,615 additions and 1,429 deletions.
18 changes: 1 addition & 17 deletions arch/powerpc/boot/dtc-src/Makefile.dtc
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,5 @@
#
DTC_SRCS = dtc.c flattree.c fstree.c data.c livetree.c treesource.c srcpos.c \
checks.c
DTC_EXTRA = dtc.h srcpos.h
DTC_LEXFILES = dtc-lexer.l
DTC_BISONFILES = dtc-parser.y

DTC_LEX_SRCS = $(DTC_LEXFILES:%.l=%.lex.c)
DTC_BISON_SRCS = $(DTC_BISONFILES:%.y=%.tab.c)
DTC_BISON_INCLUDES = $(DTC_BISONFILES:%.y=%.tab.h)

DTC_GEN_SRCS = $(DTC_LEX_SRCS) $(DTC_BISON_SRCS)
DTC_GEN_ALL = $(DTC_GEN_SRCS) $(DTC_BISON_INCLUDES)
DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c
DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o)

DTC_CLEANFILES = $(DTC_GEN_ALL)

# We assume the containing Makefile system can do auto-dependencies for most
# things, but we supply the dependencies on generated header files explicitly

$(addprefix $(DTC_objdir)/,$(DTC_GEN_SRCS:%.c=%.o)): $(addprefix $(DTC_objdir)/,$(DTC_BISON_INCLUDES))
305 changes: 71 additions & 234 deletions arch/powerpc/boot/dtc-src/checks.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,42 @@ static void check_duplicate_property_names(struct check *c, struct node *dt,
}
NODE_CHECK(duplicate_property_names, NULL, ERROR);

#define LOWERCASE "abcdefghijklmnopqrstuvwxyz"
#define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
#define DIGITS "0123456789"
#define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-"

static void check_node_name_chars(struct check *c, struct node *dt,
struct node *node)
{
int n = strspn(node->name, c->data);

if (n < strlen(node->name))
FAIL(c, "Bad character '%c' in node %s",
node->name[n], node->fullpath);
}
NODE_CHECK(node_name_chars, PROPNODECHARS "@", ERROR);

static void check_node_name_format(struct check *c, struct node *dt,
struct node *node)
{
if (strchr(get_unitname(node), '@'))
FAIL(c, "Node %s has multiple '@' characters in name",
node->fullpath);
}
NODE_CHECK(node_name_format, NULL, ERROR, &node_name_chars);

static void check_property_name_chars(struct check *c, struct node *dt,
struct node *node, struct property *prop)
{
int n = strspn(prop->name, c->data);

if (n < strlen(prop->name))
FAIL(c, "Bad character '%c' in property name \"%s\", node %s",
prop->name[n], prop->name, node->fullpath);
}
PROP_CHECK(property_name_chars, PROPNODECHARS, ERROR);

static void check_explicit_phandles(struct check *c, struct node *root,
struct node *node)
{
Expand Down Expand Up @@ -280,16 +316,29 @@ NODE_CHECK(explicit_phandles, NULL, ERROR);
static void check_name_properties(struct check *c, struct node *root,
struct node *node)
{
struct property *prop;
struct property **pp, *prop = NULL;

for (pp = &node->proplist; *pp; pp = &((*pp)->next))
if (streq((*pp)->name, "name")) {
prop = *pp;
break;
}

prop = get_property(node, "name");
if (!prop)
return; /* No name property, that's fine */

if ((prop->val.len != node->basenamelen+1)
|| (memcmp(prop->val.val, node->name, node->basenamelen) != 0))
|| (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) {
FAIL(c, "\"name\" property in %s is incorrect (\"%s\" instead"
" of base node name)", node->fullpath, prop->val.val);
} else {
/* The name property is correct, and therefore redundant.
* Delete it */
*pp = prop->next;
free(prop->name);
data_free(prop->val);
free(prop);
}
}
CHECK_IS_STRING(name_is_string, "name", ERROR);
NODE_CHECK(name_properties, NULL, ERROR, &name_is_string);
Expand All @@ -301,23 +350,23 @@ NODE_CHECK(name_properties, NULL, ERROR, &name_is_string);
static void fixup_phandle_references(struct check *c, struct node *dt,
struct node *node, struct property *prop)
{
struct marker *m = prop->val.markers;
struct node *refnode;
cell_t phandle;

for_each_marker_of_type(m, REF_PHANDLE) {
assert(m->offset + sizeof(cell_t) <= prop->val.len);

refnode = get_node_by_ref(dt, m->ref);
if (! refnode) {
FAIL(c, "Reference to non-existent node or label \"%s\"\n",
m->ref);
continue;
}

phandle = get_node_phandle(dt, refnode);
*((cell_t *)(prop->val.val + m->offset)) = cpu_to_be32(phandle);
}
struct marker *m = prop->val.markers;
struct node *refnode;
cell_t phandle;

for_each_marker_of_type(m, REF_PHANDLE) {
assert(m->offset + sizeof(cell_t) <= prop->val.len);

refnode = get_node_by_ref(dt, m->ref);
if (! refnode) {
FAIL(c, "Reference to non-existent node or label \"%s\"\n",
m->ref);
continue;
}

phandle = get_node_phandle(dt, refnode);
*((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
}
}
CHECK(phandle_references, NULL, NULL, fixup_phandle_references, NULL, ERROR,
&duplicate_node_names, &explicit_phandles);
Expand Down Expand Up @@ -498,6 +547,7 @@ TREE_CHECK(obsolete_chosen_interrupt_controller, NULL, WARN);

static struct check *check_table[] = {
&duplicate_node_names, &duplicate_property_names,
&node_name_chars, &node_name_format, &property_name_chars,
&name_is_string, &name_properties,
&explicit_phandles,
&phandle_references, &path_references,
Expand All @@ -511,10 +561,7 @@ static struct check *check_table[] = {
&obsolete_chosen_interrupt_controller,
};

int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys);

void process_checks(int force, struct boot_info *bi,
int checkflag, int outversion, int boot_cpuid_phys)
void process_checks(int force, struct boot_info *bi)
{
struct node *dt = bi->dt;
int i;
Expand All @@ -537,214 +584,4 @@ void process_checks(int force, struct boot_info *bi,
"output forced\n");
}
}

if (checkflag) {
if (error) {
fprintf(stderr, "Warning: Skipping semantic checks due to structural errors\n");
} else {
if (!check_semantics(bi->dt, outversion,
boot_cpuid_phys))
fprintf(stderr, "Warning: Input tree has semantic errors\n");
}
}
}

/*
* Semantic check functions
*/

#define ERRMSG(...) if (quiet < 2) fprintf(stderr, "ERROR: " __VA_ARGS__)
#define WARNMSG(...) if (quiet < 1) fprintf(stderr, "Warning: " __VA_ARGS__)

#define DO_ERR(...) do {ERRMSG(__VA_ARGS__); ok = 0; } while (0)

#define CHECK_HAVE(node, propname) \
do { \
if (! (prop = get_property((node), (propname)))) \
DO_ERR("Missing \"%s\" property in %s\n", (propname), \
(node)->fullpath); \
} while (0);

#define CHECK_HAVE_WARN(node, propname) \
do { \
if (! (prop = get_property((node), (propname)))) \
WARNMSG("%s has no \"%s\" property\n", \
(node)->fullpath, (propname)); \
} while (0)

#define CHECK_HAVE_STRING(node, propname) \
do { \
CHECK_HAVE((node), (propname)); \
if (prop && !data_is_one_string(prop->val)) \
DO_ERR("\"%s\" property in %s is not a string\n", \
(propname), (node)->fullpath); \
} while (0)

#define CHECK_HAVE_STREQ(node, propname, value) \
do { \
CHECK_HAVE_STRING((node), (propname)); \
if (prop && !streq(prop->val.val, (value))) \
DO_ERR("%s has wrong %s, %s (should be %s\n", \
(node)->fullpath, (propname), \
prop->val.val, (value)); \
} while (0)

#define CHECK_HAVE_ONECELL(node, propname) \
do { \
CHECK_HAVE((node), (propname)); \
if (prop && (prop->val.len != sizeof(cell_t))) \
DO_ERR("\"%s\" property in %s has wrong size %d (should be 1 cell)\n", (propname), (node)->fullpath, prop->val.len); \
} while (0)

#define CHECK_HAVE_WARN_ONECELL(node, propname) \
do { \
CHECK_HAVE_WARN((node), (propname)); \
if (prop && (prop->val.len != sizeof(cell_t))) \
DO_ERR("\"%s\" property in %s has wrong size %d (should be 1 cell)\n", (propname), (node)->fullpath, prop->val.len); \
} while (0)

#define CHECK_HAVE_WARN_PHANDLE(xnode, propname, root) \
do { \
struct node *ref; \
CHECK_HAVE_WARN_ONECELL((xnode), (propname)); \
if (prop) {\
cell_t phandle = propval_cell(prop); \
if ((phandle == 0) || (phandle == -1)) { \
DO_ERR("\"%s\" property in %s contains an invalid phandle %x\n", (propname), (xnode)->fullpath, phandle); \
} else { \
ref = get_node_by_phandle((root), propval_cell(prop)); \
if (! ref) \
DO_ERR("\"%s\" property in %s refers to non-existant phandle %x\n", (propname), (xnode)->fullpath, propval_cell(prop)); \
} \
} \
} while (0)

#define CHECK_HAVE_WARN_STRING(node, propname) \
do { \
CHECK_HAVE_WARN((node), (propname)); \
if (prop && !data_is_one_string(prop->val)) \
DO_ERR("\"%s\" property in %s is not a string\n", \
(propname), (node)->fullpath); \
} while (0)

static int check_root(struct node *root)
{
struct property *prop;
int ok = 1;

CHECK_HAVE_STRING(root, "model");
CHECK_HAVE_WARN(root, "compatible");

return ok;
}

static int check_cpus(struct node *root, int outversion, int boot_cpuid_phys)
{
struct node *cpus, *cpu;
struct property *prop;
struct node *bootcpu = NULL;
int ok = 1;

cpus = get_subnode(root, "cpus");
if (! cpus) {
ERRMSG("Missing /cpus node\n");
return 0;
}

if (cpus->addr_cells != 1)
DO_ERR("%s has bad #address-cells value %d (should be 1)\n",
cpus->fullpath, cpus->addr_cells);
if (cpus->size_cells != 0)
DO_ERR("%s has bad #size-cells value %d (should be 0)\n",
cpus->fullpath, cpus->size_cells);

for_each_child(cpus, cpu) {
CHECK_HAVE_STREQ(cpu, "device_type", "cpu");

CHECK_HAVE_ONECELL(cpu, "reg");
if (prop) {
cell_t unitnum;
char *eptr;

unitnum = strtol(get_unitname(cpu), &eptr, 16);
if (*eptr) {
WARNMSG("%s has bad format unit name %s (should be CPU number\n",
cpu->fullpath, get_unitname(cpu));
} else if (unitnum != propval_cell(prop)) {
WARNMSG("%s unit name \"%s\" does not match \"reg\" property <%x>\n",
cpu->fullpath, get_unitname(cpu),
propval_cell(prop));
}
}

/* CHECK_HAVE_ONECELL(cpu, "d-cache-line-size"); */
/* CHECK_HAVE_ONECELL(cpu, "i-cache-line-size"); */
CHECK_HAVE_ONECELL(cpu, "d-cache-size");
CHECK_HAVE_ONECELL(cpu, "i-cache-size");

CHECK_HAVE_WARN_ONECELL(cpu, "clock-frequency");
CHECK_HAVE_WARN_ONECELL(cpu, "timebase-frequency");

prop = get_property(cpu, "linux,boot-cpu");
if (prop) {
if (prop->val.len)
WARNMSG("\"linux,boot-cpu\" property in %s is non-empty\n",
cpu->fullpath);
if (bootcpu)
DO_ERR("Multiple boot cpus (%s and %s)\n",
bootcpu->fullpath, cpu->fullpath);
else
bootcpu = cpu;
}
}

if (outversion < 2) {
if (! bootcpu)
WARNMSG("No cpu has \"linux,boot-cpu\" property\n");
} else {
if (bootcpu)
WARNMSG("\"linux,boot-cpu\" property is deprecated in blob version 2 or higher\n");
if (boot_cpuid_phys == 0xfeedbeef)
WARNMSG("physical boot CPU not set. Use -b option to set\n");
}

return ok;
}

static int check_memory(struct node *root)
{
struct node *mem;
struct property *prop;
int nnodes = 0;
int ok = 1;

for_each_child(root, mem) {
if (! strneq(mem->name, "memory", mem->basenamelen))
continue;

nnodes++;

CHECK_HAVE_STREQ(mem, "device_type", "memory");
CHECK_HAVE(mem, "reg");
}

if (nnodes == 0) {
ERRMSG("No memory nodes\n");
return 0;
}

return ok;
}

int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys)
{
int ok = 1;

ok = ok && check_root(dt);
ok = ok && check_cpus(dt, outversion, boot_cpuid_phys);
ok = ok && check_memory(dt);
if (! ok)
return 0;

return 1;
}
Loading

0 comments on commit ed95d74

Please sign in to comment.