Browse Source

Re-work level setting on checks code

Currently each of the semantic checks in checks.c has a "level" between
IGNORE and ERROR.  This single level makes it awkward to implement the
semantics we want for toggling the checks on the command line.

This patch reworks the code to instead have separate boolean flags for
warning and error.  At present having both flags set will have the same
effect as having just the error flag set, but this can change in the
future.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
main
David Gibson 13 years ago committed by Jon Loeliger
parent
commit
511dedd40f
  1. 117
      checks.c
  2. 1
      dtc.h

117
checks.c

@ -31,12 +31,6 @@ @@ -31,12 +31,6 @@
#define TRACE(c, fmt, ...) do { } while (0)
#endif

enum checklevel {
IGNORE = 0,
WARN = 1,
ERROR = 2,
};

enum checkstatus {
UNCHECKED = 0,
PREREQ,
@ -57,14 +51,14 @@ struct check { @@ -57,14 +51,14 @@ struct check {
node_check_fn node_fn;
prop_check_fn prop_fn;
void *data;
enum checklevel level;
bool warn, error;
enum checkstatus status;
int inprogress;
int num_prereqs;
struct check **prereq;
};

#define CHECK(nm, tfn, nfn, pfn, d, lvl, ...) \
#define CHECK(nm, tfn, nfn, pfn, d, w, e, ...) \
static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \
static struct check nm = { \
.name = #nm, \
@ -72,20 +66,29 @@ struct check { @@ -72,20 +66,29 @@ struct check {
.node_fn = (nfn), \
.prop_fn = (pfn), \
.data = (d), \
.level = (lvl), \
.warn = (w), \
.error = (e), \
.status = UNCHECKED, \
.num_prereqs = ARRAY_SIZE(nm##_prereqs), \
.prereq = nm##_prereqs, \
};

#define TREE_CHECK(nm, d, lvl, ...) \
CHECK(nm, check_##nm, NULL, NULL, d, lvl, __VA_ARGS__)
#define NODE_CHECK(nm, d, lvl, ...) \
CHECK(nm, NULL, check_##nm, NULL, d, lvl, __VA_ARGS__)
#define PROP_CHECK(nm, d, lvl, ...) \
CHECK(nm, NULL, NULL, check_##nm, d, lvl, __VA_ARGS__)
#define BATCH_CHECK(nm, lvl, ...) \
CHECK(nm, NULL, NULL, NULL, NULL, lvl, __VA_ARGS__)
#define WARNING(nm, tfn, nfn, pfn, d, ...) \
CHECK(nm, tfn, nfn, pfn, d, true, false, __VA_ARGS__)
#define ERROR(nm, tfn, nfn, pfn, d, ...) \
CHECK(nm, tfn, nfn, pfn, d, false, true, __VA_ARGS__)

#define TREE_WARNING(nm, d, ...) \
WARNING(nm, check_##nm, NULL, NULL, d, __VA_ARGS__)
#define TREE_ERROR(nm, d, ...) \
ERROR(nm, check_##nm, NULL, NULL, d, __VA_ARGS__)
#define NODE_WARNING(nm, d, ...) \
WARNING(nm, NULL, check_##nm, NULL, d, __VA_ARGS__)
#define NODE_ERROR(nm, d, ...) \
ERROR(nm, NULL, check_##nm, NULL, d, __VA_ARGS__)
#define PROP_WARNING(nm, d, ...) \
WARNING(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)
#define PROP_ERROR(nm, d, ...) \
ERROR(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)

#ifdef __GNUC__
static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3)));
@ -95,13 +98,13 @@ static inline void check_msg(struct check *c, const char *fmt, ...) @@ -95,13 +98,13 @@ static inline void check_msg(struct check *c, const char *fmt, ...)
va_list ap;
va_start(ap, fmt);

if ((c->level < WARN) || (c->level <= quiet))
return; /* Suppress message */

fprintf(stderr, "%s (%s): ",
(c->level == ERROR) ? "ERROR" : "Warning", c->name);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
if ((c->warn && (quiet < 1))
|| (c->error && (quiet < 2))) {
fprintf(stderr, "%s (%s): ",
(c->error) ? "ERROR" : "Warning", c->name);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
}
}

#define FAIL(c, ...) \
@ -167,7 +170,7 @@ static int run_check(struct check *c, struct node *dt) @@ -167,7 +170,7 @@ static int run_check(struct check *c, struct node *dt)

out:
c->inprogress = 0;
if ((c->status != PASSED) && (c->level == ERROR))
if ((c->status != PASSED) && (c->error))
error = 1;
return error;
}
@ -190,8 +193,10 @@ static void check_is_string(struct check *c, struct node *root, @@ -190,8 +193,10 @@ static void check_is_string(struct check *c, struct node *root,
FAIL(c, "\"%s\" property in %s is not a string",
propname, node->fullpath);
}
#define CHECK_IS_STRING(nm, propname, lvl) \
CHECK(nm, NULL, check_is_string, NULL, (propname), (lvl))
#define WARNING_IF_NOT_STRING(nm, propname) \
WARNING(nm, NULL, check_is_string, NULL, (propname))
#define ERROR_IF_NOT_STRING(nm, propname) \
ERROR(nm, NULL, check_is_string, NULL, (propname))

static void check_is_cell(struct check *c, struct node *root,
struct node *node)
@ -207,8 +212,10 @@ static void check_is_cell(struct check *c, struct node *root, @@ -207,8 +212,10 @@ static void check_is_cell(struct check *c, struct node *root,
FAIL(c, "\"%s\" property in %s is not a single cell",
propname, node->fullpath);
}
#define CHECK_IS_CELL(nm, propname, lvl) \
CHECK(nm, NULL, check_is_cell, NULL, (propname), (lvl))
#define WARNING_IF_NOT_CELL(nm, propname) \
WARNING(nm, NULL, check_is_cell, NULL, (propname))
#define ERROR_IF_NOT_CELL(nm, propname) \
ERROR(nm, NULL, check_is_cell, NULL, (propname))

/*
* Structural check functions
@ -227,7 +234,7 @@ static void check_duplicate_node_names(struct check *c, struct node *dt, @@ -227,7 +234,7 @@ static void check_duplicate_node_names(struct check *c, struct node *dt,
FAIL(c, "Duplicate node name %s",
child->fullpath);
}
NODE_CHECK(duplicate_node_names, NULL, ERROR);
NODE_ERROR(duplicate_node_names, NULL);

static void check_duplicate_property_names(struct check *c, struct node *dt,
struct node *node)
@ -240,7 +247,7 @@ static void check_duplicate_property_names(struct check *c, struct node *dt, @@ -240,7 +247,7 @@ static void check_duplicate_property_names(struct check *c, struct node *dt,
FAIL(c, "Duplicate property name %s in %s",
prop->name, node->fullpath);
}
NODE_CHECK(duplicate_property_names, NULL, ERROR);
NODE_ERROR(duplicate_property_names, NULL);

#define LOWERCASE "abcdefghijklmnopqrstuvwxyz"
#define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
@ -256,7 +263,7 @@ static void check_node_name_chars(struct check *c, struct node *dt, @@ -256,7 +263,7 @@ static void check_node_name_chars(struct check *c, struct node *dt,
FAIL(c, "Bad character '%c' in node %s",
node->name[n], node->fullpath);
}
NODE_CHECK(node_name_chars, PROPNODECHARS "@", ERROR);
NODE_ERROR(node_name_chars, PROPNODECHARS "@");

static void check_node_name_format(struct check *c, struct node *dt,
struct node *node)
@ -265,7 +272,7 @@ static void check_node_name_format(struct check *c, struct node *dt, @@ -265,7 +272,7 @@ static void check_node_name_format(struct check *c, struct node *dt,
FAIL(c, "Node %s has multiple '@' characters in name",
node->fullpath);
}
NODE_CHECK(node_name_format, NULL, ERROR, &node_name_chars);
NODE_ERROR(node_name_format, NULL, &node_name_chars);

static void check_property_name_chars(struct check *c, struct node *dt,
struct node *node, struct property *prop)
@ -276,7 +283,7 @@ static void check_property_name_chars(struct check *c, struct node *dt, @@ -276,7 +283,7 @@ static void check_property_name_chars(struct check *c, struct node *dt,
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);
PROP_ERROR(property_name_chars, PROPNODECHARS);

#define DESCLABEL_FMT "%s%s%s%s%s"
#define DESCLABEL_ARGS(node,prop,mark) \
@ -331,8 +338,8 @@ static void check_duplicate_label_prop(struct check *c, struct node *dt, @@ -331,8 +338,8 @@ static void check_duplicate_label_prop(struct check *c, struct node *dt,
for_each_marker_of_type(m, LABEL)
check_duplicate_label(c, dt, m->ref, node, prop, m);
}
CHECK(duplicate_label, NULL, check_duplicate_label_node,
check_duplicate_label_prop, NULL, ERROR);
ERROR(duplicate_label, NULL, check_duplicate_label_node,
check_duplicate_label_prop, NULL);

static void check_explicit_phandles(struct check *c, struct node *root,
struct node *node, struct property *prop)
@ -391,7 +398,7 @@ static void check_explicit_phandles(struct check *c, struct node *root, @@ -391,7 +398,7 @@ static void check_explicit_phandles(struct check *c, struct node *root,

node->phandle = phandle;
}
PROP_CHECK(explicit_phandles, NULL, ERROR);
PROP_ERROR(explicit_phandles, NULL);

static void check_name_properties(struct check *c, struct node *root,
struct node *node)
@ -420,8 +427,8 @@ static void check_name_properties(struct check *c, struct node *root, @@ -420,8 +427,8 @@ static void check_name_properties(struct check *c, struct node *root,
free(prop);
}
}
CHECK_IS_STRING(name_is_string, "name", ERROR);
NODE_CHECK(name_properties, NULL, ERROR, &name_is_string);
ERROR_IF_NOT_STRING(name_is_string, "name");
NODE_ERROR(name_properties, NULL, &name_is_string);

/*
* Reference fixup functions
@ -448,7 +455,7 @@ static void fixup_phandle_references(struct check *c, struct node *dt, @@ -448,7 +455,7 @@ static void fixup_phandle_references(struct check *c, struct node *dt,
*((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
}
}
CHECK(phandle_references, NULL, NULL, fixup_phandle_references, NULL, ERROR,
ERROR(phandle_references, NULL, NULL, fixup_phandle_references, NULL,
&duplicate_node_names, &explicit_phandles);

static void fixup_path_references(struct check *c, struct node *dt,
@ -473,19 +480,19 @@ static void fixup_path_references(struct check *c, struct node *dt, @@ -473,19 +480,19 @@ static void fixup_path_references(struct check *c, struct node *dt,
strlen(path) + 1);
}
}
CHECK(path_references, NULL, NULL, fixup_path_references, NULL, ERROR,
ERROR(path_references, NULL, NULL, fixup_path_references, NULL,
&duplicate_node_names);

/*
* Semantic checks
*/
CHECK_IS_CELL(address_cells_is_cell, "#address-cells", WARN);
CHECK_IS_CELL(size_cells_is_cell, "#size-cells", WARN);
CHECK_IS_CELL(interrupt_cells_is_cell, "#interrupt-cells", WARN);
WARNING_IF_NOT_CELL(address_cells_is_cell, "#address-cells");
WARNING_IF_NOT_CELL(size_cells_is_cell, "#size-cells");
WARNING_IF_NOT_CELL(interrupt_cells_is_cell, "#interrupt-cells");

CHECK_IS_STRING(device_type_is_string, "device_type", WARN);
CHECK_IS_STRING(model_is_string, "model", WARN);
CHECK_IS_STRING(status_is_string, "status", WARN);
WARNING_IF_NOT_STRING(device_type_is_string, "device_type");
WARNING_IF_NOT_STRING(model_is_string, "model");
WARNING_IF_NOT_STRING(status_is_string, "status");

static void fixup_addr_size_cells(struct check *c, struct node *dt,
struct node *node)
@ -503,8 +510,8 @@ static void fixup_addr_size_cells(struct check *c, struct node *dt, @@ -503,8 +510,8 @@ static void fixup_addr_size_cells(struct check *c, struct node *dt,
if (prop)
node->size_cells = propval_cell(prop);
}
CHECK(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL, WARN,
&address_cells_is_cell, &size_cells_is_cell);
WARNING(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL,
&address_cells_is_cell, &size_cells_is_cell);

#define node_addr_cells(n) \
(((n)->addr_cells == -1) ? 2 : (n)->addr_cells)
@ -538,7 +545,7 @@ static void check_reg_format(struct check *c, struct node *dt, @@ -538,7 +545,7 @@ static void check_reg_format(struct check *c, struct node *dt,
"(#address-cells == %d, #size-cells == %d)",
node->fullpath, prop->val.len, addr_cells, size_cells);
}
NODE_CHECK(reg_format, NULL, WARN, &addr_size_cells);
NODE_WARNING(reg_format, NULL, &addr_size_cells);

static void check_ranges_format(struct check *c, struct node *dt,
struct node *node)
@ -579,7 +586,7 @@ static void check_ranges_format(struct check *c, struct node *dt, @@ -579,7 +586,7 @@ static void check_ranges_format(struct check *c, struct node *dt,
p_addr_cells, c_addr_cells, c_size_cells);
}
}
NODE_CHECK(ranges_format, NULL, WARN, &addr_size_cells);
NODE_WARNING(ranges_format, NULL, &addr_size_cells);

/*
* Style checks
@ -606,7 +613,7 @@ static void check_avoid_default_addr_size(struct check *c, struct node *dt, @@ -606,7 +613,7 @@ static void check_avoid_default_addr_size(struct check *c, struct node *dt,
FAIL(c, "Relying on default #size-cells value for %s",
node->fullpath);
}
NODE_CHECK(avoid_default_addr_size, NULL, WARN, &addr_size_cells);
NODE_WARNING(avoid_default_addr_size, NULL, &addr_size_cells);

static void check_obsolete_chosen_interrupt_controller(struct check *c,
struct node *dt)
@ -623,7 +630,7 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c, @@ -623,7 +630,7 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c,
FAIL(c, "/chosen has obsolete \"interrupt-controller\" "
"property");
}
TREE_CHECK(obsolete_chosen_interrupt_controller, NULL, WARN);
TREE_WARNING(obsolete_chosen_interrupt_controller, NULL);

static struct check *check_table[] = {
&duplicate_node_names, &duplicate_property_names,
@ -653,7 +660,7 @@ void process_checks(int force, struct boot_info *bi) @@ -653,7 +660,7 @@ void process_checks(int force, struct boot_info *bi)
for (i = 0; i < ARRAY_SIZE(check_table); i++) {
struct check *c = check_table[i];

if (c->level != IGNORE)
if (c->warn || c->error)
error = error || run_check(c, dt);
}


1
dtc.h

@ -25,6 +25,7 @@ @@ -25,6 +25,7 @@
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

Loading…
Cancel
Save