diff -Nru device-tree-compiler-1.4.5/checks.c device-tree-compiler-1.4.7/checks.c --- device-tree-compiler-1.4.5/checks.c 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/checks.c 2018-07-23 03:00:50.000000000 +0000 @@ -53,26 +53,28 @@ struct check **prereq; }; -#define CHECK_ENTRY(_nm, _fn, _d, _w, _e, ...) \ - static struct check *_nm##_prereqs[] = { __VA_ARGS__ }; \ - static struct check _nm = { \ - .name = #_nm, \ - .fn = (_fn), \ - .data = (_d), \ - .warn = (_w), \ - .error = (_e), \ +#define CHECK_ENTRY(nm_, fn_, d_, w_, e_, ...) \ + static struct check *nm_##_prereqs[] = { __VA_ARGS__ }; \ + static struct check nm_ = { \ + .name = #nm_, \ + .fn = (fn_), \ + .data = (d_), \ + .warn = (w_), \ + .error = (e_), \ .status = UNCHECKED, \ - .num_prereqs = ARRAY_SIZE(_nm##_prereqs), \ - .prereq = _nm##_prereqs, \ + .num_prereqs = ARRAY_SIZE(nm_##_prereqs), \ + .prereq = nm_##_prereqs, \ }; -#define WARNING(_nm, _fn, _d, ...) \ - CHECK_ENTRY(_nm, _fn, _d, true, false, __VA_ARGS__) -#define ERROR(_nm, _fn, _d, ...) \ - CHECK_ENTRY(_nm, _fn, _d, false, true, __VA_ARGS__) -#define CHECK(_nm, _fn, _d, ...) \ - CHECK_ENTRY(_nm, _fn, _d, false, false, __VA_ARGS__) - -static inline void PRINTF(3, 4) check_msg(struct check *c, struct dt_info *dti, +#define WARNING(nm_, fn_, d_, ...) \ + CHECK_ENTRY(nm_, fn_, d_, true, false, __VA_ARGS__) +#define ERROR(nm_, fn_, d_, ...) \ + CHECK_ENTRY(nm_, fn_, d_, false, true, __VA_ARGS__) +#define CHECK(nm_, fn_, d_, ...) \ + CHECK_ENTRY(nm_, fn_, d_, false, false, __VA_ARGS__) + +static inline void PRINTF(5, 6) check_msg(struct check *c, struct dt_info *dti, + struct node *node, + struct property *prop, const char *fmt, ...) { va_list ap; @@ -83,19 +85,33 @@ fprintf(stderr, "%s: %s (%s): ", strcmp(dti->outname, "-") ? dti->outname : "", (c->error) ? "ERROR" : "Warning", c->name); + if (node) { + fprintf(stderr, "%s", node->fullpath); + if (prop) + fprintf(stderr, ":%s", prop->name); + fputs(": ", stderr); + } vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); } va_end(ap); } -#define FAIL(c, dti, ...) \ +#define FAIL(c, dti, node, ...) \ + do { \ + TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \ + (c)->status = FAILED; \ + check_msg((c), dti, node, NULL, __VA_ARGS__); \ + } while (0) + +#define FAIL_PROP(c, dti, node, prop, ...) \ do { \ TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \ (c)->status = FAILED; \ - check_msg((c), dti, __VA_ARGS__); \ + check_msg((c), dti, node, prop, __VA_ARGS__); \ } while (0) + static void check_nodes_props(struct check *c, struct dt_info *dti, struct node *node) { struct node *child; @@ -126,7 +142,7 @@ error = error || run_check(prq, dti); if (prq->status != PASSED) { c->status = PREREQ; - check_msg(c, dti, "Failed prerequisite '%s'", + check_msg(c, dti, NULL, NULL, "Failed prerequisite '%s'", c->prereq[i]->name); } } @@ -156,7 +172,7 @@ static inline void check_always_fail(struct check *c, struct dt_info *dti, struct node *node) { - FAIL(c, dti, "always_fail check"); + FAIL(c, dti, node, "always_fail check"); } CHECK(always_fail, check_always_fail, NULL); @@ -171,14 +187,42 @@ return; /* Not present, assumed ok */ if (!data_is_one_string(prop->val)) - FAIL(c, dti, "\"%s\" property in %s is not a string", - propname, node->fullpath); + FAIL_PROP(c, dti, node, prop, "property is not a string"); } #define WARNING_IF_NOT_STRING(nm, propname) \ WARNING(nm, check_is_string, (propname)) #define ERROR_IF_NOT_STRING(nm, propname) \ ERROR(nm, check_is_string, (propname)) +static void check_is_string_list(struct check *c, struct dt_info *dti, + struct node *node) +{ + int rem, l; + struct property *prop; + char *propname = c->data; + char *str; + + prop = get_property(node, propname); + if (!prop) + return; /* Not present, assumed ok */ + + str = prop->val.val; + rem = prop->val.len; + while (rem > 0) { + l = strnlen(str, rem); + if (l == rem) { + FAIL_PROP(c, dti, node, prop, "property is not a string list"); + break; + } + rem -= l + 1; + str += l + 1; + } +} +#define WARNING_IF_NOT_STRING_LIST(nm, propname) \ + WARNING(nm, check_is_string_list, (propname)) +#define ERROR_IF_NOT_STRING_LIST(nm, propname) \ + ERROR(nm, check_is_string_list, (propname)) + static void check_is_cell(struct check *c, struct dt_info *dti, struct node *node) { @@ -190,8 +234,7 @@ return; /* Not present, assumed ok */ if (prop->val.len != sizeof(cell_t)) - FAIL(c, dti, "\"%s\" property in %s is not a single cell", - propname, node->fullpath); + FAIL_PROP(c, dti, node, prop, "property is not a single cell"); } #define WARNING_IF_NOT_CELL(nm, propname) \ WARNING(nm, check_is_cell, (propname)) @@ -212,8 +255,7 @@ child2; child2 = child2->next_sibling) if (streq(child->name, child2->name)) - FAIL(c, dti, "Duplicate node name %s", - child->fullpath); + FAIL(c, dti, child2, "Duplicate node name"); } ERROR(duplicate_node_names, check_duplicate_node_names, NULL); @@ -227,8 +269,7 @@ if (prop2->deleted) continue; if (streq(prop->name, prop2->name)) - FAIL(c, dti, "Duplicate property name %s in %s", - prop->name, node->fullpath); + FAIL_PROP(c, dti, node, prop, "Duplicate property name"); } } } @@ -246,8 +287,8 @@ int n = strspn(node->name, c->data); if (n < strlen(node->name)) - FAIL(c, dti, "Bad character '%c' in node %s", - node->name[n], node->fullpath); + FAIL(c, dti, node, "Bad character '%c' in node name", + node->name[n]); } ERROR(node_name_chars, check_node_name_chars, PROPNODECHARS "@"); @@ -257,8 +298,8 @@ int n = strspn(node->name, c->data); if (n < node->basenamelen) - FAIL(c, dti, "Character '%c' not recommended in node %s", - node->name[n], node->fullpath); + FAIL(c, dti, node, "Character '%c' not recommended in node name", + node->name[n]); } CHECK(node_name_chars_strict, check_node_name_chars_strict, PROPNODECHARSSTRICT); @@ -266,8 +307,7 @@ struct node *node) { if (strchr(get_unitname(node), '@')) - FAIL(c, dti, "Node %s has multiple '@' characters in name", - node->fullpath); + FAIL(c, dti, node, "multiple '@' characters in node name"); } ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars); @@ -277,6 +317,11 @@ const char *unitname = get_unitname(node); struct property *prop = get_property(node, "reg"); + if (get_subnode(node, "__overlay__")) { + /* HACK: Overlay fragments are a special case */ + return; + } + if (!prop) { prop = get_property(node, "ranges"); if (prop && !prop->val.len) @@ -285,12 +330,10 @@ if (prop) { if (!unitname[0]) - FAIL(c, dti, "Node %s has a reg or ranges property, but no unit name", - node->fullpath); + FAIL(c, dti, node, "node has a reg or ranges property, but no unit name"); } else { if (unitname[0]) - FAIL(c, dti, "Node %s has a unit name, but no reg property", - node->fullpath); + FAIL(c, dti, node, "node has a unit name, but no reg property"); } } WARNING(unit_address_vs_reg, check_unit_address_vs_reg, NULL); @@ -304,8 +347,8 @@ int n = strspn(prop->name, c->data); if (n < strlen(prop->name)) - FAIL(c, dti, "Bad character '%c' in property name \"%s\", node %s", - prop->name[n], prop->name, node->fullpath); + FAIL_PROP(c, dti, node, prop, "Bad character '%c' in property name", + prop->name[n]); } } ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS); @@ -336,8 +379,8 @@ n = strspn(name, c->data); } if (n < strlen(name)) - FAIL(c, dti, "Character '%c' not recommended in property name \"%s\", node %s", - name[n], prop->name, node->fullpath); + FAIL_PROP(c, dti, node, prop, "Character '%c' not recommended in property name", + name[n]); } } CHECK(property_name_chars_strict, check_property_name_chars_strict, PROPNODECHARSSTRICT); @@ -370,7 +413,7 @@ return; if ((othernode != node) || (otherprop != prop) || (othermark != mark)) - FAIL(c, dti, "Duplicate label '%s' on " DESCLABEL_FMT + FAIL(c, dti, node, "Duplicate label '%s' on " DESCLABEL_FMT " and " DESCLABEL_FMT, label, DESCLABEL_ARGS(node, prop, mark), DESCLABEL_ARGS(othernode, otherprop, othermark)); @@ -410,8 +453,8 @@ return 0; if (prop->val.len != sizeof(cell_t)) { - FAIL(c, dti, "%s has bad length (%d) %s property", - node->fullpath, prop->val.len, prop->name); + FAIL_PROP(c, dti, node, prop, "bad length (%d) %s property", + prop->val.len, prop->name); return 0; } @@ -422,8 +465,8 @@ /* "Set this node's phandle equal to some * other node's phandle". That's nonsensical * by construction. */ { - FAIL(c, dti, "%s in %s is a reference to another node", - prop->name, node->fullpath); + FAIL(c, dti, node, "%s is a reference to another node", + prop->name); } /* But setting this node's phandle equal to its own * phandle is allowed - that means allocate a unique @@ -436,8 +479,8 @@ phandle = propval_cell(prop); if ((phandle == 0) || (phandle == -1)) { - FAIL(c, dti, "%s has bad value (0x%x) in %s property", - node->fullpath, phandle, prop->name); + FAIL_PROP(c, dti, node, prop, "bad value (0x%x) in %s property", + phandle, prop->name); return 0; } @@ -463,16 +506,16 @@ return; if (linux_phandle && phandle && (phandle != linux_phandle)) - FAIL(c, dti, "%s has mismatching 'phandle' and 'linux,phandle'" - " properties", node->fullpath); + FAIL(c, dti, node, "mismatching 'phandle' and 'linux,phandle'" + " properties"); if (linux_phandle && !phandle) phandle = linux_phandle; other = get_node_by_phandle(root, phandle); if (other && (other != node)) { - FAIL(c, dti, "%s has duplicated phandle 0x%x (seen before at %s)", - node->fullpath, phandle, other->fullpath); + FAIL(c, dti, node, "duplicated phandle 0x%x (seen before at %s)", + phandle, other->fullpath); return; } @@ -496,8 +539,8 @@ if ((prop->val.len != node->basenamelen+1) || (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) { - FAIL(c, dti, "\"name\" property in %s is incorrect (\"%s\" instead" - " of base node name)", node->fullpath, prop->val.val); + FAIL(c, dti, node, "\"name\" property is incorrect (\"%s\" instead" + " of base node name)", prop->val.val); } else { /* The name property is correct, and therefore redundant. * Delete it */ @@ -531,7 +574,7 @@ refnode = get_node_by_ref(dt, m->ref); if (! refnode) { if (!(dti->dtsflags & DTSF_PLUGIN)) - FAIL(c, dti, "Reference to non-existent node or " + FAIL(c, dti, node, "Reference to non-existent node or " "label \"%s\"\n", m->ref); else /* mark the entry as unresolved */ *((fdt32_t *)(prop->val.val + m->offset)) = @@ -541,6 +584,8 @@ phandle = get_node_phandle(dt, refnode); *((fdt32_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle); + + reference_node(refnode); } } } @@ -563,7 +608,7 @@ refnode = get_node_by_ref(dt, m->ref); if (!refnode) { - FAIL(c, dti, "Reference to non-existent node or label \"%s\"\n", + FAIL(c, dti, node, "Reference to non-existent node or label \"%s\"\n", m->ref); continue; } @@ -571,11 +616,21 @@ path = refnode->fullpath; prop->val = data_insert_at_marker(prop->val, m, path, strlen(path) + 1); + + reference_node(refnode); } } } ERROR(path_references, fixup_path_references, NULL, &duplicate_node_names); +static void fixup_omit_unused_nodes(struct check *c, struct dt_info *dti, + struct node *node) +{ + if (node->omit_if_unused && !node->is_referenced) + delete_node(node); +} +ERROR(omit_unused_nodes, fixup_omit_unused_nodes, NULL, &phandle_references, &path_references); + /* * Semantic checks */ @@ -586,6 +641,45 @@ 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"); +WARNING_IF_NOT_STRING(label_is_string, "label"); + +WARNING_IF_NOT_STRING_LIST(compatible_is_string_list, "compatible"); + +static void check_names_is_string_list(struct check *c, struct dt_info *dti, + struct node *node) +{ + struct property *prop; + + for_each_property(node, prop) { + const char *s = strrchr(prop->name, '-'); + if (!s || !streq(s, "-names")) + continue; + + c->data = prop->name; + check_is_string_list(c, dti, node); + } +} +WARNING(names_is_string_list, check_names_is_string_list, NULL); + +static void check_alias_paths(struct check *c, struct dt_info *dti, + struct node *node) +{ + struct property *prop; + + if (!streq(node->name, "aliases")) + return; + + for_each_property(node, prop) { + if (!prop->val.val || !get_node_by_path(dti->dt, prop->val.val)) { + FAIL_PROP(c, dti, node, prop, "aliases property is not a valid node (%s)", + prop->val.val); + continue; + } + if (strspn(prop->name, LOWERCASE DIGITS "-") != strlen(prop->name)) + FAIL(c, dti, node, "aliases property name must include only lowercase and '-'"); + } +} +WARNING(alias_paths, check_alias_paths, NULL); static void fixup_addr_size_cells(struct check *c, struct dt_info *dti, struct node *node) @@ -622,21 +716,21 @@ return; /* No "reg", that's fine */ if (!node->parent) { - FAIL(c, dti, "Root node has a \"reg\" property"); + FAIL(c, dti, node, "Root node has a \"reg\" property"); return; } if (prop->val.len == 0) - FAIL(c, dti, "\"reg\" property in %s is empty", node->fullpath); + FAIL_PROP(c, dti, node, prop, "property is empty"); addr_cells = node_addr_cells(node->parent); size_cells = node_size_cells(node->parent); entrylen = (addr_cells + size_cells) * sizeof(cell_t); if (!entrylen || (prop->val.len % entrylen) != 0) - FAIL(c, dti, "\"reg\" property in %s has invalid length (%d bytes) " - "(#address-cells == %d, #size-cells == %d)", - node->fullpath, prop->val.len, addr_cells, size_cells); + FAIL_PROP(c, dti, node, prop, "property has invalid length (%d bytes) " + "(#address-cells == %d, #size-cells == %d)", + prop->val.len, addr_cells, size_cells); } WARNING(reg_format, check_reg_format, NULL, &addr_size_cells); @@ -651,7 +745,7 @@ return; if (!node->parent) { - FAIL(c, dti, "Root node has a \"ranges\" property"); + FAIL_PROP(c, dti, node, prop, "Root node has a \"ranges\" property"); return; } @@ -663,20 +757,20 @@ if (prop->val.len == 0) { if (p_addr_cells != c_addr_cells) - FAIL(c, dti, "%s has empty \"ranges\" property but its " - "#address-cells (%d) differs from %s (%d)", - node->fullpath, c_addr_cells, node->parent->fullpath, - p_addr_cells); + FAIL_PROP(c, dti, node, prop, "empty \"ranges\" property but its " + "#address-cells (%d) differs from %s (%d)", + c_addr_cells, node->parent->fullpath, + p_addr_cells); if (p_size_cells != c_size_cells) - FAIL(c, dti, "%s has empty \"ranges\" property but its " - "#size-cells (%d) differs from %s (%d)", - node->fullpath, c_size_cells, node->parent->fullpath, - p_size_cells); + FAIL_PROP(c, dti, node, prop, "empty \"ranges\" property but its " + "#size-cells (%d) differs from %s (%d)", + c_size_cells, node->parent->fullpath, + p_size_cells); } else if ((prop->val.len % entrylen) != 0) { - FAIL(c, dti, "\"ranges\" property in %s has invalid length (%d bytes) " - "(parent #address-cells == %d, child #address-cells == %d, " - "#size-cells == %d)", node->fullpath, prop->val.len, - p_addr_cells, c_addr_cells, c_size_cells); + FAIL_PROP(c, dti, node, prop, "\"ranges\" property has invalid length (%d bytes) " + "(parent #address-cells == %d, child #address-cells == %d, " + "#size-cells == %d)", prop->val.len, + p_addr_cells, c_addr_cells, c_size_cells); } } WARNING(ranges_format, check_ranges_format, NULL, &addr_size_cells); @@ -696,41 +790,32 @@ node->bus = &pci_bus; - if (!strneq(node->name, "pci", node->basenamelen) && - !strneq(node->name, "pcie", node->basenamelen)) - FAIL(c, dti, "Node %s node name is not \"pci\" or \"pcie\"", - node->fullpath); + if (!strprefixeq(node->name, node->basenamelen, "pci") && + !strprefixeq(node->name, node->basenamelen, "pcie")) + FAIL(c, dti, node, "node name is not \"pci\" or \"pcie\""); prop = get_property(node, "ranges"); if (!prop) - FAIL(c, dti, "Node %s missing ranges for PCI bridge (or not a bridge)", - node->fullpath); + FAIL(c, dti, node, "missing ranges for PCI bridge (or not a bridge)"); if (node_addr_cells(node) != 3) - FAIL(c, dti, "Node %s incorrect #address-cells for PCI bridge", - node->fullpath); + FAIL(c, dti, node, "incorrect #address-cells for PCI bridge"); if (node_size_cells(node) != 2) - FAIL(c, dti, "Node %s incorrect #size-cells for PCI bridge", - node->fullpath); + FAIL(c, dti, node, "incorrect #size-cells for PCI bridge"); prop = get_property(node, "bus-range"); - if (!prop) { - FAIL(c, dti, "Node %s missing bus-range for PCI bridge", - node->fullpath); + if (!prop) return; - } + if (prop->val.len != (sizeof(cell_t) * 2)) { - FAIL(c, dti, "Node %s bus-range must be 2 cells", - node->fullpath); + FAIL_PROP(c, dti, node, prop, "value must be 2 cells"); return; } cells = (cell_t *)prop->val.val; if (fdt32_to_cpu(cells[0]) > fdt32_to_cpu(cells[1])) - FAIL(c, dti, "Node %s bus-range 1st cell must be less than or equal to 2nd cell", - node->fullpath); + FAIL_PROP(c, dti, node, prop, "1st cell must be less than or equal to 2nd cell"); if (fdt32_to_cpu(cells[1]) > 0xff) - FAIL(c, dti, "Node %s bus-range maximum bus number must be less than 256", - node->fullpath); + FAIL_PROP(c, dti, node, prop, "maximum bus number must be less than 256"); } WARNING(pci_bridge, check_pci_bridge, NULL, &device_type_is_string, &addr_size_cells); @@ -760,8 +845,8 @@ max_bus = fdt32_to_cpu(cells[0]); } if ((bus_num < min_bus) || (bus_num > max_bus)) - FAIL(c, dti, "Node %s PCI bus number %d out of range, expected (%d - %d)", - node->fullpath, bus_num, min_bus, max_bus); + FAIL_PROP(c, dti, node, prop, "PCI bus number %d out of range, expected (%d - %d)", + bus_num, min_bus, max_bus); } WARNING(pci_device_bus_num, check_pci_device_bus_num, NULL, ®_format, &pci_bridge); @@ -778,25 +863,22 @@ prop = get_property(node, "reg"); if (!prop) { - FAIL(c, dti, "Node %s missing PCI reg property", node->fullpath); + FAIL(c, dti, node, "missing PCI reg property"); return; } cells = (cell_t *)prop->val.val; if (cells[1] || cells[2]) - FAIL(c, dti, "Node %s PCI reg config space address cells 2 and 3 must be 0", - node->fullpath); + FAIL_PROP(c, dti, node, prop, "PCI reg config space address cells 2 and 3 must be 0"); reg = fdt32_to_cpu(cells[0]); dev = (reg & 0xf800) >> 11; func = (reg & 0x700) >> 8; if (reg & 0xff000000) - FAIL(c, dti, "Node %s PCI reg address is not configuration space", - node->fullpath); + FAIL_PROP(c, dti, node, prop, "PCI reg address is not configuration space"); if (reg & 0x000000ff) - FAIL(c, dti, "Node %s PCI reg config space address register number must be 0", - node->fullpath); + FAIL_PROP(c, dti, node, prop, "PCI reg config space address register number must be 0"); if (func == 0) { snprintf(unit_addr, sizeof(unit_addr), "%x", dev); @@ -808,8 +890,8 @@ if (streq(unitname, unit_addr)) return; - FAIL(c, dti, "Node %s PCI unit address format error, expected \"%s\"", - node->fullpath, unit_addr); + FAIL(c, dti, node, "PCI unit address format error, expected \"%s\"", + unit_addr); } WARNING(pci_device_reg, check_pci_device_reg, NULL, ®_format, &pci_bridge); @@ -828,7 +910,7 @@ for (str = prop->val.val, end = str + prop->val.len; str < end; str += strnlen(str, end - str) + 1) { - if (strneq(str, compat, end - str)) + if (strprefixeq(str, end - str, compat)) return true; } return false; @@ -865,7 +947,7 @@ if (!cells) { if (node->parent->parent && !(node->bus == &simple_bus)) - FAIL(c, dti, "Node %s missing or empty reg/ranges property", node->fullpath); + FAIL(c, dti, node, "missing or empty reg/ranges property"); return; } @@ -875,8 +957,8 @@ snprintf(unit_addr, sizeof(unit_addr), "%"PRIx64, reg); if (!streq(unitname, unit_addr)) - FAIL(c, dti, "Node %s simple-bus unit address format error, expected \"%s\"", - node->fullpath, unit_addr); + FAIL(c, dti, node, "simple-bus unit address format error, expected \"%s\"", + unit_addr); } WARNING(simple_bus_reg, check_simple_bus_reg, NULL, ®_format, &simple_bus_bridge); @@ -892,14 +974,12 @@ return; if (!strncmp(unitname, "0x", 2)) { - FAIL(c, dti, "Node %s unit name should not have leading \"0x\"", - node->fullpath); + FAIL(c, dti, node, "unit name should not have leading \"0x\""); /* skip over 0x for next test */ unitname += 2; } if (unitname[0] == '0' && isxdigit(unitname[1])) - FAIL(c, dti, "Node %s unit name should not have leading 0s", - node->fullpath); + FAIL(c, dti, node, "unit name should not have leading 0s"); } WARNING(unit_address_format, check_unit_address_format, NULL, &node_name_format, &pci_bridge, &simple_bus_bridge); @@ -922,16 +1002,68 @@ return; if (node->parent->addr_cells == -1) - FAIL(c, dti, "Relying on default #address-cells value for %s", - node->fullpath); + FAIL(c, dti, node, "Relying on default #address-cells value"); if (node->parent->size_cells == -1) - FAIL(c, dti, "Relying on default #size-cells value for %s", - node->fullpath); + FAIL(c, dti, node, "Relying on default #size-cells value"); } WARNING(avoid_default_addr_size, check_avoid_default_addr_size, NULL, &addr_size_cells); +static void check_avoid_unnecessary_addr_size(struct check *c, struct dt_info *dti, + struct node *node) +{ + struct property *prop; + struct node *child; + bool has_reg = false; + + if (!node->parent || node->addr_cells < 0 || node->size_cells < 0) + return; + + if (get_property(node, "ranges") || !node->children) + return; + + for_each_child(node, child) { + prop = get_property(child, "reg"); + if (prop) + has_reg = true; + } + + if (!has_reg) + FAIL(c, dti, node, "unnecessary #address-cells/#size-cells without \"ranges\" or child \"reg\" property"); +} +WARNING(avoid_unnecessary_addr_size, check_avoid_unnecessary_addr_size, NULL, &avoid_default_addr_size); + +static void check_unique_unit_address(struct check *c, struct dt_info *dti, + struct node *node) +{ + struct node *childa; + + if (node->addr_cells < 0 || node->size_cells < 0) + return; + + if (!node->children) + return; + + for_each_child(node, childa) { + struct node *childb; + const char *addr_a = get_unitname(childa); + + if (!strlen(addr_a)) + continue; + + for_each_child(node, childb) { + const char *addr_b = get_unitname(childb); + if (childa == childb) + break; + + if (streq(addr_a, addr_b)) + FAIL(c, dti, childb, "duplicate unit-address (also used in node %s)", childa->fullpath); + } + } +} +WARNING(unique_unit_address, check_unique_unit_address, NULL, &avoid_default_addr_size); + static void check_obsolete_chosen_interrupt_controller(struct check *c, struct dt_info *dti, struct node *node) @@ -950,12 +1082,61 @@ prop = get_property(chosen, "interrupt-controller"); if (prop) - FAIL(c, dti, "/chosen has obsolete \"interrupt-controller\" " - "property"); + FAIL_PROP(c, dti, node, prop, + "/chosen has obsolete \"interrupt-controller\" property"); } WARNING(obsolete_chosen_interrupt_controller, check_obsolete_chosen_interrupt_controller, NULL); +static void check_chosen_node_is_root(struct check *c, struct dt_info *dti, + struct node *node) +{ + if (!streq(node->name, "chosen")) + return; + + if (node->parent != dti->dt) + FAIL(c, dti, node, "chosen node must be at root node"); +} +WARNING(chosen_node_is_root, check_chosen_node_is_root, NULL); + +static void check_chosen_node_bootargs(struct check *c, struct dt_info *dti, + struct node *node) +{ + struct property *prop; + + if (!streq(node->name, "chosen")) + return; + + prop = get_property(node, "bootargs"); + if (!prop) + return; + + c->data = prop->name; + check_is_string(c, dti, node); +} +WARNING(chosen_node_bootargs, check_chosen_node_bootargs, NULL); + +static void check_chosen_node_stdout_path(struct check *c, struct dt_info *dti, + struct node *node) +{ + struct property *prop; + + if (!streq(node->name, "chosen")) + return; + + prop = get_property(node, "stdout-path"); + if (!prop) { + prop = get_property(node, "linux,stdout-path"); + if (!prop) + return; + FAIL_PROP(c, dti, node, prop, "Use 'stdout-path' instead"); + } + + c->data = prop->name; + check_is_string(c, dti, node); +} +WARNING(chosen_node_stdout_path, check_chosen_node_stdout_path, NULL); + struct provider { const char *prop_name; const char *cell_name; @@ -972,8 +1153,9 @@ int cell, cellsize = 0; if (prop->val.len % sizeof(cell_t)) { - FAIL(c, dti, "property '%s' size (%d) is invalid, expected multiple of %ld in node %s", - prop->name, prop->val.len, sizeof(cell_t), node->fullpath); + FAIL_PROP(c, dti, node, prop, + "property size (%d) is invalid, expected multiple of %zu", + prop->val.len, sizeof(cell_t)); return; } @@ -988,6 +1170,10 @@ * entries when each index position has a specific definition. */ if (phandle == 0 || phandle == -1) { + /* Give up if this is an overlay with external references */ + if (dti->dtsflags & DTSF_PLUGIN) + break; + cellsize = 0; continue; } @@ -1000,14 +1186,16 @@ break; } if (!m) - FAIL(c, dti, "Property '%s', cell %d is not a phandle reference in %s", - prop->name, cell, node->fullpath); + FAIL_PROP(c, dti, node, prop, + "cell %d is not a phandle reference", + cell); } provider_node = get_node_by_phandle(root, phandle); if (!provider_node) { - FAIL(c, dti, "Could not get phandle node for %s:%s(cell %d)", - node->fullpath, prop->name, cell); + FAIL_PROP(c, dti, node, prop, + "Could not get phandle node for (cell %d)", + cell); break; } @@ -1017,16 +1205,17 @@ } else if (provider->optional) { cellsize = 0; } else { - FAIL(c, dti, "Missing property '%s' in node %s or bad phandle (referred from %s:%s[%d])", + FAIL(c, dti, node, "Missing property '%s' in node %s or bad phandle (referred from %s[%d])", provider->cell_name, provider_node->fullpath, - node->fullpath, prop->name, cell); + prop->name, cell); break; } if (prop->val.len < ((cell + cellsize + 1) * sizeof(cell_t))) { - FAIL(c, dti, "%s property size (%d) too small for cell size %d in %s", - prop->name, prop->val.len, cellsize, node->fullpath); + FAIL_PROP(c, dti, node, prop, + "property size (%d) too small for cell size %d", + prop->val.len, cellsize); } } } @@ -1062,7 +1251,7 @@ WARNING_PROPERTY_PHANDLE_CELLS(power_domains, "power-domains", "#power-domain-cells"); WARNING_PROPERTY_PHANDLE_CELLS(pwms, "pwms", "#pwm-cells"); WARNING_PROPERTY_PHANDLE_CELLS(resets, "resets", "#reset-cells"); -WARNING_PROPERTY_PHANDLE_CELLS(sound_dais, "sound-dais", "#sound-dai-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(sound_dai, "sound-dai", "#sound-dai-cells"); WARNING_PROPERTY_PHANDLE_CELLS(thermal_sensors, "thermal-sensors", "#thermal-sensor-cells"); static bool prop_is_gpio(struct property *prop) @@ -1128,8 +1317,8 @@ if (!streq(str, "gpio")) continue; - FAIL(c, dti, "'[*-]gpio' is deprecated, use '[*-]gpios' instead for %s:%s", - node->fullpath, prop->name); + FAIL_PROP(c, dti, node, prop, + "'[*-]gpio' is deprecated, use '[*-]gpios' instead"); } } @@ -1163,9 +1352,8 @@ return; if (irq_prop->val.len % sizeof(cell_t)) - FAIL(c, dti, "property '%s' size (%d) is invalid, expected multiple of %ld in node %s", - irq_prop->name, irq_prop->val.len, sizeof(cell_t), - node->fullpath); + FAIL_PROP(c, dti, node, irq_prop, "size (%d) is invalid, expected multiple of %zu", + irq_prop->val.len, sizeof(cell_t)); while (parent && !prop) { if (parent != node && node_is_interrupt_provider(parent)) { @@ -1176,16 +1364,19 @@ prop = get_property(parent, "interrupt-parent"); if (prop) { phandle = propval_cell(prop); + /* Give up if this is an overlay with external references */ + if ((phandle == 0 || phandle == -1) && + (dti->dtsflags & DTSF_PLUGIN)) + return; + irq_node = get_node_by_phandle(root, phandle); if (!irq_node) { - FAIL(c, dti, "Bad interrupt-parent phandle for %s", - node->fullpath); + FAIL_PROP(c, dti, parent, prop, "Bad phandle"); return; } if (!node_is_interrupt_provider(irq_node)) - FAIL(c, dti, - "Missing interrupt-controller or interrupt-map property in %s", - irq_node->fullpath); + FAIL(c, dti, irq_node, + "Missing interrupt-controller or interrupt-map property"); break; } @@ -1194,27 +1385,171 @@ } if (!irq_node) { - FAIL(c, dti, "Missing interrupt-parent for %s", node->fullpath); + FAIL(c, dti, node, "Missing interrupt-parent"); return; } prop = get_property(irq_node, "#interrupt-cells"); if (!prop) { - FAIL(c, dti, "Missing #interrupt-cells in interrupt-parent %s", - irq_node->fullpath); + FAIL(c, dti, irq_node, "Missing #interrupt-cells in interrupt-parent"); return; } irq_cells = propval_cell(prop); if (irq_prop->val.len % (irq_cells * sizeof(cell_t))) { - FAIL(c, dti, - "interrupts size is (%d), expected multiple of %d in %s", - irq_prop->val.len, (int)(irq_cells * sizeof(cell_t)), - node->fullpath); + FAIL_PROP(c, dti, node, prop, + "size is (%d), expected multiple of %d", + irq_prop->val.len, (int)(irq_cells * sizeof(cell_t))); } } WARNING(interrupts_property, check_interrupts_property, &phandle_references); +static const struct bus_type graph_port_bus = { + .name = "graph-port", +}; + +static const struct bus_type graph_ports_bus = { + .name = "graph-ports", +}; + +static void check_graph_nodes(struct check *c, struct dt_info *dti, + struct node *node) +{ + struct node *child; + + for_each_child(node, child) { + if (!(strprefixeq(child->name, child->basenamelen, "endpoint") || + get_property(child, "remote-endpoint"))) + continue; + + node->bus = &graph_port_bus; + + /* The parent of 'port' nodes can be either 'ports' or a device */ + if (!node->parent->bus && + (streq(node->parent->name, "ports") || get_property(node, "reg"))) + node->parent->bus = &graph_ports_bus; + + break; + } + +} +WARNING(graph_nodes, check_graph_nodes, NULL); + +static void check_graph_child_address(struct check *c, struct dt_info *dti, + struct node *node) +{ + int cnt = 0; + struct node *child; + + if (node->bus != &graph_ports_bus && node->bus != &graph_port_bus) + return; + + for_each_child(node, child) { + struct property *prop = get_property(child, "reg"); + + /* No error if we have any non-zero unit address */ + if (prop && propval_cell(prop) != 0) + return; + + cnt++; + } + + if (cnt == 1 && node->addr_cells != -1) + FAIL(c, dti, node, "graph node has single child node '%s', #address-cells/#size-cells are not necessary", + node->children->name); +} +WARNING(graph_child_address, check_graph_child_address, NULL, &graph_nodes); + +static void check_graph_reg(struct check *c, struct dt_info *dti, + struct node *node) +{ + char unit_addr[9]; + const char *unitname = get_unitname(node); + struct property *prop; + + prop = get_property(node, "reg"); + if (!prop || !unitname) + return; + + if (!(prop->val.val && prop->val.len == sizeof(cell_t))) { + FAIL(c, dti, node, "graph node malformed 'reg' property"); + return; + } + + snprintf(unit_addr, sizeof(unit_addr), "%x", propval_cell(prop)); + if (!streq(unitname, unit_addr)) + FAIL(c, dti, node, "graph node unit address error, expected \"%s\"", + unit_addr); + + if (node->parent->addr_cells != 1) + FAIL_PROP(c, dti, node, get_property(node, "#address-cells"), + "graph node '#address-cells' is %d, must be 1", + node->parent->addr_cells); + if (node->parent->size_cells != 0) + FAIL_PROP(c, dti, node, get_property(node, "#size-cells"), + "graph node '#size-cells' is %d, must be 0", + node->parent->size_cells); +} + +static void check_graph_port(struct check *c, struct dt_info *dti, + struct node *node) +{ + if (node->bus != &graph_port_bus) + return; + + if (!strprefixeq(node->name, node->basenamelen, "port")) + FAIL(c, dti, node, "graph port node name should be 'port'"); + + check_graph_reg(c, dti, node); +} +WARNING(graph_port, check_graph_port, NULL, &graph_nodes); + +static struct node *get_remote_endpoint(struct check *c, struct dt_info *dti, + struct node *endpoint) +{ + int phandle; + struct node *node; + struct property *prop; + + prop = get_property(endpoint, "remote-endpoint"); + if (!prop) + return NULL; + + phandle = propval_cell(prop); + /* Give up if this is an overlay with external references */ + if (phandle == 0 || phandle == -1) + return NULL; + + node = get_node_by_phandle(dti->dt, phandle); + if (!node) + FAIL_PROP(c, dti, endpoint, prop, "graph phandle is not valid"); + + return node; +} + +static void check_graph_endpoint(struct check *c, struct dt_info *dti, + struct node *node) +{ + struct node *remote_node; + + if (!node->parent || node->parent->bus != &graph_port_bus) + return; + + if (!strprefixeq(node->name, node->basenamelen, "endpoint")) + FAIL(c, dti, node, "graph endpont node name should be 'endpoint'"); + + check_graph_reg(c, dti, node); + + remote_node = get_remote_endpoint(c, dti, node); + if (!remote_node) + return; + + if (get_remote_endpoint(c, dti, remote_node) != node) + FAIL(c, dti, node, "graph connection to node '%s' is not bidirectional", + remote_node->fullpath); +} +WARNING(graph_endpoint, check_graph_endpoint, NULL, &graph_nodes); + static struct check *check_table[] = { &duplicate_node_names, &duplicate_property_names, &node_name_chars, &node_name_format, &property_name_chars, @@ -1224,9 +1559,13 @@ &explicit_phandles, &phandle_references, &path_references, + &omit_unused_nodes, &address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell, &device_type_is_string, &model_is_string, &status_is_string, + &label_is_string, + + &compatible_is_string_list, &names_is_string_list, &property_name_chars_strict, &node_name_chars_strict, @@ -1244,7 +1583,10 @@ &simple_bus_reg, &avoid_default_addr_size, + &avoid_unnecessary_addr_size, + &unique_unit_address, &obsolete_chosen_interrupt_controller, + &chosen_node_is_root, &chosen_node_bootargs, &chosen_node_stdout_path, &clocks_property, &cooling_device_property, @@ -1260,13 +1602,17 @@ &power_domains_property, &pwms_property, &resets_property, - &sound_dais_property, + &sound_dai_property, &thermal_sensors_property, &deprecated_gpio_property, &gpios_property, &interrupts_property, + &alias_paths, + + &graph_nodes, &graph_child_address, &graph_port, &graph_endpoint, + &always_fail, }; diff -Nru device-tree-compiler-1.4.5/data.c device-tree-compiler-1.4.7/data.c --- device-tree-compiler-1.4.5/data.c 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/data.c 2018-07-23 03:00:50.000000000 +0000 @@ -74,7 +74,8 @@ struct data d; char *q; - d = data_grow_for(empty_data, len + 1); + d = data_add_marker(empty_data, TYPE_STRING, NULL); + d = data_grow_for(d, len + 1); q = d.val; while (i < len) { @@ -94,6 +95,7 @@ { struct data d = empty_data; + d = data_add_marker(d, TYPE_BLOB, NULL); while (!feof(f) && (d.len < maxlen)) { size_t chunksize, ret; diff -Nru device-tree-compiler-1.4.5/debian/changelog device-tree-compiler-1.4.7/debian/changelog --- device-tree-compiler-1.4.5/debian/changelog 2017-10-06 18:51:12.000000000 +0000 +++ device-tree-compiler-1.4.7/debian/changelog 2019-08-16 15:29:04.000000000 +0000 @@ -1,6 +1,73 @@ +device-tree-compiler (1.4.7-3ubuntu2~cloud0) bionic-train; urgency=medium + + * New update for the Ubuntu Cloud Archive. + + -- Openstack Ubuntu Testing Bot Fri, 16 Aug 2019 15:29:04 +0000 + +device-tree-compiler (1.4.7-3ubuntu2) eoan; urgency=medium + + * d/control: run update maintainer that was forgotten on the former upload, + but required when deriving from Debian. + + -- Christian Ehrhardt Tue, 25 Jun 2019 09:54:00 +0200 + +device-tree-compiler (1.4.7-3ubuntu1) eoan; urgency=medium + + * d/p/lp-1834143-Update-version.lds.patch: fix the lack of function exports + for fdt_get_max_phandle, fdt_check_full, fdt_setprop_placeholder and + fdt_property_placeholder to avoid users of libfdt.h to FTBFS (LP: #1834143) + + -- Christian Ehrhardt Tue, 25 Jun 2019 08:19:06 +0200 + +device-tree-compiler (1.4.7-3) unstable; urgency=medium + + * Add Build-Depends on pkg-config, which is used to check for valgrind. + + -- Vagrant Cascadian Tue, 11 Sep 2018 00:51:07 -0700 + +device-tree-compiler (1.4.7-2) unstable; urgency=medium + + * Add patch from upstream making valgrind optional. + * Only Build-Depend on valgrind for architectures where valgrind is + available. + * Update Standards-Version to 4.2.1, no changes needed. + + -- Vagrant Cascadian Mon, 10 Sep 2018 23:11:53 -0700 + +device-tree-compiler (1.4.7-1) unstable; urgency=medium + + * New upstream release. + * debian/control: + - Add Build-Depends on valgrind, used in tests. + - Add Rules-Requires-Root: no. + - Update Standards-Version to 4.2.0. + + -- Vagrant Cascadian Thu, 16 Aug 2018 13:38:37 -0700 + +device-tree-compiler (1.4.6-1) unstable; urgency=medium + + [ Vagrant Cascadian ] + * New upstream release. + * Drop patches applied upstream. + * Update debian/watch: + - Use tarballs downloaded from https://www.kernel.org/pub instead of + generated tarballs from git tags. + - Check signature of downloaded tarball. Thanks to Osamu Aoki. + * Use debhelper compat level 11. + * Update to Standards-Version 4.1.4, no changes needed. + * Support "nodoc" in DEB_BUILD_PROFILES and DEB_BUILD_OPTIONS. + * Make build more verbose. + * Use dpkg buildflags.mk, passing CFLAGS and CPPFLAGS to build. + + [ Dima Kogan ] + * Moved Vcs tags to point to salsa. + + -- Vagrant Cascadian Thu, 26 Apr 2018 11:02:44 -0700 + device-tree-compiler (1.4.5-3) unstable; urgency=medium - * Add patch from upstream to fix bugs in testsuite for 32-bit arm. (Closes: #877797) + * Add patch from upstream to fix bugs in testsuite for 32-bit + arm. (Closes: #877797) -- Vagrant Cascadian Fri, 06 Oct 2017 11:51:12 -0700 diff -Nru device-tree-compiler-1.4.5/debian/compat device-tree-compiler-1.4.7/debian/compat --- device-tree-compiler-1.4.5/debian/compat 2017-10-06 17:35:17.000000000 +0000 +++ device-tree-compiler-1.4.7/debian/compat 2019-06-06 06:02:32.000000000 +0000 @@ -1 +1 @@ -10 +11 diff -Nru device-tree-compiler-1.4.5/debian/control device-tree-compiler-1.4.7/debian/control --- device-tree-compiler-1.4.5/debian/control 2017-10-06 17:35:17.000000000 +0000 +++ device-tree-compiler-1.4.7/debian/control 2019-06-25 07:53:52.000000000 +0000 @@ -1,13 +1,21 @@ Source: device-tree-compiler Section: devel Priority: optional -Maintainer: Héctor Orón Martínez +Maintainer: Ubuntu Developers +XSBC-Original-Maintainer: Héctor Orón Martínez Uploaders: Riku Voipio , Vagrant Cascadian -Standards-Version: 4.1.0 -Build-Depends: debhelper (>= 10), flex, bison, texlive, texlive-latex-extra +Standards-Version: 4.2.1 +Build-Depends: debhelper (>= 11), + flex, + bison, + pkg-config, + texlive , + texlive-latex-extra , + valgrind [amd64 arm64 armhf i386 mips mips64el mipsel powerpc ppc64 ppc64el s390x], +Rules-Requires-Root: no Homepage: https://git.kernel.org/cgit/utils/dtc/dtc.git -Vcs-Git: https://anonscm.debian.org/git/crosstoolchain/device-tree-compiler.git -Vcs-Browser: https://anonscm.debian.org/cgit/crosstoolchain/device-tree-compiler.git/ +Vcs-Git: https://salsa.debian.org/crosstoolchain-team/device-tree-compiler.git +Vcs-Browser: https://salsa.debian.org/crosstoolchain-team/device-tree-compiler Package: device-tree-compiler Architecture: any diff -Nru device-tree-compiler-1.4.5/debian/patches/02-checks-Use-proper-format-modifier-for-size_t.patch device-tree-compiler-1.4.7/debian/patches/02-checks-Use-proper-format-modifier-for-size_t.patch --- device-tree-compiler-1.4.5/debian/patches/02-checks-Use-proper-format-modifier-for-size_t.patch 2017-10-06 17:35:17.000000000 +0000 +++ device-tree-compiler-1.4.7/debian/patches/02-checks-Use-proper-format-modifier-for-size_t.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -From 497432fd2131967f349e69dc5d259072151cc4b4 Mon Sep 17 00:00:00 2001 -From: Thierry Reding -Date: Wed, 27 Sep 2017 15:04:09 +0200 -Subject: [PATCH 1/3] checks: Use proper format modifier for size_t - -The size of size_t can vary between architectures, so using %ld isn't -going to work on 32-bit builds. Use the %zu modifier to make sure it is -always correct. - -Signed-off-by: Thierry Reding -Acked-by: Rob Herring -Signed-off-by: David Gibson ---- - checks.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/checks.c b/checks.c -index 902f2e3..08a3a29 100644 ---- a/checks.c -+++ b/checks.c -@@ -972,7 +972,7 @@ static void check_property_phandle_args(struct check *c, - int cell, cellsize = 0; - - if (prop->val.len % sizeof(cell_t)) { -- FAIL(c, dti, "property '%s' size (%d) is invalid, expected multiple of %ld in node %s", -+ FAIL(c, dti, "property '%s' size (%d) is invalid, expected multiple of %zu in node %s", - prop->name, prop->val.len, sizeof(cell_t), node->fullpath); - return; - } -@@ -1163,7 +1163,7 @@ static void check_interrupts_property(struct check *c, - return; - - if (irq_prop->val.len % sizeof(cell_t)) -- FAIL(c, dti, "property '%s' size (%d) is invalid, expected multiple of %ld in node %s", -+ FAIL(c, dti, "property '%s' size (%d) is invalid, expected multiple of %zu in node %s", - irq_prop->name, irq_prop->val.len, sizeof(cell_t), - node->fullpath); - --- -2.11.0 - diff -Nru device-tree-compiler-1.4.5/debian/patches/02-Make-valgrind-optional.patch device-tree-compiler-1.4.7/debian/patches/02-Make-valgrind-optional.patch --- device-tree-compiler-1.4.5/debian/patches/02-Make-valgrind-optional.patch 1970-01-01 00:00:00.000000000 +0000 +++ device-tree-compiler-1.4.7/debian/patches/02-Make-valgrind-optional.patch 2019-06-06 06:02:32.000000000 +0000 @@ -0,0 +1,102 @@ +From b94c056b137e59deefc62fbfe0cd3a23edfcc07c Mon Sep 17 00:00:00 2001 +From: David Gibson +Date: Mon, 10 Sep 2018 16:46:59 +1000 +Subject: [PATCH] Make valgrind optional + +Some platforms don't have valgrind support, and sometimes you simply might +not want to use valgrind. But at present, dtc, or more specifically its +testsuite, won't compile without valgrind because we use the valgrind +client interface in some places to improve our testing and suppress false +positives. + +This adds some Makefile detection to correctly handle the case where +valgrind is not available. + +Signed-off-by: David Gibson +--- + .travis.yml | 9 +++------ + Makefile | 7 +++++++ + tests/Makefile.tests | 5 +++++ + tests/testutils.c | 10 ++++++++++ + 4 files changed, 25 insertions(+), 6 deletions(-) + +diff --git a/.travis.yml b/.travis.yml +index 87adfa0..ecdef0d 100644 +--- a/.travis.yml ++++ b/.travis.yml +@@ -25,11 +25,8 @@ matrix: + - make + - make check && make checkm + +- # Check it builds properly without the python bits +- - addons: +- apt: +- packages: +- - valgrind +- script: ++ # Check it builds properly without optional packages: ++ # python, valgrind ++ - script: + - make + - make check +diff --git a/Makefile b/Makefile +index d8ebc4f..c4bfae6 100644 +--- a/Makefile ++++ b/Makefile +@@ -39,6 +39,13 @@ INCLUDEDIR = $(PREFIX)/include + HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \ + sed -e 's/\(cygwin\|msys\).*/\1/') + ++NO_VALGRIND := $(shell $(PKG_CONFIG) --exists valgrind; echo $$?) ++ifeq ($(NO_VALGRIND),1) ++ CFLAGS += -DNO_VALGRIND ++else ++ CFLAGS += $(shell $(PKG_CONFIG) --cflags valgrind) ++endif ++ + ifeq ($(HOSTOS),darwin) + SHAREDLIB_EXT = dylib + SHAREDLIB_CFLAGS = -fPIC +diff --git a/tests/Makefile.tests b/tests/Makefile.tests +index 6903333..bd1c8ef 100644 +--- a/tests/Makefile.tests ++++ b/tests/Makefile.tests +@@ -83,8 +83,13 @@ tests_clean: + check: tests ${TESTS_BIN} $(TESTS_PYLIBFDT) + cd $(TESTS_PREFIX); ./run_tests.sh + ++ifeq ($(NO_VALGRIND),1) ++checkm: ++ @echo "make checkm requires valgrind, but NO_VALGRIND=1" ++else + checkm: tests ${TESTS_BIN} $(TESTS_PYLIBFDT) + cd $(TESTS_PREFIX); ./run_tests.sh -m 2>&1 | tee vglog.$$$$ ++endif + + checkv: tests ${TESTS_BIN} $(TESTS_PYLIBFDT) + cd $(TESTS_PREFIX); ./run_tests.sh -v +diff --git a/tests/testutils.c b/tests/testutils.c +index 75e3e20..0217b02 100644 +--- a/tests/testutils.c ++++ b/tests/testutils.c +@@ -30,7 +30,17 @@ + #include + #include + ++#if NO_VALGRIND ++static inline void VALGRIND_MAKE_MEM_UNDEFINED(void *p, size_t len) ++{ ++} ++ ++static inline void VALGRIND_MAKE_MEM_DEFINED(void *p, size_t len) ++{ ++} ++#else + #include ++#endif + + #include + +-- +2.11.0 + diff -Nru device-tree-compiler-1.4.5/debian/patches/03-tests-Avoid-64-bit-arithmetic-in-assembler.patch device-tree-compiler-1.4.7/debian/patches/03-tests-Avoid-64-bit-arithmetic-in-assembler.patch --- device-tree-compiler-1.4.5/debian/patches/03-tests-Avoid-64-bit-arithmetic-in-assembler.patch 2017-10-06 17:35:54.000000000 +0000 +++ device-tree-compiler-1.4.7/debian/patches/03-tests-Avoid-64-bit-arithmetic-in-assembler.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,138 +0,0 @@ -From f8872e29ce06d78d3db71b3ab26a7465fc8a9586 Mon Sep 17 00:00:00 2001 -From: David Gibson -Date: Fri, 6 Oct 2017 23:07:30 +1100 -Subject: [PATCH] tests: Avoid 64-bit arithmetic in assembler - -For testing we (ab)use the assembler to build us a sample dtb, independent -of the other tools (dtc and libfdt) that we're trying to test. In a few -places this uses 64-bit arithmetic to decompose 64-bit constants into -the individual bytes in the blob. - -Unfortunately, it seems that some builds of GNU as don't support >32 bit -arithmetic, though it's not entirely clear to me which do and which don't -(Fedora i386 does support 64-bit, Debian arm32 doesn't). - -Anyway, to be safe, this avoids 64-bit arithmetic in assembler at the cost -of some extra awkwardness because we have to define the values in 32-bit -halves. - -Signed-off-by: David Gibson ---- - tests/testdata.h | 20 +++++++++++++++----- - tests/trees.S | 33 +++++++++++++-------------------- - 2 files changed, 28 insertions(+), 25 deletions(-) - -diff --git a/tests/testdata.h b/tests/testdata.h -index 3588778..f6bbe1d 100644 ---- a/tests/testdata.h -+++ b/tests/testdata.h -@@ -4,15 +4,25 @@ - #define ASM_CONST_LL(x) (x##ULL) - #endif - --#define TEST_ADDR_1 ASM_CONST_LL(0xdeadbeef00000000) --#define TEST_SIZE_1 ASM_CONST_LL(0x100000) --#define TEST_ADDR_2 ASM_CONST_LL(123456789) --#define TEST_SIZE_2 ASM_CONST_LL(010000) -+#define TEST_ADDR_1H ASM_CONST_LL(0xdeadbeef) -+#define TEST_ADDR_1L ASM_CONST_LL(0x00000000) -+#define TEST_ADDR_1 ((TEST_ADDR_1H << 32) | TEST_ADDR_1L) -+#define TEST_SIZE_1H ASM_CONST_LL(0x00000000) -+#define TEST_SIZE_1L ASM_CONST_LL(0x00100000) -+#define TEST_SIZE_1 ((TEST_SIZE_1H << 32) | TEST_SIZE_1L) -+#define TEST_ADDR_2H ASM_CONST_LL(0) -+#define TEST_ADDR_2L ASM_CONST_LL(123456789) -+#define TEST_ADDR_2 ((TEST_ADDR_2H << 32) | TEST_ADDR_2L) -+#define TEST_SIZE_2H ASM_CONST_LL(0) -+#define TEST_SIZE_2L ASM_CONST_LL(010000) -+#define TEST_SIZE_2 ((TEST_SIZE_2H << 32) | TEST_SIZE_2L) - - #define TEST_VALUE_1 0xdeadbeef - #define TEST_VALUE_2 123456789 - --#define TEST_VALUE64_1 ASM_CONST_LL(0xdeadbeef01abcdef) -+#define TEST_VALUE64_1H ASM_CONST_LL(0xdeadbeef) -+#define TEST_VALUE64_1L ASM_CONST_LL(0x01abcdef) -+#define TEST_VALUE64_1 ((TEST_VALUE64_1H << 32) | TEST_VALUE64_1L) - - #define PHANDLE_1 0x2000 - #define PHANDLE_2 0x2001 -diff --git a/tests/trees.S b/tests/trees.S -index 9854d1d..9859914 100644 ---- a/tests/trees.S -+++ b/tests/trees.S -@@ -7,16 +7,6 @@ - .byte ((val) >> 8) & 0xff ; \ - .byte (val) & 0xff ; - --#define FDTQUAD(val) \ -- .byte ((val) >> 56) & 0xff ; \ -- .byte ((val) >> 48) & 0xff ; \ -- .byte ((val) >> 40) & 0xff ; \ -- .byte ((val) >> 32) & 0xff ; \ -- .byte ((val) >> 24) & 0xff ; \ -- .byte ((val) >> 16) & 0xff ; \ -- .byte ((val) >> 8) & 0xff ; \ -- .byte (val) & 0xff ; -- - #define TREE_HDR(tree) \ - .balign 8 ; \ - .globl _##tree ; \ -@@ -33,14 +23,16 @@ tree: \ - FDTLONG(tree##_strings_end - tree##_strings) ; \ - FDTLONG(tree##_struct_end - tree##_struct) ; - --#define RSVMAP_ENTRY(addr, len) \ -- FDTQUAD(addr) ; \ -- FDTQUAD(len) ; \ -+#define RSVMAP_ENTRY(addrh, addrl, lenh, lenl) \ -+ FDTLONG(addrh) ; \ -+ FDTLONG(addrl) ; \ -+ FDTLONG(lenh) ; \ -+ FDTLONG(lenl) - - #define EMPTY_RSVMAP(tree) \ - .balign 8 ; \ - tree##_rsvmap: ; \ -- RSVMAP_ENTRY(0, 0) \ -+ RSVMAP_ENTRY(0, 0, 0, 0) \ - tree##_rsvmap_end: ; - - #define PROPHDR(tree, name, len) \ -@@ -52,9 +44,10 @@ tree##_rsvmap_end: ; - PROPHDR(tree, name, 4) \ - FDTLONG(val) ; - --#define PROP_INT64(tree, name, val) \ -+#define PROP_INT64(tree, name, valh, vall) \ - PROPHDR(tree, name, 8) \ -- FDTQUAD(val) ; -+ FDTLONG(valh) ; \ -+ FDTLONG(vall) ; - - #define PROP_STR(tree, name, str) \ - PROPHDR(tree, name, 55f - 54f) \ -@@ -81,16 +74,16 @@ tree##_##name: ; \ - - .balign 8 - test_tree1_rsvmap: -- RSVMAP_ENTRY(TEST_ADDR_1, TEST_SIZE_1) -- RSVMAP_ENTRY(TEST_ADDR_2, TEST_SIZE_2) -- RSVMAP_ENTRY(0, 0) -+ RSVMAP_ENTRY(TEST_ADDR_1H, TEST_ADDR_1L, TEST_SIZE_1H, TEST_SIZE_1L) -+ RSVMAP_ENTRY(TEST_ADDR_2H, TEST_ADDR_2L, TEST_SIZE_2H, TEST_SIZE_2L) -+ RSVMAP_ENTRY(0, 0, 0, 0) - test_tree1_rsvmap_end: - - test_tree1_struct: - BEGIN_NODE("") - PROP_STR(test_tree1, compatible, "test_tree1") - PROP_INT(test_tree1, prop_int, TEST_VALUE_1) -- PROP_INT64(test_tree1, prop_int64, TEST_VALUE64_1) -+ PROP_INT64(test_tree1, prop_int64, TEST_VALUE64_1H, TEST_VALUE64_1L) - PROP_STR(test_tree1, prop_str, TEST_STRING_1) - PROP_INT(test_tree1, address_cells, 1) - PROP_INT(test_tree1, size_cells, 0) --- -2.11.0 - diff -Nru device-tree-compiler-1.4.5/debian/patches/lp-1834143-Update-version.lds.patch device-tree-compiler-1.4.7/debian/patches/lp-1834143-Update-version.lds.patch --- device-tree-compiler-1.4.5/debian/patches/lp-1834143-Update-version.lds.patch 1970-01-01 00:00:00.000000000 +0000 +++ device-tree-compiler-1.4.7/debian/patches/lp-1834143-Update-version.lds.patch 2019-06-25 06:17:55.000000000 +0000 @@ -0,0 +1,44 @@ +From eac2ad495b29f15d78daa2a7226653f36515cd7a Mon Sep 17 00:00:00 2001 +From: David Gibson +Date: Mon, 25 Mar 2019 14:52:47 +1100 +Subject: [PATCH] Update version.lds again + +Yet again, we've added several functions to libfdt that were supposed +to be exported, but forgotten to add them to the versio.lds script. +This adds them. + +Note: this is required to make the new functions in 1.4.7 like +fdt_check_full usable from the .so file. The archive will follow +upstream, but the IBM cloud PPA will use this backport of the fix +to be able to build already. +Origin: upstream, https://github.com/dgibson/dtc/commit/eac2ad49 +Last-Update: 2019-06-06 + +Signed-off-by: David Gibson + +Origin: upstream, https://github.com/dgibson/dtc/commit/eac2ad49 +Bug-Ubuntu: https://bugs.launchpad.net/bugs/1834143 +Last-Update: 2019-06-25 + +--- + libfdt/version.lds | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/libfdt/version.lds b/libfdt/version.lds +index 9f5d708..a5fe62d 100644 +--- a/libfdt/version.lds ++++ b/libfdt/version.lds +@@ -66,6 +66,10 @@ LIBFDT_1.2 { + fdt_resize; + fdt_overlay_apply; + fdt_get_string; ++ fdt_get_max_phandle; ++ fdt_check_full; ++ fdt_setprop_placeholder; ++ fdt_property_placeholder; + local: + *; + }; +-- +2.21.0 + diff -Nru device-tree-compiler-1.4.5/debian/patches/series device-tree-compiler-1.4.7/debian/patches/series --- device-tree-compiler-1.4.5/debian/patches/series 2017-10-06 17:36:17.000000000 +0000 +++ device-tree-compiler-1.4.7/debian/patches/series 2019-06-25 06:15:58.000000000 +0000 @@ -1,3 +1,3 @@ 01_build_doc.patch -02-checks-Use-proper-format-modifier-for-size_t.patch -03-tests-Avoid-64-bit-arithmetic-in-assembler.patch +02-Make-valgrind-optional.patch +lp-1834143-Update-version.lds.patch diff -Nru device-tree-compiler-1.4.5/debian/rules device-tree-compiler-1.4.7/debian/rules --- device-tree-compiler-1.4.5/debian/rules 2017-10-06 17:35:17.000000000 +0000 +++ device-tree-compiler-1.4.7/debian/rules 2019-06-06 06:02:32.000000000 +0000 @@ -7,8 +7,6 @@ export DEB_BUILD_MAINT_OPTIONS=hardening=+all -export CFLAGS = -Wall -g -fPIC - # python library builds with warnings, temporarily disabled. export NO_PYTHON = 1 @@ -17,18 +15,20 @@ export CC = $(DEB_HOST_GNU_TYPE)-gcc endif -ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) - CFLAGS += -O0 -else - CFLAGS += -O2 -endif +include /usr/share/dpkg/buildflags.mk +CFLAGS += -fPIC -Werror -Wall -Wpointer-arith -Wcast-qual \ + -Wnested-externs -Wstrict-prototypes -Wmissing-prototypes \ + -Wredundant-decls -Wshadow +CPPFLAGS += -I libfdt -I . %: dh $@ override_dh_auto_build: - dh_auto_build + dh_auto_build -- V=1 CFLAGS="$(CFLAGS)" CPPFLAGS="$(CPPFLAGS)" +ifeq (,$(findstring nodoc,$(DEB_BUILD_OPTIONS))) $(MAKE) -C Documentation +endif override_dh_auto_install: $(MAKE) install DESTDIR=$(CURDIR)/debian/tmp PREFIX=/usr LIBDIR=/usr/lib/$(DEB_HOST_MULTIARCH) diff -Nru device-tree-compiler-1.4.5/debian/upstream/signing-key.asc device-tree-compiler-1.4.7/debian/upstream/signing-key.asc --- device-tree-compiler-1.4.5/debian/upstream/signing-key.asc 1970-01-01 00:00:00.000000000 +0000 +++ device-tree-compiler-1.4.7/debian/upstream/signing-key.asc 2019-06-06 06:02:32.000000000 +0000 @@ -0,0 +1,89 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBFILNF4BEADnwUE61jAXuQsnqugpL0ANYmEBadAS/hCpJvXKfoa4bgSw3NfQ +G6UmtFt+CzAmERaV9lmZ246dk4BSyCxUnWGUfBs8xxIqhVqkXWvhw2PsRSjMciXf +qKvdvp49AFdKiqzjLF6OeRfBePK5X7XfuSsTu1zT+u9jUAKMesJbW+5BIUdnOqGz +oh2lSwi9ajy0NBr6rUQ+B+v0m4vaSGSO2XR1P16pslBp9F/HnSHILIvFEoebjnBe +BNQXNnaNHMDF14Oj8JN5ewqbii8HzeKHw9Atz9rmH7DKWPEIcwL9fz4/zp+fib1Q +w1tuKbhz5jXTmGmK0+iPPZH9KRbnrUd/T1wcglYGdzYGtQM6Gq/awJoPYGG1SMRH +MBD9GLarAJXhwnfAMHZ/ChdgNiAmLuuThbD7bPo0WnIZm2lEI31PUDJjDufGJBCX +ugDYVn18V1bEjVrz09w02CSbbmM9Wz+JuhIQCTlbkvGk8uWIkNldcOc4C31Y0z6Z +a4yenAR/rDV0ma1rQ0LwPs0qZ9IKQoZS9IrbZ747iRctY5vXbhfYbMHm2D1/zAdL +DWAAglLvJM+welAmOdnmR/Dj0pqGU+MwuwVmKDvHoiwaq+E444VHVp0PRIXM5o4W +iZbDnqlHZLJ4U4tnZPGcOAfhmwe5del22noTzhGriy1mpCbJ388K7aK44QARAQAB +tCpEYXZpZCBHaWJzb24gKGtlcm5lbC5vcmcpIDxkd2dAa2VybmVsLm9yZz6JAjgE +EwECACIFAlIMYyECGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEGw4ysog +2bOShmAP/A0IWyB03D7dtt590bLMDiP6MUV88o4qzc4AIPrvbn7aENu0MJpmLDaR +MaxPW6DN07oqCeKhISrTiV8yYllsawc8B4/mlFxz5m93RBtiV142u9SOlJZBCne/ +H6pQAnZMDDn2jzg/kFoboovnppm/BPLV2bzjaEv/tUT9spy2KhsR7yxr7gkN1KpS +ao43ErWvV/zjWS2Q4ugkI3Km5nEpE2lN3Zcz5ct3FsaEpWISuPvE8py0jNbl26tI +4uA821q7KFvzGEpV3uY+Z8DyOrvsZryp9AJ3Y9NbeqkVCZnR1va6W8HVrtGKGNI2 +Zk0h/hHoZR1fqYphZxrgdy5nOoLg0X9OXqfZvjwEMG8m+Sh7tnHOSZ3kxygcHX8N +YcDS0rMxkS6PAosFtAKuZL5Fpor1elV/xbAurREVFr5u7L/7IUTovdv5Iq6Yof8u +Vkbdf1ZGfdEG1/UFhm29r1KWhVQX2eWSpVfqceq0Gd0s76YeWeRpQu6O7yz6X+ih +xNrpocHuUBq0cQs8j7O1m0ploJXrUlyCgzWXVkvqP6E5RLjA+81DgxvUS5TMjgFk +NkWa/dCnFQDlJEzRf5hlEVHKiQAHyPo4kQh6qfzTywkFSXJakFEbPd29Fvo4LzAu +2gwFApXl9KsSw/C7Vh07jNp5CaGuuGZw1q4jWEnGGZ3R67kLpGcgtCpEYXZpZCBH +aWJzb24gPGRhdmlkQGdpYnNvbi5kcm9wYmVhci5pZC5hdT6JAjsEEwECACUCGwMG +CwkIBwMCBhUIAgkKCwQWAgMBAh4BAheABQJSCzcWAhkBAAoJEGw4ysog2bOSsKQQ +AJO7yEL81fo3wgLJYPYUYDxR6jxVcVeuD6VfojnJwN245iur0j6rnONQEvC2fmn9 +flz/IhCRG6LxX6gTneCm3P+O6Dby6aUHA+DLsKq34PSRNQLZj3TFkCLeLtgUoQbd +0vyiolzR1uzifIbWluvnqxcW9Vr91og/ipt+6Ws1NcwhfdSI0Q/zTSAJIFrq+P7n +KZZnzn64ErmkLZwHuNr3msvdgvpRi5D08+WYJpUfnIBt55lwJEhjGgr4RCegHZL0 +rOISjSmNZJsdcNEb51z5We4367rzrtVla6hVUviSdbya9BpICXcZuEmlfZ2X6uya +j0kBF0GxWUbM9uB/+PtVL3Cnlzf6YWHp+2R1Xosdt0iB3nrfPu5AKwSoNZQS7WRl +aouLNtsum+vJ6fAkSvbHWgU1E0+52o5+uDv5t83iPe1bOQeHQTvg70H6zWiLcE47 +j4n7L1tSyQoj5oh6ipLfgP+yUfSat/uNsA7bgDwd+7+4jRbvhATAgjJZ/5aH/ZQ0 +ycnnG99NCw0pzjGX0iDG+rUeGGmZWW7iidFDN7fyoJSguAZUdMf1+67qVAwt9t6b +xHDXaXog+4UYkhhLtqRidb2ESY35Gv1nBE630cPi2FDdmfvUISJ1/OZKxBsVQhOM +GylkN+IJjOKlloURT+q4AqKpN8t2C3LKQqWViM4b3BaAtCtEYXZpZCBHaWJzb24g +KFJlZCBIYXQpIDxkZ2lic29uQHJlZGhhdC5jb20+iQI4BBMBAgAiBQJSCzTSAhsD +BgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRBsOMrKINmzkk5iEACrv9XYF1Qi +EqiyGRZAl65f9XpCDbNhlpyozwvlEXbjcgA1mJWlt6K5ehvVT2m2jsq5k50y1SA0 +F+xrF0gzY1HC/2IRgzEyQKc0HaeG9MNoPQtuyzccu7zgYonLt3lmiKN9VtrmNhYV +5L8f0BDdCdiX7s/XMgNq1qhXpj7Bh2wvC+Bf7mcosABxPRdWyRvoxaXHB5vEnGMH +EzsOdi1SqZ3Po3t7nadFrlnuOoON3tVVQLZAyw/WUqRRWiVy4UJfjeWim2xUg7K3 +Yu+L+vim8V2/vB+ykyi5586uu1LGcywIqqwGpb1E32+jdKsx1cWmjqgxpJ/FWH9F +5QZZGTKrG6Dsd9HFGKVh1k/V9Ps1NLAxfmSgbZrH3Aag+oQmhel2AropEjjheILM +u204oKjW0LsBIb4XF+52jV5Jl+blgcGf35m0VNCAA8hPHOuQdex92Ih+yLSyHiss +21f4XGtwmqru7b9P8AIcUaiDZH6BBB4IQpFG73ZOAMnr1Q3NZdIrEGM9u9fngxlf +uexUh6Mqz3T7h2AjqTdMteiKt+BqkMByaHozemPpOO/iEEj8yfQxT7UyNGwcPPd1 +Vnr2rRvautVlckldjJO0swS7JYb4+j4DVtc4WEOMv24WtlVkzE/1RTc6MjaLKyNf +HV9dLzr3hFzK3FsCR4VRbCkUgblxOtd21LQuRGF2aWQgR2lic29uIChvemxhYnMu +b3JnKSA8ZGdpYnNvbkBvemxhYnMub3JnPokCOAQTAQIAIgUCUgs3SAIbAwYLCQgH +AwIGFQgCCQoLBBYCAwECHgECF4AACgkQbDjKyiDZs5Ln/hAAjfeEftU91lT0F0ms +pz6lBYRLg4Vo005WRdDl3/twf0oYx1O4e8G2dot0WVL39tjZuNcLCJ1/iGMeoyc3 +ykFVwFR8EZMKpBcYgJm3x74JkJC6SWq9bhmLZ0e7O2RcOCkaGEULgu9+WC0iKJSi +GR/TwX/RuS13JxhNXMoXzKVPYsH4uhOlXtpLXdl6rrFwW1gPPIAw5wYOLCZ7vCc5 +RIXPBllTXvDVynvFWL/PxabsaQpZcTULWRq9TgiSeI0wVUbfKGpLdYEZCngABjZG +tiIxRw23+G18y4eEN0SFaedbfO+ghYPCTg9sytxdn11nA6KX/+ZKbbuVMlLX/Yg5 +6wYvJiuOHa9T5RFuNpFS+9SRZk+KJrSgSdRqHi57/Tyv1k1zV0eom5NHVXgIU2Pr +D99+xuixeMaG9mVhtbdMRsAfBavXxmxUdSOKKbvWgIlvgKJoJrmCc3/PtZRY6lgY +FA8Slk6b0ShmEGJIQfjM9Sy0oWVHJujuxJU7V1qe7jCjPUC22qw8sBBnGYdCFcE1 +G7NJ1A+qyI0WIuaDhutl8gLfsJBBzJDrX20YrJA2hbkmX7Z82270czPWXKrpS0SF +D9yiC+WcXzLrS8U8feEBG9FATqSROUN+gWyUHNTu89OxdImJTorsucTiTeEMlFS5 +OSjwhs3RTVAdUw8Qln1RohqnOq+5Ag0EUgs0XgEQANU0/GOsaKTdptxF93qBaAMx +kWcLkDD4+Bqq0KalqY8uEZ+qpRMFLTWA+eW3Y2U2Q1SfUPpyJzF/3TWX+u14zxih +hPcC9HtaJuitkLmcMJPVx7hhD2e1LxeCYiLmsZWnqbAs89C1AgORo3waoTmcLwJA +pephbrqwhey2PUkztLtVmtL+k78WUpBcrcigaIfY/8PUiJFSvs6z4rDUbxoJq4ae +7qvlhyZE7HhnvsOXAF8DYDK3ao04EhK4OIDBYbEYx45a93m30CDb80a3ebTfCETb +ymKpAhqCuTcLbOHOiRamcUsdv7oQrA73M4ZGQr+ckyxdLPdSiDcKfz6RWZuaBjP5 +rq3zM5Q6v8M8CpwaqUgLUG1ZqJX5OekS2C+dtQ2x4dmLY90FWF+4ZvlwQJpJGSz3 +iVE8AGXNLtAkQ9+p1MN2GeZsRPuFoquM+8SFzR0/VAGTSrb47Oao1fIHmFdbbc+v +8zFUKfJ1kS3qDBk35yXlca9hvnvFI6OqChAhYHhBw6XBw9vLTtljKdgY4t1JOvli +n7ju9gEbSARM2aNhDXThbqkKjJ9n0yP5eGZxzUofDEzUUExOTBl9bPgB1WnnO1d+ +PdGqA6MUPlTvULFWhHlTE+4w+iKHaR2ykZDi4MNsECcmu92iuH8x1XscRrev6QPO +UfPBxF1BdF6ydg9xugthABEBAAGJAh8EGAECAAkFAlILNF4CGwwACgkQbDjKyiDZ +s5LGwg//fdQD0X+bQ5PdTBeXdr4F5UZFuI6scxw6qKHVpinPzO1C0b/1E+Wx1yjc +cAcLrGGfjJSOINBonLBwnCYs809abbtq28LldDcD6WaKyPJlBTrN5fRzPoh9/Fil +oQJVkzaYsFqSm94e+io5f1q38bxFYRj5eG42D4cD0tTk+1kiw75InXwIz5TVxHIs +1Xhsq6HFGo8NkC/0kajQmJZZA/qhvraYil6XL3dCX/qpNIKADN4MlYBDHF8/Z/Fm +9x4mt4SVfiPQwvKIIV+cqTjXoqhbFI7hWdJ19lTyIMHT4lIYScistZmE3ZC4kT0U +KJarh8vDMy1uzeJwvvgsBuHTQNJiM4tgxxKtakxRjEyM24gpCmmy/TYOg3b0FBXA +hvAbJW2tiCcLHfjpr44hP1wy0FVdOdYhFh5Rjpne/KKp6r6pe0MAMpLQqtJRQS2i +UIBJSVn4kCc9LQ83PN9KQWaNIBm8WJHQKz7vlKc6h4jbKDtSDCDnJfCyRMO285np +jWObpaxtOWyxNe3HDN58N6EhId+8QNg8S3RD1Vn9rPbRjILz0jrrjoQVEWcTENCP +snSbRV14L9AlyuYSflplhtEj96Vcoo1HE/fhPv9/Q5YK86zUBEoBEZKbMhXNT2c4 +dZf0QKp8+AUaz/iDh0tmbkeMZLcaqqGBB8gjYIa4+75M/sGv98A= +=Z9nT +-----END PGP PUBLIC KEY BLOCK----- diff -Nru device-tree-compiler-1.4.5/debian/watch device-tree-compiler-1.4.7/debian/watch --- device-tree-compiler-1.4.5/debian/watch 2017-10-06 17:35:17.000000000 +0000 +++ device-tree-compiler-1.4.7/debian/watch 2019-06-06 06:02:32.000000000 +0000 @@ -1,3 +1,5 @@ version=4 -https://git.kernel.org/pub/scm/utils/dtc/dtc.git \ - .*/snapshot/dtc-@ANY_VERSION@@ARCHIVE_EXT@ +opts="pgpmode=mangle, pgpsigurlmangle=s%tar\..z$%tar\.sign%, decompress" \ +https://www.kernel.org/pub/software/utils/dtc/ \ + dtc-@ANY_VERSION@@ARCHIVE_EXT@ \ + debian uupdate diff -Nru device-tree-compiler-1.4.5/Documentation/manual.txt device-tree-compiler-1.4.7/Documentation/manual.txt --- device-tree-compiler-1.4.5/Documentation/manual.txt 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/Documentation/manual.txt 2018-07-23 03:00:50.000000000 +0000 @@ -693,3 +693,67 @@ -i, --input Input base DT blob -o, --output Output DT blob -v, --verbose Verbose message output + +4 ) fdtget -- Read properties from device tree + +This command can be used to obtain individual values from the device tree in a +nicely formatted way. You can specify multiple nodes to display (when using -p) +or multiple node/property pairs (when not using -p). For the latter, each +property is displayed on its own line, with a space between each cell within +the property. + +The syntax of the fdtget command is: + + fdtget
[ ]... + fdtget -p
[ ]... + +where options are: + + s=string, i=int, u=unsigned, x=hex + Optional modifier prefix: + hh or b=byte, h=2 byte, l=4 byte (default) + + Options: -[t:pld:hV] + -t, --type Type of data + -p, --properties List properties for each node + -l, --list List subnodes for each node + -d, --default Default value to display when the property is missing + -h, --help Print this help and exit + -V, --version Print version and exit + +If -t is not provided, fdtget will try to figure out the type, trying to detect +strings, string lists and the size of each value in the property. This is +similar to how fdtdump works, and uses the same heuristics. + + +5 ) fdtput - Write properties to a device tree + +The syntax of the fdtput command is: + + fdtput
[...] + fdtput -c
[...] + fdtput -r
[...] + fdtput -d
[...] + +Options are: + + s=string, i=int, u=unsigned, x=hex + Optional modifier prefix: + hh or b=byte, h=2 byte, l=4 byte (default) + + -c, --create Create nodes if they don't already exist + -r, --remove Delete nodes (and any subnodes) if they already exist + -d, --delete Delete properties if they already exist + -p, --auto-path Automatically create nodes as needed for the node path + -t, --type Type of data + -v, --verbose Display each value decoded from command line + -h, --help Print this help and exit + -V, --version Print version and exit + +The option determines which usage is selected and therefore the operation that +is performed. The first usage adds or updates properties; the rest are used to +create/delete nodes and delete properties. + +For the first usage, the command line arguments are joined together into a +single value which is written to the property. The -t option is required so +that fdtput knows how to decode its arguments. diff -Nru device-tree-compiler-1.4.5/dtc.c device-tree-compiler-1.4.7/dtc.c --- device-tree-compiler-1.4.5/dtc.c 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/dtc.c 2018-07-23 03:00:50.000000000 +0000 @@ -59,8 +59,6 @@ } /* Usage related data. */ -#define FDT_VERSION(version) _FDT_VERSION(version) -#define _FDT_VERSION(version) #version static const char usage_synopsis[] = "dtc [options] "; static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@Ahv"; static struct option const usage_long_opts[] = { @@ -98,7 +96,7 @@ "\t\tdts - device tree source text\n" "\t\tdtb - device tree blob\n" "\t\tasm - assembler source", - "\n\tBlob version to produce, defaults to "FDT_VERSION(DEFAULT_FDT_VERSION)" (for dtb and asm output)", + "\n\tBlob version to produce, defaults to "stringify(DEFAULT_FDT_VERSION)" (for dtb and asm output)", "\n\tOutput dependency file", "\n\tMake space for reserve map entries (for dtb and asm output)", "\n\tMake the blob at least long (extra space)", @@ -319,13 +317,14 @@ dti->boot_cpuid_phys = cmdline_boot_cpuid; fill_fullpaths(dti->dt, ""); - process_checks(force, dti); /* on a plugin, generate by default */ if (dti->dtsflags & DTSF_PLUGIN) { generate_fixups = 1; } + process_checks(force, dti); + if (auto_label_aliases) generate_label_tree(dti, "aliases", false); diff -Nru device-tree-compiler-1.4.5/dtc.h device-tree-compiler-1.4.7/dtc.h --- device-tree-compiler-1.4.5/dtc.h 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/dtc.h 2018-07-23 03:00:50.000000000 +0000 @@ -1,5 +1,5 @@ -#ifndef _DTC_H -#define _DTC_H +#ifndef DTC_H +#define DTC_H /* * (C) Copyright David Gibson , IBM Corporation. 2005. @@ -67,16 +67,25 @@ #define streq(a, b) (strcmp((a), (b)) == 0) -#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0) +#define strstarts(s, prefix) (strncmp((s), (prefix), strlen(prefix)) == 0) +#define strprefixeq(a, n, b) (strlen(b) == (n) && (memcmp(a, b, n) == 0)) #define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) /* Data blobs */ enum markertype { + TYPE_NONE, REF_PHANDLE, REF_PATH, LABEL, + TYPE_UINT8, + TYPE_UINT16, + TYPE_UINT32, + TYPE_UINT64, + TYPE_BLOB, + TYPE_STRING, }; +extern const char *markername(enum markertype markertype); struct marker { enum markertype type; @@ -167,6 +176,8 @@ struct label *labels; const struct bus_type *bus; + + bool omit_if_unused, is_referenced; }; #define for_each_label_withdel(l0, l) \ @@ -201,8 +212,11 @@ struct node *build_node(struct property *proplist, struct node *children); struct node *build_node_delete(void); struct node *name_node(struct node *node, char *name); +struct node *omit_node_if_unused(struct node *node); +struct node *reference_node(struct node *node); struct node *chain_node(struct node *first, struct node *list); struct node *merge_nodes(struct node *old_node, struct node *new_node); +struct node *add_orphan_node(struct node *old_node, struct node *new_node, char *ref); void add_property(struct node *node, struct property *prop); void delete_property_by_name(struct node *node, char *name); @@ -288,4 +302,4 @@ struct dt_info *dt_from_fs(const char *dirname); -#endif /* _DTC_H */ +#endif /* DTC_H */ diff -Nru device-tree-compiler-1.4.5/dtc-lexer.l device-tree-compiler-1.4.7/dtc-lexer.l --- device-tree-compiler-1.4.5/dtc-lexer.l 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/dtc-lexer.l 2018-07-23 03:00:50.000000000 +0000 @@ -153,6 +153,13 @@ return DT_DEL_NODE; } +<*>"/omit-if-no-ref/" { + DPRINT("Keyword: /omit-if-no-ref/\n"); + DPRINT("\n"); + BEGIN(PROPNODENAME); + return DT_OMIT_NO_REF; + } + <*>{LABEL}: { DPRINT("Label: %s\n", yytext); yylval.labelref = xstrdup(yytext); diff -Nru device-tree-compiler-1.4.5/dtc-parser.y device-tree-compiler-1.4.7/dtc-parser.y --- device-tree-compiler-1.4.5/dtc-parser.y 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/dtc-parser.y 2018-07-23 03:00:50.000000000 +0000 @@ -63,6 +63,7 @@ %token DT_BITS %token DT_DEL_PROP %token DT_DEL_NODE +%token DT_OMIT_NO_REF %token DT_PROPNODENAME %token DT_LITERAL %token DT_CHAR_LITERAL @@ -166,7 +167,17 @@ { $$ = merge_nodes($1, $3); } - + | DT_REF nodedef + { + /* + * We rely on the rule being always: + * versioninfo plugindecl memreserves devicetree + * so $-1 is what we want (plugindecl) + */ + if (!($-1 & DTSF_PLUGIN)) + ERROR(&@2, "Label or path %s not found", $1); + $$ = add_orphan_node(name_node(build_node(NULL, NULL), ""), $2, $1); + } | devicetree DT_LABEL DT_REF nodedef { struct node *target = get_node_by_ref($1, $3); @@ -180,12 +191,21 @@ } | devicetree DT_REF nodedef { - struct node *target = get_node_by_ref($1, $2); + /* + * We rely on the rule being always: + * versioninfo plugindecl memreserves devicetree + * so $-1 is what we want (plugindecl) + */ + if ($-1 & DTSF_PLUGIN) { + add_orphan_node($1, $3, $2); + } else { + struct node *target = get_node_by_ref($1, $2); - if (target) - merge_nodes(target, $3); - else - ERROR(&@2, "Label or path %s not found", $2); + if (target) + merge_nodes(target, $3); + else + ERROR(&@2, "Label or path %s not found", $2); + } $$ = $1; } | devicetree DT_DEL_NODE DT_REF ';' @@ -200,6 +220,18 @@ $$ = $1; } + | devicetree DT_OMIT_NO_REF DT_REF ';' + { + struct node *target = get_node_by_ref($1, $3); + + if (target) + omit_node_if_unused(target); + else + ERROR(&@3, "Label or path %s not found", $3); + + + $$ = $1; + } ; nodedef: @@ -308,22 +340,27 @@ DT_BITS DT_LITERAL '<' { unsigned long long bits; + enum markertype type = TYPE_UINT32; bits = $2; - if ((bits != 8) && (bits != 16) && - (bits != 32) && (bits != 64)) { + switch (bits) { + case 8: type = TYPE_UINT8; break; + case 16: type = TYPE_UINT16; break; + case 32: type = TYPE_UINT32; break; + case 64: type = TYPE_UINT64; break; + default: ERROR(&@2, "Array elements must be" " 8, 16, 32 or 64-bits"); bits = 32; } - $$.data = empty_data; + $$.data = data_add_marker(empty_data, type, NULL); $$.bits = bits; } | '<' { - $$.data = empty_data; + $$.data = data_add_marker(empty_data, TYPE_UINT32, NULL); $$.bits = 32; } | arrayprefix integer_prim @@ -467,7 +504,7 @@ bytestring: /* empty */ { - $$ = empty_data; + $$ = data_add_marker(empty_data, TYPE_UINT8, NULL); } | bytestring DT_BYTE { @@ -504,6 +541,10 @@ { $$ = name_node(build_node_delete(), $2); } + | DT_OMIT_NO_REF subnode + { + $$ = omit_node_if_unused($2); + } | DT_LABEL subnode { add_label(&$2->labels, $1); diff -Nru device-tree-compiler-1.4.5/fdtdump.c device-tree-compiler-1.4.7/fdtdump.c --- device-tree-compiler-1.4.5/fdtdump.c 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/fdtdump.c 2018-07-23 03:00:50.000000000 +0000 @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -65,23 +66,24 @@ 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", + printf("// magic:\t\t0x%"PRIx32"\n", fdt32_to_cpu(bph->magic)); + printf("// totalsize:\t\t0x%"PRIx32" (%"PRIu32")\n", + totalsize, totalsize); + printf("// off_dt_struct:\t0x%"PRIx32"\n", off_dt); + printf("// off_dt_strings:\t0x%"PRIx32"\n", off_str); + printf("// off_mem_rsvmap:\t0x%"PRIx32"\n", off_mem_rsvmap); + printf("// version:\t\t%"PRIu32"\n", version); + printf("// last_comp_version:\t%"PRIu32"\n", fdt32_to_cpu(bph->last_comp_version)); if (version >= 2) - printf("// boot_cpuid_phys:\t0x%x\n", + printf("// boot_cpuid_phys:\t0x%"PRIx32"\n", fdt32_to_cpu(bph->boot_cpuid_phys)); if (version >= 3) - printf("// size_dt_strings:\t0x%x\n", + printf("// size_dt_strings:\t0x%"PRIx32"\n", fdt32_to_cpu(bph->size_dt_strings)); if (version >= 17) - printf("// size_dt_struct:\t0x%x\n", + printf("// size_dt_struct:\t0x%"PRIx32"\n", fdt32_to_cpu(bph->size_dt_struct)); printf("\n"); @@ -91,14 +93,14 @@ if (addr == 0 && size == 0) break; - printf("/memreserve/ %#llx %#llx;\n", - (unsigned long long)addr, (unsigned long long)size); + printf("/memreserve/ %#"PRIx64" %#"PRIx64";\n", + addr, size); } p = p_struct; while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) { - dumpf("%04zx: tag: 0x%08x (%s)\n", + dumpf("%04zx: tag: 0x%08"PRIx32" (%s)\n", (uintptr_t)p - blob_off - 4, tag, tagname(tag)); if (tag == FDT_BEGIN_NODE) { @@ -127,7 +129,7 @@ } if (tag != FDT_PROP) { - fprintf(stderr, "%*s ** Unknown tag 0x%08x\n", depth * shift, "", tag); + fprintf(stderr, "%*s ** Unknown tag 0x%08"PRIx32"\n", depth * shift, "", tag); break; } sz = fdt32_to_cpu(GET_CELL(p)); @@ -181,7 +183,7 @@ char *buf; bool debug = false; bool scan = false; - off_t len; + size_t len; fprintf(stderr, "\n" "**** fdtdump is a low-level debugging tool, not meant for general use.\n" @@ -204,7 +206,7 @@ usage("missing input filename"); file = argv[optind]; - buf = utilfdt_read_len(file, &len); + buf = utilfdt_read(file, &len); if (!buf) die("could not read: %s\n", file); diff -Nru device-tree-compiler-1.4.5/fdtget.c device-tree-compiler-1.4.7/fdtget.c --- device-tree-compiler-1.4.5/fdtget.c 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/fdtget.c 2018-07-23 03:00:50.000000000 +0000 @@ -76,7 +76,7 @@ for (i = 0; i < len; i += size, p += size) { if (i) printf(" "); - value = size == 4 ? fdt32_to_cpu(*(const fdt32_t *)p) : + value = size == 4 ? fdt32_ld((const fdt32_t *)p) : size == 2 ? (*p << 8) | p[1] : *p; printf(fmt, value); } @@ -140,7 +140,6 @@ */ static int list_properties(const void *blob, int node) { - const struct fdt_property *data; const char *name; int prop; @@ -149,8 +148,7 @@ /* 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)); + fdt_getprop_by_offset(blob, prop, &name, NULL); if (name) puts(name); prop = fdt_next_property_offset(blob, prop); @@ -273,7 +271,7 @@ const char *prop; int i, node; - blob = utilfdt_read(filename); + blob = utilfdt_read(filename, NULL); if (!blob) return -1; diff -Nru device-tree-compiler-1.4.5/fdtoverlay.c device-tree-compiler-1.4.7/fdtoverlay.c --- device-tree-compiler-1.4.5/fdtoverlay.c 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/fdtoverlay.c 2018-07-23 03:00:50.000000000 +0000 @@ -26,7 +26,6 @@ #include #include #include -#include #include #include @@ -61,10 +60,10 @@ { char *blob = NULL; char **ovblob = NULL; - off_t blob_len, ov_len, total_len; + size_t blob_len, ov_len, total_len; int i, ret = -1; - blob = utilfdt_read_len(input_filename, &blob_len); + blob = utilfdt_read(input_filename, &blob_len); if (!blob) { fprintf(stderr, "\nFailed to read base blob %s\n", input_filename); @@ -79,13 +78,13 @@ ret = 0; /* allocate blob pointer array */ - ovblob = alloca(sizeof(*ovblob) * argc); + ovblob = malloc(sizeof(*ovblob) * argc); memset(ovblob, 0, sizeof(*ovblob) * argc); /* read and keep track of the overlay blobs */ total_len = 0; for (i = 0; i < argc; i++) { - ovblob[i] = utilfdt_read_len(argv[i], &ov_len); + ovblob[i] = utilfdt_read(argv[i], &ov_len); if (!ovblob[i]) { fprintf(stderr, "\nFailed to read overlay %s\n", argv[i]); @@ -121,6 +120,7 @@ if (ovblob[i]) free(ovblob[i]); } + free(ovblob); } free(blob); diff -Nru device-tree-compiler-1.4.5/fdtput.c device-tree-compiler-1.4.7/fdtput.c --- device-tree-compiler-1.4.5/fdtput.c 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/fdtput.c 2018-07-23 03:00:50.000000000 +0000 @@ -130,7 +130,7 @@ #define ALIGN(x) (((x) + (FDT_TAGSIZE) - 1) & ~((FDT_TAGSIZE) - 1)) -static char *_realloc_fdt(char *fdt, int delta) +static char *realloc_fdt(char *fdt, int delta) { int new_sz = fdt_totalsize(fdt) + delta; fdt = xrealloc(fdt, new_sz); @@ -144,7 +144,7 @@ /* FDT_BEGIN_NODE, node name in off_struct and FDT_END_NODE */ delta = sizeof(struct fdt_node_header) + ALIGN(strlen(name) + 1) + FDT_TAGSIZE; - return _realloc_fdt(fdt, delta); + return realloc_fdt(fdt, delta); } static char *realloc_property(char *fdt, int nodeoffset, @@ -161,7 +161,7 @@ /* actual value in off_struct */ delta += ALIGN(newlen) - ALIGN(oldlen); - return _realloc_fdt(fdt, delta); + return realloc_fdt(fdt, delta); } static int store_key_value(char **blob, const char *node_name, @@ -333,7 +333,7 @@ char *node; int len, ret = 0; - blob = utilfdt_read(filename); + blob = utilfdt_read(filename, NULL); if (!blob) return -1; diff -Nru device-tree-compiler-1.4.5/flattree.c device-tree-compiler-1.4.7/flattree.c --- device-tree-compiler-1.4.5/flattree.c 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/flattree.c 2018-07-23 03:00:50.000000000 +0000 @@ -393,7 +393,7 @@ padlen = 0; if (quiet < 1) fprintf(stderr, - "Warning: blob size %d >= minimum size %d\n", + "Warning: blob size %"PRIu32" >= minimum size %d\n", fdt32_to_cpu(fdt.totalsize), minsize); } } @@ -731,7 +731,7 @@ plen = strlen(ppath); - if (!strneq(ppath, cpath, plen)) + if (!strstarts(cpath, ppath)) die("Path \"%s\" is not valid as a child of \"%s\"\n", cpath, ppath); diff -Nru device-tree-compiler-1.4.5/libfdt/fdt_addresses.c device-tree-compiler-1.4.7/libfdt/fdt_addresses.c --- device-tree-compiler-1.4.5/libfdt/fdt_addresses.c 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/libfdt/fdt_addresses.c 2018-07-23 03:00:50.000000000 +0000 @@ -1,6 +1,7 @@ /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2014 David Gibson + * Copyright (C) 2018 embedded brains GmbH * * libfdt is dual licensed: you can use it either under the terms of * the GPL, or the BSD license, at your option. @@ -55,42 +56,32 @@ #include "libfdt_internal.h" -int fdt_address_cells(const void *fdt, int nodeoffset) +static int fdt_cells(const void *fdt, int nodeoffset, const char *name) { - const fdt32_t *ac; + const fdt32_t *c; int val; int len; - ac = fdt_getprop(fdt, nodeoffset, "#address-cells", &len); - if (!ac) + c = fdt_getprop(fdt, nodeoffset, name, &len); + if (!c) return 2; - if (len != sizeof(*ac)) + if (len != sizeof(*c)) return -FDT_ERR_BADNCELLS; - val = fdt32_to_cpu(*ac); + val = fdt32_to_cpu(*c); if ((val <= 0) || (val > FDT_MAX_NCELLS)) return -FDT_ERR_BADNCELLS; return val; } -int fdt_size_cells(const void *fdt, int nodeoffset) +int fdt_address_cells(const void *fdt, int nodeoffset) { - const fdt32_t *sc; - int val; - int len; - - sc = fdt_getprop(fdt, nodeoffset, "#size-cells", &len); - if (!sc) - return 2; - - if (len != sizeof(*sc)) - return -FDT_ERR_BADNCELLS; - - val = fdt32_to_cpu(*sc); - if ((val < 0) || (val > FDT_MAX_NCELLS)) - return -FDT_ERR_BADNCELLS; + return fdt_cells(fdt, nodeoffset, "#address-cells"); +} - return val; +int fdt_size_cells(const void *fdt, int nodeoffset) +{ + return fdt_cells(fdt, nodeoffset, "#size-cells"); } diff -Nru device-tree-compiler-1.4.5/libfdt/fdt.c device-tree-compiler-1.4.7/libfdt/fdt.c --- device-tree-compiler-1.4.5/libfdt/fdt.c 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/libfdt/fdt.c 2018-07-23 03:00:50.000000000 +0000 @@ -55,7 +55,12 @@ #include "libfdt_internal.h" -int fdt_check_header(const void *fdt) +/* + * Minimal sanity check for a read-only tree. fdt_ro_probe_() checks + * that the given buffer contains what appears to be a flattened + * device tree with sane information in its header. + */ +int fdt_ro_probe_(const void *fdt) { if (fdt_magic(fdt) == FDT_MAGIC) { /* Complete tree */ @@ -74,6 +79,78 @@ return 0; } +static int check_off_(uint32_t hdrsize, uint32_t totalsize, uint32_t off) +{ + return (off >= hdrsize) && (off <= totalsize); +} + +static int check_block_(uint32_t hdrsize, uint32_t totalsize, + uint32_t base, uint32_t size) +{ + if (!check_off_(hdrsize, totalsize, base)) + return 0; /* block start out of bounds */ + if ((base + size) < base) + return 0; /* overflow */ + if (!check_off_(hdrsize, totalsize, base + size)) + return 0; /* block end out of bounds */ + return 1; +} + +size_t fdt_header_size_(uint32_t version) +{ + if (version <= 1) + return FDT_V1_SIZE; + else if (version <= 2) + return FDT_V2_SIZE; + else if (version <= 3) + return FDT_V3_SIZE; + else if (version <= 16) + return FDT_V16_SIZE; + else + return FDT_V17_SIZE; +} + +int fdt_check_header(const void *fdt) +{ + size_t hdrsize; + + if (fdt_magic(fdt) != FDT_MAGIC) + return -FDT_ERR_BADMAGIC; + hdrsize = fdt_header_size(fdt); + if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) + || (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)) + return -FDT_ERR_BADVERSION; + if (fdt_version(fdt) < fdt_last_comp_version(fdt)) + return -FDT_ERR_BADVERSION; + + if ((fdt_totalsize(fdt) < hdrsize) + || (fdt_totalsize(fdt) > INT_MAX)) + return -FDT_ERR_TRUNCATED; + + /* Bounds check memrsv block */ + if (!check_off_(hdrsize, fdt_totalsize(fdt), fdt_off_mem_rsvmap(fdt))) + return -FDT_ERR_TRUNCATED; + + /* Bounds check structure block */ + if (fdt_version(fdt) < 17) { + if (!check_off_(hdrsize, fdt_totalsize(fdt), + fdt_off_dt_struct(fdt))) + return -FDT_ERR_TRUNCATED; + } else { + if (!check_block_(hdrsize, fdt_totalsize(fdt), + fdt_off_dt_struct(fdt), + fdt_size_dt_struct(fdt))) + return -FDT_ERR_TRUNCATED; + } + + /* Bounds check strings block */ + if (!check_block_(hdrsize, fdt_totalsize(fdt), + fdt_off_dt_strings(fdt), fdt_size_dt_strings(fdt))) + return -FDT_ERR_TRUNCATED; + + return 0; +} + const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) { unsigned absoffset = offset + fdt_off_dt_struct(fdt); @@ -88,7 +165,7 @@ || ((offset + len) > fdt_size_dt_struct(fdt))) return NULL; - return _fdt_offset_ptr(fdt, offset); + return fdt_offset_ptr_(fdt, offset); } uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) @@ -123,6 +200,9 @@ /* skip-name offset, length and value */ offset += sizeof(struct fdt_property) - FDT_TAGSIZE + fdt32_to_cpu(*lenp); + if (fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 && + ((offset - fdt32_to_cpu(*lenp)) % 8) != 0) + offset += 4; break; case FDT_END: @@ -141,7 +221,7 @@ return tag; } -int _fdt_check_node_offset(const void *fdt, int offset) +int fdt_check_node_offset_(const void *fdt, int offset) { if ((offset < 0) || (offset % FDT_TAGSIZE) || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE)) @@ -150,7 +230,7 @@ return offset; } -int _fdt_check_prop_offset(const void *fdt, int offset) +int fdt_check_prop_offset_(const void *fdt, int offset) { if ((offset < 0) || (offset % FDT_TAGSIZE) || (fdt_next_tag(fdt, offset, &offset) != FDT_PROP)) @@ -165,7 +245,7 @@ uint32_t tag; if (offset >= 0) - if ((nextoffset = _fdt_check_node_offset(fdt, offset)) < 0) + if ((nextoffset = fdt_check_node_offset_(fdt, offset)) < 0) return nextoffset; do { @@ -227,7 +307,7 @@ return offset; } -const char *_fdt_find_string(const char *strtab, int tabsize, const char *s) +const char *fdt_find_string_(const char *strtab, int tabsize, const char *s) { int len = strlen(s) + 1; const char *last = strtab + tabsize - len; @@ -241,7 +321,7 @@ int fdt_move(const void *fdt, void *buf, int bufsize) { - FDT_CHECK_HEADER(fdt); + FDT_RO_PROBE(fdt); if (fdt_totalsize(fdt) > bufsize) return -FDT_ERR_NOSPACE; diff -Nru device-tree-compiler-1.4.5/libfdt/fdt.h device-tree-compiler-1.4.7/libfdt/fdt.h --- device-tree-compiler-1.4.5/libfdt/fdt.h 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/libfdt/fdt.h 2018-07-23 03:00:50.000000000 +0000 @@ -1,5 +1,5 @@ -#ifndef _FDT_H -#define _FDT_H +#ifndef FDT_H +#define FDT_H /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. @@ -108,4 +108,4 @@ #define FDT_V16_SIZE FDT_V3_SIZE #define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(fdt32_t)) -#endif /* _FDT_H */ +#endif /* FDT_H */ diff -Nru device-tree-compiler-1.4.5/libfdt/fdt_overlay.c device-tree-compiler-1.4.7/libfdt/fdt_overlay.c --- device-tree-compiler-1.4.5/libfdt/fdt_overlay.c 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/libfdt/fdt_overlay.c 2018-07-23 03:00:50.000000000 +0000 @@ -1,3 +1,54 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2016 Free Electrons + * Copyright (C) 2016 NextThing Co. + * + * 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 @@ -646,7 +697,7 @@ int len = 0, namelen; const char *name; - FDT_CHECK_HEADER(fdt); + FDT_RO_PROBE(fdt); for (;;) { name = fdt_get_name(fdt, nodeoffset, &namelen); @@ -815,8 +866,8 @@ uint32_t delta = fdt_get_max_phandle(fdt); int ret; - FDT_CHECK_HEADER(fdt); - FDT_CHECK_HEADER(fdto); + FDT_RO_PROBE(fdt); + FDT_RO_PROBE(fdto); ret = overlay_adjust_local_phandles(fdto, delta); if (ret) diff -Nru device-tree-compiler-1.4.5/libfdt/fdt_ro.c device-tree-compiler-1.4.7/libfdt/fdt_ro.c --- device-tree-compiler-1.4.5/libfdt/fdt_ro.c 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/libfdt/fdt_ro.c 2018-07-23 03:00:50.000000000 +0000 @@ -55,12 +55,13 @@ #include "libfdt_internal.h" -static int _fdt_nodename_eq(const void *fdt, int offset, +static int fdt_nodename_eq_(const void *fdt, int offset, const char *s, int len) { - const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1); + int olen; + const char *p = fdt_get_name(fdt, offset, &olen); - if (!p) + if (!p || olen < len) /* short match */ return 0; @@ -75,17 +76,72 @@ return 0; } +const char *fdt_get_string(const void *fdt, int stroffset, int *lenp) +{ + uint32_t absoffset = stroffset + fdt_off_dt_strings(fdt); + size_t len; + int err; + const char *s, *n; + + err = fdt_ro_probe_(fdt); + if (err != 0) + goto fail; + + err = -FDT_ERR_BADOFFSET; + if (absoffset >= fdt_totalsize(fdt)) + goto fail; + len = fdt_totalsize(fdt) - absoffset; + + if (fdt_magic(fdt) == FDT_MAGIC) { + if (stroffset < 0) + goto fail; + if (fdt_version(fdt) >= 17) { + if (stroffset >= fdt_size_dt_strings(fdt)) + goto fail; + if ((fdt_size_dt_strings(fdt) - stroffset) < len) + len = fdt_size_dt_strings(fdt) - stroffset; + } + } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { + if ((stroffset >= 0) + || (stroffset < -fdt_size_dt_strings(fdt))) + goto fail; + if ((-stroffset) < len) + len = -stroffset; + } else { + err = -FDT_ERR_INTERNAL; + goto fail; + } + + s = (const char *)fdt + absoffset; + n = memchr(s, '\0', len); + if (!n) { + /* missing terminating NULL */ + err = -FDT_ERR_TRUNCATED; + goto fail; + } + + if (lenp) + *lenp = n - s; + return s; + +fail: + if (lenp) + *lenp = err; + return NULL; +} + const char *fdt_string(const void *fdt, int stroffset) { - return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; + return fdt_get_string(fdt, stroffset, NULL); } -static int _fdt_string_eq(const void *fdt, int stroffset, +static int fdt_string_eq_(const void *fdt, int stroffset, const char *s, int len) { - const char *p = fdt_string(fdt, stroffset); + int slen; + const char *p = fdt_get_string(fdt, stroffset, &slen); - return (strlen(p) == len) && (memcmp(p, s, len) == 0); + return p && (slen == len) && (memcmp(p, s, len) == 0); } uint32_t fdt_get_max_phandle(const void *fdt) @@ -114,24 +170,45 @@ return 0; } +static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n) +{ + int offset = n * sizeof(struct fdt_reserve_entry); + int absoffset = fdt_off_mem_rsvmap(fdt) + offset; + + if (absoffset < fdt_off_mem_rsvmap(fdt)) + return NULL; + if (absoffset > fdt_totalsize(fdt) - sizeof(struct fdt_reserve_entry)) + return NULL; + return fdt_mem_rsv_(fdt, n); +} + int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) { - FDT_CHECK_HEADER(fdt); - *address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address); - *size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size); + const struct fdt_reserve_entry *re; + + FDT_RO_PROBE(fdt); + re = fdt_mem_rsv(fdt, n); + if (!re) + return -FDT_ERR_BADOFFSET; + + *address = fdt64_ld(&re->address); + *size = fdt64_ld(&re->size); return 0; } int fdt_num_mem_rsv(const void *fdt) { - int i = 0; + int i; + const struct fdt_reserve_entry *re; - while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0) - i++; - return i; + for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) { + if (fdt64_ld(&re->size) == 0) + return i; + } + return -FDT_ERR_TRUNCATED; } -static int _nextprop(const void *fdt, int offset) +static int nextprop_(const void *fdt, int offset) { uint32_t tag; int nextoffset; @@ -160,13 +237,13 @@ { int depth; - FDT_CHECK_HEADER(fdt); + FDT_RO_PROBE(fdt); for (depth = 0; (offset >= 0) && (depth >= 0); offset = fdt_next_node(fdt, offset, &depth)) if ((depth == 1) - && _fdt_nodename_eq(fdt, offset, name, namelen)) + && fdt_nodename_eq_(fdt, offset, name, namelen)) return offset; if (depth < 0) @@ -186,7 +263,7 @@ const char *p = path; int offset = 0; - FDT_CHECK_HEADER(fdt); + FDT_RO_PROBE(fdt); /* see if we have an alias */ if (*path != '/') { @@ -232,17 +309,35 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) { - const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset); + const struct fdt_node_header *nh = fdt_offset_ptr_(fdt, nodeoffset); + const char *nameptr; int err; - if (((err = fdt_check_header(fdt)) != 0) - || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0)) + if (((err = fdt_ro_probe_(fdt)) != 0) + || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0)) goto fail; + nameptr = nh->name; + + if (fdt_version(fdt) < 0x10) { + /* + * For old FDT versions, match the naming conventions of V16: + * give only the leaf name (after all /). The actual tree + * contents are loosely checked. + */ + const char *leaf; + leaf = strrchr(nameptr, '/'); + if (leaf == NULL) { + err = -FDT_ERR_BADSTRUCTURE; + goto fail; + } + nameptr = leaf+1; + } + if (len) - *len = strlen(nh->name); + *len = strlen(nameptr); - return nh->name; + return nameptr; fail: if (len) @@ -254,58 +349,79 @@ { int offset; - if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0) + if ((offset = fdt_check_node_offset_(fdt, nodeoffset)) < 0) return offset; - return _nextprop(fdt, offset); + return nextprop_(fdt, offset); } int fdt_next_property_offset(const void *fdt, int offset) { - if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0) + if ((offset = fdt_check_prop_offset_(fdt, offset)) < 0) return offset; - return _nextprop(fdt, offset); + return nextprop_(fdt, offset); } -const struct fdt_property *fdt_get_property_by_offset(const void *fdt, - int offset, - int *lenp) +static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt, + int offset, + int *lenp) { int err; const struct fdt_property *prop; - if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) { + if ((err = fdt_check_prop_offset_(fdt, offset)) < 0) { if (lenp) *lenp = err; return NULL; } - prop = _fdt_offset_ptr(fdt, offset); + prop = fdt_offset_ptr_(fdt, offset); if (lenp) - *lenp = fdt32_to_cpu(prop->len); + *lenp = fdt32_ld(&prop->len); return prop; } -const struct fdt_property *fdt_get_property_namelen(const void *fdt, - int offset, - const char *name, - int namelen, int *lenp) +const struct fdt_property *fdt_get_property_by_offset(const void *fdt, + int offset, + int *lenp) +{ + /* Prior to version 16, properties may need realignment + * and this API does not work. fdt_getprop_*() will, however. */ + + if (fdt_version(fdt) < 0x10) { + if (lenp) + *lenp = -FDT_ERR_BADVERSION; + return NULL; + } + + return fdt_get_property_by_offset_(fdt, offset, lenp); +} + +static const struct fdt_property *fdt_get_property_namelen_(const void *fdt, + int offset, + const char *name, + int namelen, + int *lenp, + int *poffset) { for (offset = fdt_first_property_offset(fdt, offset); (offset >= 0); (offset = fdt_next_property_offset(fdt, offset))) { const struct fdt_property *prop; - if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) { + if (!(prop = fdt_get_property_by_offset_(fdt, offset, lenp))) { offset = -FDT_ERR_INTERNAL; break; } - if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff), - name, namelen)) + if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff), + name, namelen)) { + if (poffset) + *poffset = offset; return prop; + } } if (lenp) @@ -313,6 +429,25 @@ return NULL; } + +const struct fdt_property *fdt_get_property_namelen(const void *fdt, + int offset, + const char *name, + int namelen, int *lenp) +{ + /* Prior to version 16, properties may need realignment + * and this API does not work. fdt_getprop_*() will, however. */ + if (fdt_version(fdt) < 0x10) { + if (lenp) + *lenp = -FDT_ERR_BADVERSION; + return NULL; + } + + return fdt_get_property_namelen_(fdt, offset, name, namelen, lenp, + NULL); +} + + const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset, const char *name, int *lenp) @@ -324,12 +459,18 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, const char *name, int namelen, int *lenp) { + int poffset; const struct fdt_property *prop; - prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp); + prop = fdt_get_property_namelen_(fdt, nodeoffset, name, namelen, lenp, + &poffset); if (!prop) return NULL; + /* Handle realignment */ + if (fdt_version(fdt) < 0x10 && (poffset + sizeof(*prop)) % 8 && + fdt32_ld(&prop->len) >= 8) + return prop->data + 4; return prop->data; } @@ -338,11 +479,26 @@ { const struct fdt_property *prop; - prop = fdt_get_property_by_offset(fdt, offset, lenp); + prop = fdt_get_property_by_offset_(fdt, offset, lenp); if (!prop) return NULL; - if (namep) - *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff)); + if (namep) { + const char *name; + int namelen; + name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff), + &namelen); + if (!name) { + if (lenp) + *lenp = namelen; + return NULL; + } + *namep = name; + } + + /* Handle realignment */ + if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 && + fdt32_ld(&prop->len) >= 8) + return prop->data + 4; return prop->data; } @@ -366,7 +522,7 @@ return 0; } - return fdt32_to_cpu(*php); + return fdt32_ld(php); } const char *fdt_get_alias_namelen(const void *fdt, @@ -392,7 +548,7 @@ int offset, depth, namelen; const char *name; - FDT_CHECK_HEADER(fdt); + FDT_RO_PROBE(fdt); if (buflen < 2) return -FDT_ERR_NOSPACE; @@ -444,7 +600,7 @@ int offset, depth; int supernodeoffset = -FDT_ERR_INTERNAL; - FDT_CHECK_HEADER(fdt); + FDT_RO_PROBE(fdt); if (supernodedepth < 0) return -FDT_ERR_NOTFOUND; @@ -503,7 +659,7 @@ const void *val; int len; - FDT_CHECK_HEADER(fdt); + FDT_RO_PROBE(fdt); /* FIXME: The algorithm here is pretty horrible: we scan each * property of a node in fdt_getprop(), then if that didn't @@ -529,7 +685,7 @@ if ((phandle == 0) || (phandle == -1)) return -FDT_ERR_BADPHANDLE; - FDT_CHECK_HEADER(fdt); + FDT_RO_PROBE(fdt); /* FIXME: The algorithm here is pretty horrible: we * potentially scan each property of a node in @@ -682,7 +838,7 @@ { int offset, err; - FDT_CHECK_HEADER(fdt); + FDT_RO_PROBE(fdt); /* FIXME: The algorithm here is pretty horrible: we scan each * property of a node in fdt_node_check_compatible(), then if @@ -701,3 +857,66 @@ return offset; /* error from fdt_next_node() */ } + +int fdt_check_full(const void *fdt, size_t bufsize) +{ + int err; + int num_memrsv; + int offset, nextoffset = 0; + uint32_t tag; + unsigned depth = 0; + const void *prop; + const char *propname; + + if (bufsize < FDT_V1_SIZE) + return -FDT_ERR_TRUNCATED; + err = fdt_check_header(fdt); + if (err != 0) + return err; + if (bufsize < fdt_totalsize(fdt)) + return -FDT_ERR_TRUNCATED; + + num_memrsv = fdt_num_mem_rsv(fdt); + if (num_memrsv < 0) + return num_memrsv; + + while (1) { + offset = nextoffset; + tag = fdt_next_tag(fdt, offset, &nextoffset); + + if (nextoffset < 0) + return nextoffset; + + switch (tag) { + case FDT_NOP: + break; + + case FDT_END: + if (depth != 0) + return -FDT_ERR_BADSTRUCTURE; + return 0; + + case FDT_BEGIN_NODE: + depth++; + if (depth > INT_MAX) + return -FDT_ERR_BADSTRUCTURE; + break; + + case FDT_END_NODE: + if (depth == 0) + return -FDT_ERR_BADSTRUCTURE; + depth--; + break; + + case FDT_PROP: + prop = fdt_getprop_by_offset(fdt, offset, &propname, + &err); + if (!prop) + return err; + break; + + default: + return -FDT_ERR_INTERNAL; + } + } +} diff -Nru device-tree-compiler-1.4.5/libfdt/fdt_rw.c device-tree-compiler-1.4.7/libfdt/fdt_rw.c --- device-tree-compiler-1.4.5/libfdt/fdt_rw.c 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/libfdt/fdt_rw.c 2018-07-23 03:00:50.000000000 +0000 @@ -55,8 +55,8 @@ #include "libfdt_internal.h" -static int _fdt_blocks_misordered(const void *fdt, - int mem_rsv_size, int struct_size) +static int fdt_blocks_misordered_(const void *fdt, + int mem_rsv_size, int struct_size) { return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8)) || (fdt_off_dt_struct(fdt) < @@ -67,13 +67,13 @@ (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))); } -static int _fdt_rw_check_header(void *fdt) +static int fdt_rw_probe_(void *fdt) { - FDT_CHECK_HEADER(fdt); + FDT_RO_PROBE(fdt); if (fdt_version(fdt) < 17) return -FDT_ERR_BADVERSION; - if (_fdt_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry), + if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry), fdt_size_dt_struct(fdt))) return -FDT_ERR_BADLAYOUT; if (fdt_version(fdt) > 17) @@ -82,22 +82,22 @@ return 0; } -#define FDT_RW_CHECK_HEADER(fdt) \ +#define FDT_RW_PROBE(fdt) \ { \ - int __err; \ - if ((__err = _fdt_rw_check_header(fdt)) != 0) \ - return __err; \ + int err_; \ + if ((err_ = fdt_rw_probe_(fdt)) != 0) \ + return err_; \ } -static inline int _fdt_data_size(void *fdt) +static inline int fdt_data_size_(void *fdt) { return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); } -static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen) +static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen) { char *p = splicepoint; - char *end = (char *)fdt + _fdt_data_size(fdt); + char *end = (char *)fdt + fdt_data_size_(fdt); if (((p + oldlen) < p) || ((p + oldlen) > end)) return -FDT_ERR_BADOFFSET; @@ -109,12 +109,12 @@ return 0; } -static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p, +static int fdt_splice_mem_rsv_(void *fdt, struct fdt_reserve_entry *p, int oldn, int newn) { int delta = (newn - oldn) * sizeof(*p); int err; - err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p)); + err = fdt_splice_(fdt, p, oldn * sizeof(*p), newn * sizeof(*p)); if (err) return err; fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta); @@ -122,13 +122,13 @@ return 0; } -static int _fdt_splice_struct(void *fdt, void *p, +static int fdt_splice_struct_(void *fdt, void *p, int oldlen, int newlen) { int delta = newlen - oldlen; int err; - if ((err = _fdt_splice(fdt, p, oldlen, newlen))) + if ((err = fdt_splice_(fdt, p, oldlen, newlen))) return err; fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta); @@ -136,20 +136,20 @@ return 0; } -static int _fdt_splice_string(void *fdt, int newlen) +static int fdt_splice_string_(void *fdt, int newlen) { void *p = (char *)fdt + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); int err; - if ((err = _fdt_splice(fdt, p, 0, newlen))) + if ((err = fdt_splice_(fdt, p, 0, newlen))) return err; fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen); return 0; } -static int _fdt_find_add_string(void *fdt, const char *s) +static int fdt_find_add_string_(void *fdt, const char *s) { char *strtab = (char *)fdt + fdt_off_dt_strings(fdt); const char *p; @@ -157,13 +157,13 @@ int len = strlen(s) + 1; int err; - p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s); + p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s); if (p) /* found it */ return (p - strtab); new = strtab + fdt_size_dt_strings(fdt); - err = _fdt_splice_string(fdt, len); + err = fdt_splice_string_(fdt, len); if (err) return err; @@ -176,10 +176,10 @@ struct fdt_reserve_entry *re; int err; - FDT_RW_CHECK_HEADER(fdt); + FDT_RW_PROBE(fdt); - re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt)); - err = _fdt_splice_mem_rsv(fdt, re, 0, 1); + re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt)); + err = fdt_splice_mem_rsv_(fdt, re, 0, 1); if (err) return err; @@ -190,17 +190,17 @@ int fdt_del_mem_rsv(void *fdt, int n) { - struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n); + struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, n); - FDT_RW_CHECK_HEADER(fdt); + FDT_RW_PROBE(fdt); if (n >= fdt_num_mem_rsv(fdt)) return -FDT_ERR_NOTFOUND; - return _fdt_splice_mem_rsv(fdt, re, 1, 0); + return fdt_splice_mem_rsv_(fdt, re, 1, 0); } -static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name, +static int fdt_resize_property_(void *fdt, int nodeoffset, const char *name, int len, struct fdt_property **prop) { int oldlen; @@ -210,7 +210,7 @@ if (!*prop) return oldlen; - if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen), + if ((err = fdt_splice_struct_(fdt, (*prop)->data, FDT_TAGALIGN(oldlen), FDT_TAGALIGN(len)))) return err; @@ -218,7 +218,7 @@ return 0; } -static int _fdt_add_property(void *fdt, int nodeoffset, const char *name, +static int fdt_add_property_(void *fdt, int nodeoffset, const char *name, int len, struct fdt_property **prop) { int proplen; @@ -226,17 +226,17 @@ int namestroff; int err; - if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0) + if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0) return nextoffset; - namestroff = _fdt_find_add_string(fdt, name); + namestroff = fdt_find_add_string_(fdt, name); if (namestroff < 0) return namestroff; - *prop = _fdt_offset_ptr_w(fdt, nextoffset); + *prop = fdt_offset_ptr_w_(fdt, nextoffset); proplen = sizeof(**prop) + FDT_TAGALIGN(len); - err = _fdt_splice_struct(fdt, *prop, 0, proplen); + err = fdt_splice_struct_(fdt, *prop, 0, proplen); if (err) return err; @@ -252,7 +252,7 @@ int oldlen, newlen; int err; - FDT_RW_CHECK_HEADER(fdt); + FDT_RW_PROBE(fdt); namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen); if (!namep) @@ -260,7 +260,7 @@ newlen = strlen(name); - err = _fdt_splice_struct(fdt, namep, FDT_TAGALIGN(oldlen+1), + err = fdt_splice_struct_(fdt, namep, FDT_TAGALIGN(oldlen+1), FDT_TAGALIGN(newlen+1)); if (err) return err; @@ -275,11 +275,11 @@ struct fdt_property *prop; int err; - FDT_RW_CHECK_HEADER(fdt); + FDT_RW_PROBE(fdt); - err = _fdt_resize_property(fdt, nodeoffset, name, len, &prop); + err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop); if (err == -FDT_ERR_NOTFOUND) - err = _fdt_add_property(fdt, nodeoffset, name, len, &prop); + err = fdt_add_property_(fdt, nodeoffset, name, len, &prop); if (err) return err; @@ -308,12 +308,12 @@ struct fdt_property *prop; int err, oldlen, newlen; - FDT_RW_CHECK_HEADER(fdt); + FDT_RW_PROBE(fdt); prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); if (prop) { newlen = len + oldlen; - err = _fdt_splice_struct(fdt, prop->data, + err = fdt_splice_struct_(fdt, prop->data, FDT_TAGALIGN(oldlen), FDT_TAGALIGN(newlen)); if (err) @@ -321,7 +321,7 @@ prop->len = cpu_to_fdt32(newlen); memcpy(prop->data + oldlen, val, len); } else { - err = _fdt_add_property(fdt, nodeoffset, name, len, &prop); + err = fdt_add_property_(fdt, nodeoffset, name, len, &prop); if (err) return err; memcpy(prop->data, val, len); @@ -334,14 +334,14 @@ struct fdt_property *prop; int len, proplen; - FDT_RW_CHECK_HEADER(fdt); + FDT_RW_PROBE(fdt); prop = fdt_get_property_w(fdt, nodeoffset, name, &len); if (!prop) return len; proplen = sizeof(*prop) + FDT_TAGALIGN(len); - return _fdt_splice_struct(fdt, prop, proplen, 0); + return fdt_splice_struct_(fdt, prop, proplen, 0); } int fdt_add_subnode_namelen(void *fdt, int parentoffset, @@ -354,7 +354,7 @@ uint32_t tag; fdt32_t *endtag; - FDT_RW_CHECK_HEADER(fdt); + FDT_RW_PROBE(fdt); offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen); if (offset >= 0) @@ -369,10 +369,10 @@ tag = fdt_next_tag(fdt, offset, &nextoffset); } while ((tag == FDT_PROP) || (tag == FDT_NOP)); - nh = _fdt_offset_ptr_w(fdt, offset); + nh = fdt_offset_ptr_w_(fdt, offset); nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE; - err = _fdt_splice_struct(fdt, nh, 0, nodelen); + err = fdt_splice_struct_(fdt, nh, 0, nodelen); if (err) return err; @@ -394,17 +394,17 @@ { int endoffset; - FDT_RW_CHECK_HEADER(fdt); + FDT_RW_PROBE(fdt); - endoffset = _fdt_node_end_offset(fdt, nodeoffset); + endoffset = fdt_node_end_offset_(fdt, nodeoffset); if (endoffset < 0) return endoffset; - return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset), + return fdt_splice_struct_(fdt, fdt_offset_ptr_w_(fdt, nodeoffset), endoffset - nodeoffset, 0); } -static void _fdt_packblocks(const char *old, char *new, +static void fdt_packblocks_(const char *old, char *new, int mem_rsv_size, int struct_size) { int mem_rsv_off, struct_off, strings_off; @@ -435,7 +435,7 @@ const char *fdtend = fdtstart + fdt_totalsize(fdt); char *tmp; - FDT_CHECK_HEADER(fdt); + FDT_RO_PROBE(fdt); mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) * sizeof(struct fdt_reserve_entry); @@ -450,7 +450,7 @@ return struct_size; } - if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) { + if (!fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) { /* no further work necessary */ err = fdt_move(fdt, buf, bufsize); if (err) @@ -478,7 +478,7 @@ return -FDT_ERR_NOSPACE; } - _fdt_packblocks(fdt, tmp, mem_rsv_size, struct_size); + fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size); memmove(buf, tmp, newsize); fdt_set_magic(buf, FDT_MAGIC); @@ -494,12 +494,12 @@ { int mem_rsv_size; - FDT_RW_CHECK_HEADER(fdt); + FDT_RW_PROBE(fdt); mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) * sizeof(struct fdt_reserve_entry); - _fdt_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt)); - fdt_set_totalsize(fdt, _fdt_data_size(fdt)); + fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt)); + fdt_set_totalsize(fdt, fdt_data_size_(fdt)); return 0; } diff -Nru device-tree-compiler-1.4.5/libfdt/fdt_sw.c device-tree-compiler-1.4.7/libfdt/fdt_sw.c --- device-tree-compiler-1.4.5/libfdt/fdt_sw.c 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/libfdt/fdt_sw.c 2018-07-23 03:00:50.000000000 +0000 @@ -55,22 +55,78 @@ #include "libfdt_internal.h" -static int _fdt_sw_check_header(void *fdt) +static int fdt_sw_probe_(void *fdt) { - if (fdt_magic(fdt) != FDT_SW_MAGIC) + if (fdt_magic(fdt) == FDT_MAGIC) + return -FDT_ERR_BADSTATE; + else if (fdt_magic(fdt) != FDT_SW_MAGIC) return -FDT_ERR_BADMAGIC; - /* FIXME: should check more details about the header state */ return 0; } -#define FDT_SW_CHECK_HEADER(fdt) \ +#define FDT_SW_PROBE(fdt) \ + { \ + int err; \ + if ((err = fdt_sw_probe_(fdt)) != 0) \ + return err; \ + } + +/* 'memrsv' state: Initial state after fdt_create() + * + * Allowed functions: + * fdt_add_reservmap_entry() + * fdt_finish_reservemap() [moves to 'struct' state] + */ +static int fdt_sw_probe_memrsv_(void *fdt) +{ + int err = fdt_sw_probe_(fdt); + if (err) + return err; + + if (fdt_off_dt_strings(fdt) != 0) + return -FDT_ERR_BADSTATE; + return 0; +} + +#define FDT_SW_PROBE_MEMRSV(fdt) \ + { \ + int err; \ + if ((err = fdt_sw_probe_memrsv_(fdt)) != 0) \ + return err; \ + } + +/* 'struct' state: Enter this state after fdt_finish_reservemap() + * + * Allowed functions: + * fdt_begin_node() + * fdt_end_node() + * fdt_property*() + * fdt_finish() [moves to 'complete' state] + */ +static int fdt_sw_probe_struct_(void *fdt) +{ + int err = fdt_sw_probe_(fdt); + if (err) + return err; + + if (fdt_off_dt_strings(fdt) != fdt_totalsize(fdt)) + return -FDT_ERR_BADSTATE; + return 0; +} + +#define FDT_SW_PROBE_STRUCT(fdt) \ { \ int err; \ - if ((err = _fdt_sw_check_header(fdt)) != 0) \ + if ((err = fdt_sw_probe_struct_(fdt)) != 0) \ return err; \ } -static void *_fdt_grab_space(void *fdt, size_t len) +/* 'complete' state: Enter this state after fdt_finish() + * + * Allowed functions: none + */ + +static void *fdt_grab_space_(void *fdt, size_t len) { int offset = fdt_size_dt_struct(fdt); int spaceleft; @@ -82,14 +138,16 @@ return NULL; fdt_set_size_dt_struct(fdt, offset + len); - return _fdt_offset_ptr_w(fdt, offset); + return fdt_offset_ptr_w_(fdt, offset); } int fdt_create(void *buf, int bufsize) { + const size_t hdrsize = FDT_ALIGN(sizeof(struct fdt_header), + sizeof(struct fdt_reserve_entry)); void *fdt = buf; - if (bufsize < sizeof(struct fdt_header)) + if (bufsize < hdrsize) return -FDT_ERR_NOSPACE; memset(buf, 0, bufsize); @@ -99,10 +157,9 @@ fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION); fdt_set_totalsize(fdt, bufsize); - fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header), - sizeof(struct fdt_reserve_entry))); + fdt_set_off_mem_rsvmap(fdt, hdrsize); fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt)); - fdt_set_off_dt_strings(fdt, bufsize); + fdt_set_off_dt_strings(fdt, 0); return 0; } @@ -112,11 +169,14 @@ size_t headsize, tailsize; char *oldtail, *newtail; - FDT_SW_CHECK_HEADER(fdt); + FDT_SW_PROBE(fdt); - headsize = fdt_off_dt_struct(fdt); + headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); tailsize = fdt_size_dt_strings(fdt); + if ((headsize + tailsize) > fdt_totalsize(fdt)) + return -FDT_ERR_INTERNAL; + if ((headsize + tailsize) > bufsize) return -FDT_ERR_NOSPACE; @@ -133,8 +193,9 @@ memmove(buf, fdt, headsize); } - fdt_set_off_dt_strings(buf, bufsize); fdt_set_totalsize(buf, bufsize); + if (fdt_off_dt_strings(buf)) + fdt_set_off_dt_strings(buf, bufsize); return 0; } @@ -144,10 +205,7 @@ struct fdt_reserve_entry *re; int offset; - FDT_SW_CHECK_HEADER(fdt); - - if (fdt_size_dt_struct(fdt)) - return -FDT_ERR_BADSTATE; + FDT_SW_PROBE_MEMRSV(fdt); offset = fdt_off_dt_struct(fdt); if ((offset + sizeof(*re)) > fdt_totalsize(fdt)) @@ -164,17 +222,24 @@ int fdt_finish_reservemap(void *fdt) { - return fdt_add_reservemap_entry(fdt, 0, 0); + int err = fdt_add_reservemap_entry(fdt, 0, 0); + + if (err) + return err; + + fdt_set_off_dt_strings(fdt, fdt_totalsize(fdt)); + return 0; } int fdt_begin_node(void *fdt, const char *name) { struct fdt_node_header *nh; - int namelen = strlen(name) + 1; + int namelen; - FDT_SW_CHECK_HEADER(fdt); + FDT_SW_PROBE_STRUCT(fdt); - nh = _fdt_grab_space(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen)); + namelen = strlen(name) + 1; + nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen)); if (! nh) return -FDT_ERR_NOSPACE; @@ -187,9 +252,9 @@ { fdt32_t *en; - FDT_SW_CHECK_HEADER(fdt); + FDT_SW_PROBE_STRUCT(fdt); - en = _fdt_grab_space(fdt, FDT_TAGSIZE); + en = fdt_grab_space_(fdt, FDT_TAGSIZE); if (! en) return -FDT_ERR_NOSPACE; @@ -197,7 +262,7 @@ return 0; } -static int _fdt_find_add_string(void *fdt, const char *s) +static int fdt_find_add_string_(void *fdt, const char *s) { char *strtab = (char *)fdt + fdt_totalsize(fdt); const char *p; @@ -205,7 +270,7 @@ int len = strlen(s) + 1; int struct_top, offset; - p = _fdt_find_string(strtab - strtabsize, strtabsize, s); + p = fdt_find_string_(strtab - strtabsize, strtabsize, s); if (p) return p - strtab; @@ -225,13 +290,13 @@ struct fdt_property *prop; int nameoff; - FDT_SW_CHECK_HEADER(fdt); + FDT_SW_PROBE_STRUCT(fdt); - nameoff = _fdt_find_add_string(fdt, name); + nameoff = fdt_find_add_string_(fdt, name); if (nameoff == 0) return -FDT_ERR_NOSPACE; - prop = _fdt_grab_space(fdt, sizeof(*prop) + FDT_TAGALIGN(len)); + prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len)); if (! prop) return -FDT_ERR_NOSPACE; @@ -262,10 +327,10 @@ uint32_t tag; int offset, nextoffset; - FDT_SW_CHECK_HEADER(fdt); + FDT_SW_PROBE_STRUCT(fdt); /* Add terminator */ - end = _fdt_grab_space(fdt, sizeof(*end)); + end = fdt_grab_space_(fdt, sizeof(*end)); if (! end) return -FDT_ERR_NOSPACE; *end = cpu_to_fdt32(FDT_END); @@ -281,7 +346,7 @@ while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) { if (tag == FDT_PROP) { struct fdt_property *prop = - _fdt_offset_ptr_w(fdt, offset); + fdt_offset_ptr_w_(fdt, offset); int nameoff; nameoff = fdt32_to_cpu(prop->nameoff); diff -Nru device-tree-compiler-1.4.5/libfdt/fdt_wip.c device-tree-compiler-1.4.7/libfdt/fdt_wip.c --- device-tree-compiler-1.4.5/libfdt/fdt_wip.c 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/libfdt/fdt_wip.c 2018-07-23 03:00:50.000000000 +0000 @@ -93,7 +93,7 @@ val, len); } -static void _fdt_nop_region(void *start, int len) +static void fdt_nop_region_(void *start, int len) { fdt32_t *p; @@ -110,12 +110,12 @@ if (!prop) return len; - _fdt_nop_region(prop, len + sizeof(*prop)); + fdt_nop_region_(prop, len + sizeof(*prop)); return 0; } -int _fdt_node_end_offset(void *fdt, int offset) +int fdt_node_end_offset_(void *fdt, int offset) { int depth = 0; @@ -129,11 +129,11 @@ { int endoffset; - endoffset = _fdt_node_end_offset(fdt, nodeoffset); + endoffset = fdt_node_end_offset_(fdt, nodeoffset); if (endoffset < 0) return endoffset; - _fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0), + fdt_nop_region_(fdt_offset_ptr_w(fdt, nodeoffset, 0), endoffset - nodeoffset); return 0; } diff -Nru device-tree-compiler-1.4.5/libfdt/libfdt_env.h device-tree-compiler-1.4.7/libfdt/libfdt_env.h --- device-tree-compiler-1.4.5/libfdt/libfdt_env.h 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/libfdt/libfdt_env.h 2018-07-23 03:00:50.000000000 +0000 @@ -1,5 +1,5 @@ -#ifndef _LIBFDT_ENV_H -#define _LIBFDT_ENV_H +#ifndef LIBFDT_ENV_H +#define LIBFDT_ENV_H /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. @@ -56,6 +56,7 @@ #include #include #include +#include #ifdef __CHECKER__ #define FDT_FORCE __attribute__((force)) @@ -109,4 +110,31 @@ #undef CPU_TO_FDT16 #undef EXTRACT_BYTE -#endif /* _LIBFDT_ENV_H */ +#ifdef __APPLE__ +#include + +/* strnlen() is not available on Mac OS < 10.7 */ +# if !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED < \ + MAC_OS_X_VERSION_10_7) + +#define strnlen fdt_strnlen + +/* + * fdt_strnlen: returns the length of a string or max_count - which ever is + * smallest. + * Input 1 string: the string whose size is to be determined + * Input 2 max_count: the maximum value returned by this function + * Output: length of the string or max_count (the smallest of the two) + */ +static inline size_t fdt_strnlen(const char *string, size_t max_count) +{ + const char *p = memchr(string, 0, max_count); + return p ? p - string : max_count; +} + +#endif /* !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED < + MAC_OS_X_VERSION_10_7) */ + +#endif /* __APPLE__ */ + +#endif /* LIBFDT_ENV_H */ diff -Nru device-tree-compiler-1.4.5/libfdt/libfdt.h device-tree-compiler-1.4.7/libfdt/libfdt.h --- device-tree-compiler-1.4.5/libfdt/libfdt.h 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/libfdt/libfdt.h 2018-07-23 03:00:50.000000000 +0000 @@ -1,5 +1,5 @@ -#ifndef _LIBFDT_H -#define _LIBFDT_H +#ifndef LIBFDT_H +#define LIBFDT_H /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. @@ -54,7 +54,7 @@ #include #include -#define FDT_FIRST_SUPPORTED_VERSION 0x10 +#define FDT_FIRST_SUPPORTED_VERSION 0x02 #define FDT_LAST_SUPPORTED_VERSION 0x11 /* Error codes: informative error codes */ @@ -90,8 +90,9 @@ /* Error codes: codes for bad device tree blobs */ #define FDT_ERR_TRUNCATED 8 - /* FDT_ERR_TRUNCATED: Structure block of the given device tree - * ends without an FDT_END tag. */ + /* FDT_ERR_TRUNCATED: FDT or a sub-block is improperly + * terminated (overflows, goes outside allowed bounds, or + * isn't properly terminated). */ #define FDT_ERR_BADMAGIC 9 /* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a * device tree at all - it is missing the flattened device @@ -153,6 +154,29 @@ uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); +/* + * Alignment helpers: + * These helpers access words from a device tree blob. They're + * built to work even with unaligned pointers on platforms (ike + * ARM) that don't like unaligned loads and stores + */ + +static inline uint32_t fdt32_ld(const fdt32_t *p) +{ + fdt32_t v; + + memcpy(&v, p, sizeof(v)); + return fdt32_to_cpu(v); +} + +static inline uint64_t fdt64_ld(const fdt64_t *p) +{ + fdt64_t v; + + memcpy(&v, p, sizeof(v)); + return fdt64_to_cpu(v); +} + /**********************************************************************/ /* Traversal functions */ /**********************************************************************/ @@ -213,7 +237,7 @@ /* General functions */ /**********************************************************************/ #define fdt_get_header(fdt, field) \ - (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field)) + (fdt32_ld(&((const struct fdt_header *)(fdt))->field)) #define fdt_magic(fdt) (fdt_get_header(fdt, magic)) #define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize)) #define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct)) @@ -225,37 +249,50 @@ #define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings)) #define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct)) -#define __fdt_set_hdr(name) \ +#define fdt_set_hdr_(name) \ static inline void fdt_set_##name(void *fdt, uint32_t val) \ { \ struct fdt_header *fdth = (struct fdt_header *)fdt; \ fdth->name = cpu_to_fdt32(val); \ } -__fdt_set_hdr(magic); -__fdt_set_hdr(totalsize); -__fdt_set_hdr(off_dt_struct); -__fdt_set_hdr(off_dt_strings); -__fdt_set_hdr(off_mem_rsvmap); -__fdt_set_hdr(version); -__fdt_set_hdr(last_comp_version); -__fdt_set_hdr(boot_cpuid_phys); -__fdt_set_hdr(size_dt_strings); -__fdt_set_hdr(size_dt_struct); -#undef __fdt_set_hdr +fdt_set_hdr_(magic); +fdt_set_hdr_(totalsize); +fdt_set_hdr_(off_dt_struct); +fdt_set_hdr_(off_dt_strings); +fdt_set_hdr_(off_mem_rsvmap); +fdt_set_hdr_(version); +fdt_set_hdr_(last_comp_version); +fdt_set_hdr_(boot_cpuid_phys); +fdt_set_hdr_(size_dt_strings); +fdt_set_hdr_(size_dt_struct); +#undef fdt_set_hdr_ + +/** + * fdt_header_size - return the size of the tree's header + * @fdt: pointer to a flattened device tree + */ +size_t fdt_header_size_(uint32_t version); +static inline size_t fdt_header_size(const void *fdt) +{ + return fdt_header_size_(fdt_version(fdt)); +} /** - * fdt_check_header - sanity check a device tree or possible device tree + * fdt_check_header - sanity check a device tree header + * @fdt: pointer to data which might be a flattened device tree * * fdt_check_header() checks that the given buffer contains what - * appears to be a flattened device tree with sane information in its - * header. + * appears to be a flattened device tree, and that the header contains + * valid information (to the extent that can be determined from the + * header alone). * * returns: * 0, if the buffer appears to contain a valid device tree * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, standard meanings, as above + * -FDT_ERR_BADSTATE, + * -FDT_ERR_TRUNCATED, standard meanings, as above */ int fdt_check_header(const void *fdt); @@ -284,6 +321,24 @@ /* Read-only functions */ /**********************************************************************/ +int fdt_check_full(const void *fdt, size_t bufsize); + +/** + * fdt_get_string - retrieve a string from the strings block of a device tree + * @fdt: pointer to the device tree blob + * @stroffset: offset of the string within the strings block (native endian) + * @lenp: optional pointer to return the string's length + * + * fdt_get_string() retrieves a pointer to a single string from the + * strings block of the device tree blob at fdt, and optionally also + * returns the string's length in *lenp. + * + * returns: + * a pointer to the string, on success + * NULL, if stroffset is out of bounds, or doesn't point to a valid string + */ +const char *fdt_get_string(const void *fdt, int stroffset, int *lenp); + /** * fdt_string - retrieve a string from the strings block of a device tree * @fdt: pointer to the device tree blob @@ -294,7 +349,7 @@ * * returns: * a pointer to the string, on success - * NULL, if stroffset is out of bounds + * NULL, if stroffset is out of bounds, or doesn't point to a valid string */ const char *fdt_string(const void *fdt, int stroffset); @@ -527,6 +582,9 @@ * offset. If lenp is non-NULL, the length of the property value is * also returned, in the integer pointed to by lenp. * + * Note that this code only works on device tree versions >= 16. fdt_getprop() + * works on all versions. + * * returns: * pointer to the structure representing the property * if lenp is non-NULL, *lenp contains the length of the property @@ -1087,7 +1145,7 @@ * * returns: * 0 <= n < FDT_MAX_NCELLS, on success - * 2, if the node has no #address-cells property + * 2, if the node has no #size-cells property * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid * #size-cells property * -FDT_ERR_BADMAGIC, @@ -1310,10 +1368,13 @@ fdt64_t tmp = cpu_to_fdt64(val); return fdt_property(fdt, name, &tmp, sizeof(tmp)); } + +#ifndef SWIG /* Not available in Python */ static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val) { return fdt_property_u32(fdt, name, val); } +#endif /** * fdt_property_placeholder - add a new property and return a ptr to its value @@ -1449,7 +1510,7 @@ const void *val, int len); /** - * fdt_setprop _placeholder - allocate space for a property + * fdt_setprop_placeholder - allocate space for a property * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change * @name: name of the property to change @@ -1896,4 +1957,4 @@ const char *fdt_strerror(int errval); -#endif /* _LIBFDT_H */ +#endif /* LIBFDT_H */ diff -Nru device-tree-compiler-1.4.5/libfdt/libfdt_internal.h device-tree-compiler-1.4.7/libfdt/libfdt_internal.h --- device-tree-compiler-1.4.5/libfdt/libfdt_internal.h 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/libfdt/libfdt_internal.h 2018-07-23 03:00:50.000000000 +0000 @@ -1,5 +1,5 @@ -#ifndef _LIBFDT_INTERNAL_H -#define _LIBFDT_INTERNAL_H +#ifndef LIBFDT_INTERNAL_H +#define LIBFDT_INTERNAL_H /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. @@ -55,29 +55,30 @@ #define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) #define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE)) -#define FDT_CHECK_HEADER(fdt) \ +int fdt_ro_probe_(const void *fdt); +#define FDT_RO_PROBE(fdt) \ { \ - int __err; \ - if ((__err = fdt_check_header(fdt)) != 0) \ - return __err; \ + int err_; \ + if ((err_ = fdt_ro_probe_(fdt)) != 0) \ + return err_; \ } -int _fdt_check_node_offset(const void *fdt, int offset); -int _fdt_check_prop_offset(const void *fdt, int offset); -const char *_fdt_find_string(const char *strtab, int tabsize, const char *s); -int _fdt_node_end_offset(void *fdt, int nodeoffset); +int fdt_check_node_offset_(const void *fdt, int offset); +int fdt_check_prop_offset_(const void *fdt, int offset); +const char *fdt_find_string_(const char *strtab, int tabsize, const char *s); +int fdt_node_end_offset_(void *fdt, int nodeoffset); -static inline const void *_fdt_offset_ptr(const void *fdt, int offset) +static inline const void *fdt_offset_ptr_(const void *fdt, int offset) { return (const char *)fdt + fdt_off_dt_struct(fdt) + offset; } -static inline void *_fdt_offset_ptr_w(void *fdt, int offset) +static inline void *fdt_offset_ptr_w_(void *fdt, int offset) { - return (void *)(uintptr_t)_fdt_offset_ptr(fdt, offset); + return (void *)(uintptr_t)fdt_offset_ptr_(fdt, offset); } -static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n) +static inline const struct fdt_reserve_entry *fdt_mem_rsv_(const void *fdt, int n) { const struct fdt_reserve_entry *rsv_table = (const struct fdt_reserve_entry *) @@ -85,11 +86,11 @@ return rsv_table + n; } -static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n) +static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n) { - return (void *)(uintptr_t)_fdt_mem_rsv(fdt, n); + return (void *)(uintptr_t)fdt_mem_rsv_(fdt, n); } #define FDT_SW_MAGIC (~FDT_MAGIC) -#endif /* _LIBFDT_INTERNAL_H */ +#endif /* LIBFDT_INTERNAL_H */ diff -Nru device-tree-compiler-1.4.5/libfdt/version.lds device-tree-compiler-1.4.7/libfdt/version.lds --- device-tree-compiler-1.4.5/libfdt/version.lds 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/libfdt/version.lds 2018-07-23 03:00:50.000000000 +0000 @@ -60,9 +60,12 @@ fdt_address_cells; fdt_size_cells; fdt_stringlist_contains; + fdt_stringlist_count; + fdt_stringlist_search; + fdt_stringlist_get; fdt_resize; fdt_overlay_apply; - + fdt_get_string; local: *; }; diff -Nru device-tree-compiler-1.4.5/livetree.c device-tree-compiler-1.4.7/livetree.c --- device-tree-compiler-1.4.5/livetree.c 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/livetree.c 2018-07-23 03:00:50.000000000 +0000 @@ -134,6 +134,20 @@ return node; } +struct node *omit_node_if_unused(struct node *node) +{ + node->omit_if_unused = 1; + + return node; +} + +struct node *reference_node(struct node *node) +{ + node->is_referenced = 1; + + return node; +} + struct node *merge_nodes(struct node *old_node, struct node *new_node) { struct property *new_prop, *old_prop; @@ -216,6 +230,35 @@ return old_node; } +struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref) +{ + static unsigned int next_orphan_fragment = 0; + struct node *node; + struct property *p; + struct data d = empty_data; + char *name; + + if (ref[0] == '/') { + d = data_append_data(d, ref, strlen(ref) + 1); + + p = build_property("target-path", d); + } else { + d = data_add_marker(d, REF_PHANDLE, ref); + d = data_append_integer(d, 0xffffffff, 32); + + p = build_property("target", d); + } + + xasprintf(&name, "fragment@%u", + next_orphan_fragment++); + name_node(new_node, "__overlay__"); + node = build_node(p, new_node); + name_node(node, name); + + add_child(dt, node); + return dt; +} + struct node *chain_node(struct node *first, struct node *list) { assert(first->next_sibling == NULL); @@ -485,7 +528,7 @@ for_each_child(tree, child) { if (p && (strlen(child->name) == p-path) && - strneq(path, child->name, p-path)) + strprefixeq(path, p - path, child->name)) return get_node_by_path(child, p+1); else if (!p && streq(path, child->name)) return child; @@ -518,7 +561,10 @@ { struct node *child, *node; - assert((phandle != 0) && (phandle != -1)); + if ((phandle == 0) || (phandle == -1)) { + assert(generate_fixups); + return NULL; + } if (tree->phandle == phandle) { if (tree->deleted) @@ -548,6 +594,7 @@ cell_t get_node_phandle(struct node *root, struct node *node) { static cell_t phandle = 1; /* FIXME: ick, static local */ + struct data d = empty_data; if ((node->phandle != 0) && (node->phandle != -1)) return node->phandle; @@ -557,17 +604,16 @@ node->phandle = phandle; + d = data_add_marker(d, TYPE_UINT32, NULL); + d = data_append_cell(d, phandle); + if (!get_property(node, "linux,phandle") && (phandle_format & PHANDLE_LEGACY)) - add_property(node, - build_property("linux,phandle", - data_append_cell(empty_data, phandle))); + add_property(node, build_property("linux,phandle", d)); if (!get_property(node, "phandle") && (phandle_format & PHANDLE_EPAPR)) - add_property(node, - build_property("phandle", - data_append_cell(empty_data, phandle))); + add_property(node, build_property("phandle", d)); /* If the node *does* have a phandle property, we must * be dealing with a self-referencing phandle, which will be diff -Nru device-tree-compiler-1.4.5/Makefile device-tree-compiler-1.4.7/Makefile --- device-tree-compiler-1.4.5/Makefile 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/Makefile 2018-07-23 03:00:50.000000000 +0000 @@ -10,7 +10,7 @@ # VERSION = 1 PATCHLEVEL = 4 -SUBLEVEL = 5 +SUBLEVEL = 7 EXTRAVERSION = LOCAL_VERSION = CONFIG_LOCALVERSION = @@ -26,6 +26,10 @@ PKG_CONFIG ?= pkg-config INSTALL = /usr/bin/install +INSTALL_PROGRAM = $(INSTALL) +INSTALL_LIB = $(INSTALL) +INSTALL_DATA = $(INSTALL) -m 644 +INSTALL_SCRIPT = $(INSTALL) DESTDIR = PREFIX = $(HOME) BINDIR = $(PREFIX)/bin @@ -126,19 +130,23 @@ all: $(BIN) libfdt -# We need both Python and swig to build pylibfdt. -.PHONY: maybe_pylibfdt -maybe_pylibfdt: FORCE +# We need both Python and swig to build/install pylibfdt. +# This builds the given make ${target} if those deps are found. +check_python_deps = \ if $(PKG_CONFIG) --cflags python2 >/dev/null 2>&1; then \ if which swig >/dev/null 2>&1; then \ can_build=yes; \ fi; \ fi; \ - if [ "$$can_build" = "yes" ]; then \ - $(MAKE) pylibfdt; \ + if [ "$${can_build}" = "yes" ]; then \ + $(MAKE) $${target}; \ else \ - echo "## Skipping pylibfdt (install python dev and swig to build)"; \ - fi + echo "\#\# Skipping pylibfdt (install python dev and swig to build)"; \ + fi ; + +.PHONY: maybe_pylibfdt +maybe_pylibfdt: FORCE + target=pylibfdt; $(check_python_deps) ifeq ($(NO_PYTHON),) all: maybe_pylibfdt @@ -191,25 +199,30 @@ install-bin: all $(SCRIPTS) @$(VECHO) INSTALL-BIN $(INSTALL) -d $(DESTDIR)$(BINDIR) - $(INSTALL) $(BIN) $(SCRIPTS) $(DESTDIR)$(BINDIR) + $(INSTALL_PROGRAM) $(BIN) $(DESTDIR)$(BINDIR) + $(INSTALL_SCRIPT) $(SCRIPTS) $(DESTDIR)$(BINDIR) install-lib: all @$(VECHO) INSTALL-LIB $(INSTALL) -d $(DESTDIR)$(LIBDIR) - $(INSTALL) $(LIBFDT_lib) $(DESTDIR)$(LIBDIR) + $(INSTALL_LIB) $(LIBFDT_lib) $(DESTDIR)$(LIBDIR) ln -sf $(notdir $(LIBFDT_lib)) $(DESTDIR)$(LIBDIR)/$(LIBFDT_soname) ln -sf $(LIBFDT_soname) $(DESTDIR)$(LIBDIR)/libfdt.$(SHAREDLIB_EXT) - $(INSTALL) -m 644 $(LIBFDT_archive) $(DESTDIR)$(LIBDIR) + $(INSTALL_DATA) $(LIBFDT_archive) $(DESTDIR)$(LIBDIR) install-includes: @$(VECHO) INSTALL-INC $(INSTALL) -d $(DESTDIR)$(INCLUDEDIR) - $(INSTALL) -m 644 $(LIBFDT_include) $(DESTDIR)$(INCLUDEDIR) + $(INSTALL_DATA) $(LIBFDT_include) $(DESTDIR)$(INCLUDEDIR) install: install-bin install-lib install-includes +.PHONY: maybe_install_pylibfdt +maybe_install_pylibfdt: FORCE + target=install_pylibfdt; $(check_python_deps) + ifeq ($(NO_PYTHON),) -install: install_pylibfdt +install: maybe_install_pylibfdt endif $(VERSION_FILE): Makefile FORCE diff -Nru device-tree-compiler-1.4.5/pylibfdt/libfdt.i device-tree-compiler-1.4.7/pylibfdt/libfdt.i --- device-tree-compiler-1.4.5/pylibfdt/libfdt.i 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/pylibfdt/libfdt.i 2018-07-23 03:00:50.000000000 +0000 @@ -57,6 +57,18 @@ %{ #define SWIG_FILE_WITH_INIT #include "libfdt.h" + +/* + * We rename this function here to avoid problems with swig, since we also have + * a struct called fdt_property. That struct causes swig to create a class in + * libfdt.py called fdt_property(), which confuses things. + */ +static int fdt_property_stub(void *fdt, const char *name, const char *val, + int len) +{ + return fdt_property(fdt, name, val, len); +} + %} %pythoncode %{ @@ -88,6 +100,7 @@ # Pass this as the 'quiet' parameter to return -ENOTFOUND on NOTFOUND errors, # instead of raising an exception. QUIET_NOTFOUND = (NOTFOUND,) +QUIET_NOSPACE = (NOSPACE,) class FdtException(Exception): @@ -153,27 +166,182 @@ raise FdtException(val) return val -class Fdt: - """Device tree class, supporting all operations - - The Fdt object is created is created from a device tree binary file, - e.g. with something like: +class FdtRo(object): + """Class for a read-only device-tree - fdt = Fdt(open("filename.dtb").read()) - - Operations can then be performed using the methods in this class. Each - method xxx(args...) corresponds to a libfdt function fdt_xxx(fdt, args...). - - All methods raise an FdtException if an error occurs. To avoid this - behaviour a 'quiet' parameter is provided for some functions. This - defaults to empty, but you can pass a list of errors that you expect. - If one of these errors occurs, the function will return an error number - (e.g. -NOTFOUND). + This is a base class used by FdtRw (read-write access) and FdtSw + (sequential-write access). It implements read-only access to the + device tree. + + Here are the three classes and when you should use them: + + FdtRo - read-only access to an existing FDT + FdtRw - read-write access to an existing FDT (most common case) + FdtSw - for creating a new FDT, as well as allowing read-only access """ def __init__(self, data): self._fdt = bytearray(data) check_err(fdt_check_header(self._fdt)); + def as_bytearray(self): + """Get the device tree contents as a bytearray + + This can be passed directly to libfdt functions that access a + const void * for the device tree. + + Returns: + bytearray containing the device tree + """ + return bytearray(self._fdt) + + def next_node(self, nodeoffset, depth, quiet=()): + """Find the next subnode + + Args: + nodeoffset: Node offset of previous node + depth: The depth of the node at nodeoffset. This is used to + calculate the depth of the returned node + quiet: Errors to ignore (empty to raise on all errors) + + Returns: + Typle: + Offset of the next node, if any, else a -ve error + Depth of the returned node, if any, else undefined + + Raises: + FdtException if no more nodes found or other error occurs + """ + return check_err(fdt_next_node(self._fdt, nodeoffset, depth), quiet) + + def first_subnode(self, nodeoffset, quiet=()): + """Find the first subnode of a parent node + + Args: + nodeoffset: Node offset of parent node + quiet: Errors to ignore (empty to raise on all errors) + + Returns: + The offset of the first subnode, if any + + Raises: + FdtException if no subnodes found or other error occurs + """ + return check_err(fdt_first_subnode(self._fdt, nodeoffset), quiet) + + def next_subnode(self, nodeoffset, quiet=()): + """Find the next subnode + + Args: + nodeoffset: Node offset of previous subnode + quiet: Errors to ignore (empty to raise on all errors) + + Returns: + The offset of the next subnode, if any + + Raises: + FdtException if no more subnodes found or other error occurs + """ + return check_err(fdt_next_subnode(self._fdt, nodeoffset), quiet) + + def magic(self): + """Return the magic word from the header + + Returns: + Magic word + """ + return fdt_magic(self._fdt) + + def totalsize(self): + """Return the total size of the device tree + + Returns: + Total tree size in bytes + """ + return fdt_totalsize(self._fdt) + + def off_dt_struct(self): + """Return the start of the device-tree struct area + + Returns: + Start offset of struct area + """ + return fdt_off_dt_struct(self._fdt) + + def off_dt_strings(self): + """Return the start of the device-tree string area + + Returns: + Start offset of string area + """ + return fdt_off_dt_strings(self._fdt) + + def off_mem_rsvmap(self): + """Return the start of the memory reserve map + + Returns: + Start offset of memory reserve map + """ + return fdt_off_mem_rsvmap(self._fdt) + + def version(self): + """Return the version of the device tree + + Returns: + Version number of the device tree + """ + return fdt_version(self._fdt) + + def last_comp_version(self): + """Return the last compatible version of the device tree + + Returns: + Last compatible version number of the device tree + """ + return fdt_last_comp_version(self._fdt) + + def boot_cpuid_phys(self): + """Return the physical boot CPU ID + + Returns: + Physical boot CPU ID + """ + return fdt_boot_cpuid_phys(self._fdt) + + def size_dt_strings(self): + """Return the start of the device-tree string area + + Returns: + Start offset of string area + """ + return fdt_size_dt_strings(self._fdt) + + def size_dt_struct(self): + """Return the start of the device-tree struct area + + Returns: + Start offset of struct area + """ + return fdt_size_dt_struct(self._fdt) + + def num_mem_rsv(self, quiet=()): + """Return the number of memory reserve-map records + + Returns: + Number of memory reserve-map records + """ + return check_err(fdt_num_mem_rsv(self._fdt), quiet) + + def get_mem_rsv(self, index, quiet=()): + """Return the indexed memory reserve-map record + + Args: + index: Record to return (0=first) + + Returns: + Number of memory reserve-map records + """ + return check_err(fdt_get_mem_rsv(self._fdt, index), quiet) + def subnode_offset(self, parentoffset, name, quiet=()): """Get the offset of a named subnode @@ -206,6 +374,20 @@ """ return check_err(fdt_path_offset(self._fdt, path), quiet) + def get_name(self, nodeoffset): + """Get the name of a node + + Args: + nodeoffset: Offset of node to check + + Returns: + Node name + + Raises: + FdtException on error (e.g. nodeoffset is invalid) + """ + return check_err_null(fdt_get_name(self._fdt, nodeoffset))[0] + def first_property_offset(self, nodeoffset, quiet=()): """Get the offset of the first property in a node offset @@ -240,20 +422,6 @@ return check_err(fdt_next_property_offset(self._fdt, prop_offset), quiet) - def get_name(self, nodeoffset): - """Get the name of a node - - Args: - nodeoffset: Offset of node to check - - Returns: - Node name - - Raises: - FdtException on error (e.g. nodeoffset is invalid) - """ - return check_err_null(fdt_get_name(self._fdt, nodeoffset))[0] - def get_property_by_offset(self, prop_offset, quiet=()): """Obtains a property that can be examined @@ -274,51 +442,123 @@ return pdata return Property(pdata[0], pdata[1]) - def first_subnode(self, nodeoffset, quiet=()): - """Find the first subnode of a parent node + def getprop(self, nodeoffset, prop_name, quiet=()): + """Get a property from a node Args: - nodeoffset: Node offset of parent node + nodeoffset: Node offset containing property to get + prop_name: Name of property to get quiet: Errors to ignore (empty to raise on all errors) Returns: - The offset of the first subnode, if any + Value of property as a Property object (which can be used as a + bytearray/string), or -ve error number. On failure, returns an + integer error Raises: - FdtException if no subnode found or other error occurs + FdtError if any error occurs (e.g. the property is not found) """ - return check_err(fdt_first_subnode(self._fdt, nodeoffset), quiet) + pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name), + quiet) + if isinstance(pdata, (int)): + return pdata + return Property(prop_name, bytearray(pdata[0])) - def next_subnode(self, nodeoffset, quiet=()): - """Find the next subnode + def get_phandle(self, nodeoffset): + """Get the phandle of a node Args: - nodeoffset: Node offset of previous subnode + nodeoffset: Node offset to check + + Returns: + phandle of node, or 0 if the node has no phandle or another error + occurs + """ + return fdt_get_phandle(self._fdt, nodeoffset) + + def parent_offset(self, nodeoffset, quiet=()): + """Get the offset of a node's parent + + Args: + nodeoffset: Node offset to check quiet: Errors to ignore (empty to raise on all errors) Returns: - The offset of the next subnode, if any + The offset of the parent node, if any Raises: - FdtException if no more subnode found or other error occurs + FdtException if no parent found or other error occurs """ - return check_err(fdt_next_subnode(self._fdt, nodeoffset), quiet) + return check_err(fdt_parent_offset(self._fdt, nodeoffset), quiet) - def totalsize(self): - """Return the total size of the device tree + def node_offset_by_phandle(self, phandle, quiet=()): + """Get the offset of a node with the given phandle + + Args: + phandle: Phandle to search for + quiet: Errors to ignore (empty to raise on all errors) Returns: - Total tree size in bytes + The offset of node with that phandle, if any + + Raises: + FdtException if no node found or other error occurs """ - return check_err(fdt_totalsize(self._fdt)) + return check_err(fdt_node_offset_by_phandle(self._fdt, phandle), quiet) - def off_dt_struct(self): - """Return the start of the device tree struct area + +class Fdt(FdtRo): + """Device tree class, supporting all operations + + The Fdt object is created is created from a device tree binary file, + e.g. with something like: + + fdt = Fdt(open("filename.dtb").read()) + + Operations can then be performed using the methods in this class. Each + method xxx(args...) corresponds to a libfdt function fdt_xxx(fdt, args...). + + All methods raise an FdtException if an error occurs. To avoid this + behaviour a 'quiet' parameter is provided for some functions. This + defaults to empty, but you can pass a list of errors that you expect. + If one of these errors occurs, the function will return an error number + (e.g. -NOTFOUND). + """ + def __init__(self, data): + FdtRo.__init__(self, data) + + @staticmethod + def create_empty_tree(size, quiet=()): + """Create an empty device tree ready for use + + Args: + size: Size of device tree in bytes Returns: - Start offset of struct area + Fdt object containing the device tree """ - return check_err(fdt_off_dt_struct(self._fdt)) + data = bytearray(size) + err = check_err(fdt_create_empty_tree(data, size), quiet) + if err: + return err + return Fdt(data) + + def resize(self, size, quiet=()): + """Move the device tree into a larger or smaller space + + This creates a new device tree of size @size and moves the existing + device tree contents over to that. It can be used to create more space + in a device tree. Note that the Fdt object remains the same, but it + now has a new bytearray holding the contents. + + Args: + size: Required new size of device tree in bytes + """ + fdt = bytearray(size) + err = check_err(fdt_open_into(self._fdt, fdt, size), quiet) + if err: + return err + self._fdt = fdt def pack(self, quiet=()): """Pack the device tree to remove unused space @@ -328,86 +568,125 @@ Args: quiet: Errors to ignore (empty to raise on all errors) + Returns: + Error code, or 0 if OK + Raises: FdtException if any error occurs """ - return check_err(fdt_pack(self._fdt), quiet) + err = check_err(fdt_pack(self._fdt), quiet) + if err: + return err + del self._fdt[self.totalsize():] + return err - def delprop(self, nodeoffset, prop_name): - """Delete a property from a node + def set_name(self, nodeoffset, name, quiet=()): + """Set the name of a node Args: - nodeoffset: Node offset containing property to delete - prop_name: Name of property to delete + nodeoffset: Node offset of node to update + name: New node name (string without \0) + + Returns: + Error code, or 0 if OK Raises: - FdtError if the property does not exist, or another error occurs + FdtException if no parent found or other error occurs """ - return check_err(fdt_delprop(self._fdt, nodeoffset, prop_name)) + if chr(0) in name: + raise ValueError('Property contains embedded nul characters') + return check_err(fdt_set_name(self._fdt, nodeoffset, name), quiet) - def getprop(self, nodeoffset, prop_name, quiet=()): - """Get a property from a node + def setprop(self, nodeoffset, prop_name, val, quiet=()): + """Set the value of a property Args: - nodeoffset: Node offset containing property to get - prop_name: Name of property to get + nodeoffset: Node offset containing the property to create/update + prop_name: Name of property + val: Value to write (string or bytearray) quiet: Errors to ignore (empty to raise on all errors) Returns: - Value of property as a bytearray, or -ve error number + Error code, or 0 if OK Raises: - FdtError if any error occurs (e.g. the property is not found) + FdtException if no parent found or other error occurs """ - pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name), - quiet) - if isinstance(pdata, (int)): - return pdata - return bytearray(pdata[0]) + return check_err(fdt_setprop(self._fdt, nodeoffset, prop_name, val, + len(val)), quiet) - def get_phandle(self, nodeoffset): - """Get the phandle of a node + def setprop_u32(self, nodeoffset, prop_name, val, quiet=()): + """Set the value of a property Args: - nodeoffset: Node offset to check + nodeoffset: Node offset containing the property to create/update + prop_name: Name of property + val: Value to write (integer) + quiet: Errors to ignore (empty to raise on all errors) Returns: - phandle of node, or 0 if the node has no phandle or another error - occurs + Error code, or 0 if OK + + Raises: + FdtException if no parent found or other error occurs """ - return fdt_get_phandle(self._fdt, nodeoffset) + return check_err(fdt_setprop_u32(self._fdt, nodeoffset, prop_name, val), + quiet) - def parent_offset(self, nodeoffset, quiet=()): - """Get the offset of a node's parent + def setprop_u64(self, nodeoffset, prop_name, val, quiet=()): + """Set the value of a property Args: - nodeoffset: Node offset to check + nodeoffset: Node offset containing the property to create/update + prop_name: Name of property + val: Value to write (integer) quiet: Errors to ignore (empty to raise on all errors) Returns: - The offset of the parent node, if any + Error code, or 0 if OK Raises: FdtException if no parent found or other error occurs """ - return check_err(fdt_parent_offset(self._fdt, nodeoffset), quiet) + return check_err(fdt_setprop_u64(self._fdt, nodeoffset, prop_name, val), + quiet) - def node_offset_by_phandle(self, phandle, quiet=()): - """Get the offset of a node with the given phandle + def setprop_str(self, nodeoffset, prop_name, val, quiet=()): + """Set the string value of a property + + The property is set to the string, with a nul terminator added Args: - phandle: Phandle to search for + nodeoffset: Node offset containing the property to create/update + prop_name: Name of property + val: Value to write (string without nul terminator). Unicode is + supposed by encoding to UTF-8 quiet: Errors to ignore (empty to raise on all errors) Returns: - The offset of node with that phandle, if any + Error code, or 0 if OK Raises: - FdtException if no node found or other error occurs + FdtException if no parent found or other error occurs """ - return check_err(fdt_node_offset_by_phandle(self._fdt, phandle), quiet) + val = val.encode('utf-8') + '\0' + return check_err(fdt_setprop(self._fdt, nodeoffset, prop_name, + val, len(val)), quiet) + + def delprop(self, nodeoffset, prop_name): + """Delete a property from a node + + Args: + nodeoffset: Node offset containing property to delete + prop_name: Name of property to delete + + Raises: + FdtError if the property does not exist, or another error occurs + """ + return check_err(fdt_delprop(self._fdt, nodeoffset, prop_name)) + -class Property: +class Property(bytearray): """Holds a device tree property name and value. This holds a copy of a property taken from the device tree. It does not @@ -416,16 +695,305 @@ Properties: name: Property name - value: Proper value as a bytearray + value: Property value as a bytearray """ def __init__(self, name, value): + bytearray.__init__(self, value) self.name = name - self.value = value + + def as_cell(self, fmt): + return struct.unpack('>' + fmt, self)[0] + + def as_uint32(self): + return self.as_cell('L') + + def as_int32(self): + return self.as_cell('l') + + def as_uint64(self): + return self.as_cell('Q') + + def as_int64(self): + return self.as_cell('q') + + def as_str(self): + """Unicode is supported by decoding from UTF-8""" + if self[-1] != 0: + raise ValueError('Property lacks nul termination') + if 0 in self[:-1]: + raise ValueError('Property contains embedded nul characters') + return self[:-1].decode('utf-8') + + +class FdtSw(FdtRo): + """Software interface to create a device tree from scratch + + The methods in this class work by adding to an existing 'partial' device + tree buffer of a fixed size created by instantiating this class. When the + tree is complete, call as_fdt() to obtain a device tree ready to be used. + + Similarly with nodes, a new node is started with begin_node() and finished + with end_node(). + + The context manager functions can be used to make this a bit easier: + + # First create the device tree with a node and property: + sw = FdtSw() + with sw.add_node('node'): + sw.property_u32('reg', 2) + fdt = sw.as_fdt() + + # Now we can use it as a real device tree + fdt.setprop_u32(0, 'reg', 3) + + The size hint provides a starting size for the space to be used by the + device tree. This will be increased automatically as needed as new items + are added to the tree. + """ + INC_SIZE = 1024 # Expand size by this much when out of space + + def __init__(self, size_hint=None): + """Create a new FdtSw object + + Args: + size_hint: A hint as to the initial size to use + + Raises: + ValueError if size_hint is negative + + Returns: + FdtSw object on success, else integer error code (if not raising) + """ + if not size_hint: + size_hint = self.INC_SIZE + fdtsw = bytearray(size_hint) + err = check_err(fdt_create(fdtsw, size_hint)) + if err: + return err + self._fdt = fdtsw + + def as_fdt(self): + """Convert a FdtSw into an Fdt so it can be accessed as normal + + Creates a new Fdt object from the work-in-progress device tree. This + does not call fdt_finish() on the current object, so it is possible to + add more nodes/properties and call as_fdt() again to get an updated + tree. + + Returns: + Fdt object allowing access to the newly created device tree + """ + fdtsw = bytearray(self._fdt) + check_err(fdt_finish(fdtsw)) + return Fdt(fdtsw) + + def check_space(self, val): + """Check if we need to add more space to the FDT + + This should be called with the error code from an operation. If this is + -NOSPACE then the FDT will be expanded to have more space, and True will + be returned, indicating that the operation needs to be tried again. + + Args: + val: Return value from the operation that was attempted + + Returns: + True if the operation must be retried, else False + """ + if check_err(val, QUIET_NOSPACE) < 0: + self.resize(len(self._fdt) + self.INC_SIZE) + return True + return False + + def resize(self, size): + """Resize the buffer to accommodate a larger tree + + Args: + size: New size of tree + + Raises: + FdtException on any error + """ + fdt = bytearray(size) + err = check_err(fdt_resize(self._fdt, fdt, size)) + self._fdt = fdt + + def add_reservemap_entry(self, addr, size): + """Add a new memory reserve map entry + + Once finished adding, you must call finish_reservemap(). + + Args: + addr: 64-bit start address + size: 64-bit size + + Raises: + FdtException on any error + """ + while self.check_space(fdt_add_reservemap_entry(self._fdt, addr, + size)): + pass + + def finish_reservemap(self): + """Indicate that there are no more reserve map entries to add + + Raises: + FdtException on any error + """ + while self.check_space(fdt_finish_reservemap(self._fdt)): + pass + + def begin_node(self, name): + """Begin a new node + + Use this before adding properties to the node. Then call end_node() to + finish it. You can also use the context manager as shown in the FdtSw + class comment. + + Args: + name: Name of node to begin + + Raises: + FdtException on any error + """ + while self.check_space(fdt_begin_node(self._fdt, name)): + pass + + def property_string(self, name, string): + """Add a property with a string value + + The string will be nul-terminated when written to the device tree + + Args: + name: Name of property to add + string: String value of property + + Raises: + FdtException on any error + """ + while self.check_space(fdt_property_string(self._fdt, name, string)): + pass + + def property_u32(self, name, val): + """Add a property with a 32-bit value + + Write a single-cell value to the device tree + + Args: + name: Name of property to add + val: Value of property + + Raises: + FdtException on any error + """ + while self.check_space(fdt_property_u32(self._fdt, name, val)): + pass + + def property_u64(self, name, val): + """Add a property with a 64-bit value + + Write a double-cell value to the device tree in big-endian format + + Args: + name: Name of property to add + val: Value of property + + Raises: + FdtException on any error + """ + while self.check_space(fdt_property_u64(self._fdt, name, val)): + pass + + def property_cell(self, name, val): + """Add a property with a single-cell value + + Write a single-cell value to the device tree + + Args: + name: Name of property to add + val: Value of property + quiet: Errors to ignore (empty to raise on all errors) + + Raises: + FdtException on any error + """ + while self.check_space(fdt_property_cell(self._fdt, name, val)): + pass + + def property(self, name, val): + """Add a property + + Write a new property with the given value to the device tree. The value + is taken as is and is not nul-terminated + + Args: + name: Name of property to add + val: Value of property + quiet: Errors to ignore (empty to raise on all errors) + + Raises: + FdtException on any error + """ + while self.check_space(fdt_property_stub(self._fdt, name, val, + len(val))): + pass + + def end_node(self): + """End a node + + Use this after adding properties to a node to close it off. You can also + use the context manager as shown in the FdtSw class comment. + + Args: + quiet: Errors to ignore (empty to raise on all errors) + + Raises: + FdtException on any error + """ + while self.check_space(fdt_end_node(self._fdt)): + pass + + def add_node(self, name): + """Create a new context for adding a node + + When used in a 'with' clause this starts a new node and finishes it + afterward. + + Args: + name: Name of node to add + """ + return NodeAdder(self, name) + + +class NodeAdder(): + """Class to provide a node context + + This allows you to add nodes in a more natural way: + + with fdtsw.add_node('name'): + fdtsw.property_string('test', 'value') + + The node is automatically completed with a call to end_node() when the + context exits. + """ + def __init__(self, fdtsw, name): + self._fdt = fdtsw + self._name = name + + def __enter__(self): + self._fdt.begin_node(self._name) + + def __exit__(self, type, value, traceback): + self._fdt.end_node() %} %rename(fdt_property) fdt_property_func; -typedef int fdt32_t; +/* + * fdt32_t is a big-endian 32-bit value defined to uint32_t in libfdt_env.h + * so use the same type here. + */ +typedef uint32_t fdt32_t; %include "libfdt/fdt.h" @@ -453,6 +1021,7 @@ fdt = fdt; /* avoid unused variable warning */ } +/* typemap used for fdt_get_property_by_offset() */ %typemap(out) (struct fdt_property *) { PyObject *buff; @@ -475,19 +1044,66 @@ $result = Py_BuildValue("s#", $1, *arg4); } +/* typemap used for fdt_setprop() */ +%typemap(in) (const void *val) { + $1 = PyString_AsString($input); /* char *str */ +} + +/* typemap used for fdt_add_reservemap_entry() */ +%typemap(in) uint64_t { + $1 = PyLong_AsUnsignedLong($input); +} + +/* typemaps used for fdt_next_node() */ +%typemap(in, numinputs=1) int *depth (int depth) { + depth = (int) PyInt_AsLong($input); + $1 = &depth; +} + +%typemap(argout) int *depth { + PyObject *val = Py_BuildValue("i", *arg$argnum); + resultobj = SWIG_Python_AppendOutput(resultobj, val); +} + +%apply int *depth { int *depth }; + +/* typemaps for fdt_get_mem_rsv */ +%typemap(in, numinputs=0) uint64_t * (uint64_t temp) { + $1 = &temp; +} + +%typemap(argout) uint64_t * { + PyObject *val = PyLong_FromUnsignedLong(*arg$argnum); + if (!result) { + if (PyTuple_GET_SIZE(resultobj) == 0) + resultobj = val; + else + resultobj = SWIG_Python_AppendOutput(resultobj, val); + } +} + /* We have both struct fdt_property and a function fdt_property() */ %warnfilter(302) fdt_property; /* These are macros in the header so have to be redefined here */ -int fdt_magic(const void *fdt); -int fdt_totalsize(const void *fdt); -int fdt_off_dt_struct(const void *fdt); -int fdt_off_dt_strings(const void *fdt); -int fdt_off_mem_rsvmap(const void *fdt); -int fdt_version(const void *fdt); -int fdt_last_comp_version(const void *fdt); -int fdt_boot_cpuid_phys(const void *fdt); -int fdt_size_dt_strings(const void *fdt); -int fdt_size_dt_struct(const void *fdt); +uint32_t fdt_magic(const void *fdt); +uint32_t fdt_totalsize(const void *fdt); +uint32_t fdt_off_dt_struct(const void *fdt); +uint32_t fdt_off_dt_strings(const void *fdt); +uint32_t fdt_off_mem_rsvmap(const void *fdt); +uint32_t fdt_version(const void *fdt); +uint32_t fdt_last_comp_version(const void *fdt); +uint32_t fdt_boot_cpuid_phys(const void *fdt); +uint32_t fdt_size_dt_strings(const void *fdt); +uint32_t fdt_size_dt_struct(const void *fdt); + +int fdt_property_string(void *fdt, const char *name, const char *val); +int fdt_property_cell(void *fdt, const char *name, uint32_t val); + +/* + * This function has a stub since the name fdt_property is used for both a + * function and a struct, which confuses SWIG. + */ +int fdt_property_stub(void *fdt, const char *name, const char *val, int len); %include <../libfdt/libfdt.h> diff -Nru device-tree-compiler-1.4.5/srcpos.c device-tree-compiler-1.4.7/srcpos.c --- device-tree-compiler-1.4.5/srcpos.c 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/srcpos.c 2018-07-23 03:00:50.000000000 +0000 @@ -209,8 +209,6 @@ .file = NULL, }; -#define TAB_SIZE 8 - void srcpos_update(struct srcpos *pos, const char *text, int len) { int i; @@ -224,9 +222,6 @@ if (text[i] == '\n') { current_srcfile->lineno++; current_srcfile->colno = 1; - } else if (text[i] == '\t') { - current_srcfile->colno = - ALIGN(current_srcfile->colno, TAB_SIZE); } else { current_srcfile->colno++; } diff -Nru device-tree-compiler-1.4.5/srcpos.h device-tree-compiler-1.4.7/srcpos.h --- device-tree-compiler-1.4.5/srcpos.h 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/srcpos.h 2018-07-23 03:00:50.000000000 +0000 @@ -17,8 +17,8 @@ * USA */ -#ifndef _SRCPOS_H_ -#define _SRCPOS_H_ +#ifndef SRCPOS_H +#define SRCPOS_H #include #include @@ -114,4 +114,4 @@ extern void srcpos_set_line(char *f, int l); -#endif /* _SRCPOS_H_ */ +#endif /* SRCPOS_H */ diff -Nru device-tree-compiler-1.4.5/tests/addresses.dts device-tree-compiler-1.4.7/tests/addresses.dts --- device-tree-compiler-1.4.5/tests/addresses.dts 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/addresses.dts 2018-07-23 03:00:50.000000000 +0000 @@ -12,4 +12,19 @@ #address-cells = <2>; #size-cells = <1>; }; + + c0@0 { + #address-cells = <1 1>; + #size-cells = <1 1>; + }; + + c1@0 { + #address-cells = <0x80000000>; + #size-cells = <0x80000000>; + }; + + c2@0 { + #address-cells = <5>; + #size-cells = <5>; + }; }; diff -Nru device-tree-compiler-1.4.5/tests/addr_size_cells2.c device-tree-compiler-1.4.7/tests/addr_size_cells2.c --- device-tree-compiler-1.4.5/tests/addr_size_cells2.c 1970-01-01 00:00:00.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/addr_size_cells2.c 2018-07-23 03:00:50.000000000 +0000 @@ -0,0 +1,62 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for #address-cells and #size-cells handling + * Copyright (C) 2014 David Gibson, + * + * 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 +#include +#include +#include + +#include + +#include "tests.h" +#include "testdata.h" + +static void check_node(const void *fdt, const char *path, int ac, int sc) +{ + int offset; + int xac, xsc; + + offset = fdt_path_offset(fdt, path); + if (offset < 0) + FAIL("Couldn't find path %s", path); + + xac = fdt_address_cells(fdt, offset); + xsc = fdt_size_cells(fdt, offset); + + if (xac != ac) + FAIL("Address cells for %s is %d instead of %d\n", + path, xac, ac); + if (xsc != sc) + FAIL("Size cells for %s is %d instead of %d\n", + path, xsc, sc); +} + +int main(int argc, char *argv[]) +{ + void *fdt; + + if (argc != 2) + CONFIG("Usage: %s \n", argv[0]); + + test_init(argc, argv); + fdt = load_blob(argv[1]); + + check_node(fdt, "/", 2, 2); + PASS(); +} diff -Nru device-tree-compiler-1.4.5/tests/addr_size_cells.c device-tree-compiler-1.4.7/tests/addr_size_cells.c --- device-tree-compiler-1.4.5/tests/addr_size_cells.c 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/addr_size_cells.c 2018-07-23 03:00:50.000000000 +0000 @@ -60,5 +60,8 @@ check_node(fdt, "/", 2, 2); check_node(fdt, "/identity-bus@0", 2, 2); check_node(fdt, "/simple-bus@1000000", 2, 1); + check_node(fdt, "/c0", -FDT_ERR_BADNCELLS, -FDT_ERR_BADNCELLS); + check_node(fdt, "/c1", -FDT_ERR_BADNCELLS, -FDT_ERR_BADNCELLS); + check_node(fdt, "/c2", -FDT_ERR_BADNCELLS, -FDT_ERR_BADNCELLS); PASS(); } diff -Nru device-tree-compiler-1.4.5/tests/bad-chosen.dts device-tree-compiler-1.4.7/tests/bad-chosen.dts --- device-tree-compiler-1.4.5/tests/bad-chosen.dts 1970-01-01 00:00:00.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/bad-chosen.dts 2018-07-23 03:00:50.000000000 +0000 @@ -0,0 +1,10 @@ +/dts-v1/; + +/ { + node2 { + chosen { + bootargs = <0xdeadbeef>; + stdout-path = <1>; + }; + }; +}; diff -Nru device-tree-compiler-1.4.5/tests/bad-graph.dts device-tree-compiler-1.4.7/tests/bad-graph.dts --- device-tree-compiler-1.4.5/tests/bad-graph.dts 1970-01-01 00:00:00.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/bad-graph.dts 2018-07-23 03:00:50.000000000 +0000 @@ -0,0 +1,24 @@ +/dts-v1/; + +/ { + ports { + #address-cells = <1>; + #size-cells = <0>; + + bad_endpoint: port-a@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + endpoint@d0 { + reg = <0>; + remote-endpoint = <0xdeadbeef>; + }; + + }; + + port@1 { + reg = <0>; + }; + }; +}; diff -Nru device-tree-compiler-1.4.5/tests/bad-string-props.dts device-tree-compiler-1.4.7/tests/bad-string-props.dts --- device-tree-compiler-1.4.5/tests/bad-string-props.dts 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/bad-string-props.dts 2018-07-23 03:00:50.000000000 +0000 @@ -4,4 +4,11 @@ device_type = <0xdeadbeef>; model = <0xdeadbeef>; status = <0xdeadbeef>; + label = <0xdeadbeef>; + + foobar-names = "foo", <1>; + + node { + compatible = "good", <0xdeadbeef>; + }; }; diff -Nru device-tree-compiler-1.4.5/tests/check_full.c device-tree-compiler-1.4.7/tests/check_full.c --- device-tree-compiler-1.4.5/tests/check_full.c 1970-01-01 00:00:00.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/check_full.c 2018-07-23 03:00:50.000000000 +0000 @@ -0,0 +1,63 @@ +/* + * 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 +#include +#include +#include + +#include + +#include "tests.h" +#include "testdata.h" + +static int expect_bad; /* = 0 */ + +int main(int argc, char *argv[]) +{ + const char *filename; + char *fdt; + size_t len; + int err; + + test_init(argc, argv); + if ((argc != 2) + && ((argc != 3) || !streq(argv[1], "-n"))) + CONFIG("Usage: %s [-n] ", argv[0]); + if (argc == 3) + expect_bad = 1; + + filename = argv[argc-1]; + err = utilfdt_read_err(filename, &fdt, &len); + if (err) + CONFIG("Couldn't open blob from \"%s\": %s", + filename, strerror(err)); + + vg_prepare_blob(fdt, len); + + err = fdt_check_full(fdt, len); + + if (expect_bad && (err == 0)) + FAIL("fdt_check_full() succeeded unexpectedly"); + else if (!expect_bad && (err != 0)) + FAIL("fdt_check_full() failed: %s", fdt_strerror(err)); + + PASS(); +} diff -Nru device-tree-compiler-1.4.5/tests/check_header.c device-tree-compiler-1.4.7/tests/check_header.c --- device-tree-compiler-1.4.5/tests/check_header.c 1970-01-01 00:00:00.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/check_header.c 2018-07-23 03:00:50.000000000 +0000 @@ -0,0 +1,128 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_check_header + * Copyright (C) 2018 David Gibson + * + * 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 + +#include + +#include "tests.h" + +static void *dtdup(void *dt) +{ + size_t bufsize = fdt_totalsize(dt); + void *buf = xmalloc(bufsize); + fdt_move(dt, buf, bufsize); + return buf; +} + +#define CHECK_MANGLE(exerr, code) \ + do { \ + void *fdt = dtdup(template); \ + { code } \ + err = fdt_check_header(fdt); \ + verbose_printf("\"%s\" => %s\n", #code, fdt_strerror(err)); \ + if (err != (exerr)) \ + FAIL("fdt_check_header() didn't catch mangle %s", \ + #code); \ + free(fdt); \ + } while (0) + +int main(int argc, char *argv[]) +{ + void *template; + int err; + + test_init(argc, argv); + template = load_blob(argv[1]); + + /* Check that the base dt is valid before mangling it */ + err = fdt_check_header(template); + if (err != 0) + FAIL("Base tree fails: %s", fdt_strerror(err)); + + /* Check a no-op mangle doesn't break things */ + CHECK_MANGLE(0, ; ); + + /* Mess up the magic number */ + CHECK_MANGLE(-FDT_ERR_BADMAGIC, + fdt_set_magic(fdt, fdt_magic(fdt) ^ 0x1); + ); + CHECK_MANGLE(-FDT_ERR_BADMAGIC, + fdt_set_magic(fdt, fdt_magic(fdt) ^ 0x80000000); + ); + + /* Mess up the version */ + CHECK_MANGLE(-FDT_ERR_BADVERSION, + fdt_set_version(fdt, FDT_FIRST_SUPPORTED_VERSION - 1); + fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION - 1); + ); + CHECK_MANGLE(-FDT_ERR_BADVERSION, + fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION + 1); + fdt_set_last_comp_version(fdt, FDT_LAST_SUPPORTED_VERSION + 1); + ); + CHECK_MANGLE(-FDT_ERR_BADVERSION, + fdt_set_version(fdt, FDT_FIRST_SUPPORTED_VERSION); + fdt_set_last_comp_version(fdt, FDT_LAST_SUPPORTED_VERSION); + ); + + /* Out of bounds sizes */ + CHECK_MANGLE(-FDT_ERR_TRUNCATED, + fdt_set_totalsize(fdt, FDT_V1_SIZE - 1); + ); + CHECK_MANGLE(-FDT_ERR_TRUNCATED, + fdt_set_totalsize(fdt, (uint32_t)INT_MAX + 1); + ); + + /* Truncate within various blocks */ + CHECK_MANGLE(-FDT_ERR_TRUNCATED, + fdt_set_totalsize(fdt, fdt_off_dt_struct(fdt) - 1); + ); + CHECK_MANGLE(-FDT_ERR_TRUNCATED, + fdt_set_totalsize(fdt, fdt_off_dt_strings(fdt) - 1); + ); + CHECK_MANGLE(-FDT_ERR_TRUNCATED, + fdt_set_totalsize(fdt, fdt_off_mem_rsvmap(fdt) - 1); + ); + CHECK_MANGLE(-FDT_ERR_TRUNCATED, + fdt_set_totalsize(fdt, fdt_off_dt_struct(fdt) + 1); + ); + CHECK_MANGLE(-FDT_ERR_TRUNCATED, + fdt_set_totalsize(fdt, fdt_off_dt_strings(fdt) + 1); + ); + CHECK_MANGLE(-FDT_ERR_TRUNCATED, + fdt_set_totalsize(fdt, fdt_off_mem_rsvmap(fdt) + 1); + ); + + /* Negative block sizes */ + CHECK_MANGLE(-FDT_ERR_TRUNCATED, + fdt_set_size_dt_struct(fdt, (uint32_t)-1); + ); + CHECK_MANGLE(-FDT_ERR_TRUNCATED, + fdt_set_size_dt_strings(fdt, (uint32_t)-1); + ); + CHECK_MANGLE(-FDT_ERR_TRUNCATED, + fdt_set_size_dt_struct(fdt, (uint32_t)INT_MIN); + ); + CHECK_MANGLE(-FDT_ERR_TRUNCATED, + fdt_set_size_dt_strings(fdt, (uint32_t)INT_MIN); + ); + + PASS(); +} diff -Nru device-tree-compiler-1.4.5/tests/dtc-checkfails.sh device-tree-compiler-1.4.7/tests/dtc-checkfails.sh --- device-tree-compiler-1.4.5/tests/dtc-checkfails.sh 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/dtc-checkfails.sh 2018-07-23 03:00:50.000000000 +0000 @@ -30,13 +30,13 @@ FAIL_IF_SIGNAL $ret for c in $YESCHECKS; do - if ! grep -E "^(ERROR)|(Warning) \($c\):" $LOG > /dev/null; then + if ! grep -E "(ERROR|Warning) \($c\):" $LOG > /dev/null; then FAIL "Failed to trigger check \"$c\"" fi done for c in $NOCHECKS; do - if grep -E "^(ERROR)|(Warning) \($c\):" $LOG > /dev/null; then + if grep -E "(ERROR|Warning) \($c\):" $LOG > /dev/null; then FAIL "Incorrectly triggered check \"$c\"" fi done diff -Nru device-tree-compiler-1.4.5/tests/dumptrees.c device-tree-compiler-1.4.7/tests/dumptrees.c --- device-tree-compiler-1.4.5/tests/dumptrees.c 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/dumptrees.c 2018-07-23 03:00:50.000000000 +0000 @@ -33,10 +33,12 @@ void *blob; const char *filename; } trees[] = { -#define TREE(name) { &_##name, #name ".dtb" } +#define TREE(name) { &name, #name ".dtb" } TREE(test_tree1), TREE(bad_node_char), TREE(bad_node_format), TREE(bad_prop_char), TREE(ovf_size_strings), + TREE(truncated_property), TREE(truncated_string), + TREE(truncated_memrsv), }; #define NUM_TREES (sizeof(trees) / sizeof(trees[0])) diff -Nru device-tree-compiler-1.4.5/tests/get_path.c device-tree-compiler-1.4.7/tests/get_path.c --- device-tree-compiler-1.4.5/tests/get_path.c 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/get_path.c 2018-07-23 03:00:50.000000000 +0000 @@ -42,7 +42,8 @@ memset(buf, POISON, sizeof(buf)); /* poison the buffer */ len = fdt_get_path(fdt, offset, buf, buflen); - verbose_printf("get_path() %s -> %d -> %s\n", path, offset, buf); + verbose_printf("get_path() %s -> %d -> %s\n", path, offset, + len >= 0 ? buf : ""); if (buflen <= pathlen) { if (len != -FDT_ERR_NOSPACE) diff -Nru device-tree-compiler-1.4.5/tests/.gitignore device-tree-compiler-1.4.7/tests/.gitignore --- device-tree-compiler-1.4.5/tests/.gitignore 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/.gitignore 2018-07-23 03:00:50.000000000 +0000 @@ -4,10 +4,13 @@ tmp.* /add_subnode_with_nops /addr_size_cells +/addr_size_cells2 /appendprop[12] /asm_tree_dump /boot-cpuid /char_literal +/check_full +/check_header /check_path /del_node /del_property @@ -58,6 +61,9 @@ /subnode_offset /supernode_atdepth_offset /sw_tree1 +/sw_states /truncated_property +/truncated_string +/truncated_memrsv /utilfdt_test /value-labels diff -Nru device-tree-compiler-1.4.5/tests/Makefile.tests device-tree-compiler-1.4.7/tests/Makefile.tests --- device-tree-compiler-1.4.5/tests/Makefile.tests 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/Makefile.tests 2018-07-23 03:00:50.000000000 +0000 @@ -9,9 +9,10 @@ sized_cells \ notfound \ addr_size_cells \ + addr_size_cells2 \ stringlist \ setprop_inplace nop_property nop_node \ - sw_tree1 \ + sw_tree1 sw_states \ move_and_save mangle-layout nopulate \ open_pack rw_tree1 set_name setprop del_property del_node \ appendprop1 appendprop2 propname_escapes \ @@ -26,10 +27,10 @@ property_iterate \ subnode_iterate \ overlay overlay_bad_fixup \ - check_path + check_path check_header check_full LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%) -LIBTREE_TESTS_L = truncated_property +LIBTREE_TESTS_L = truncated_property truncated_string truncated_memrsv LIBTREE_TESTS = $(LIBTREE_TESTS_L:%=$(TESTS_PREFIX)%) DL_LIB_TESTS_L = asm_tree_dump value-labels @@ -54,9 +55,12 @@ $(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_archive) +# Not necessary on all platforms; allow -ldl to be excluded instead of forcing +# other platforms to patch it out. +LIBDL = -ldl $(DL_LIB_TESTS): %: %.o $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_archive) @$(VECHO) LD [libdl] $@ - $(LINK.c) -o $@ $^ -ldl + $(LINK.c) -o $@ $^ $(LIBDL) $(LIBTREE_TESTS): %: $(TESTS_PREFIX)testutils.o $(TESTS_PREFIX)trees.o \ util.o $(LIBFDT_archive) diff -Nru device-tree-compiler-1.4.5/tests/mangle-layout.c device-tree-compiler-1.4.7/tests/mangle-layout.c --- device-tree-compiler-1.4.5/tests/mangle-layout.c 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/mangle-layout.c 2018-07-23 03:00:50.000000000 +0000 @@ -44,13 +44,9 @@ static void new_header(struct bufstate *buf, int version, const void *fdt) { - int hdrsize; + int hdrsize = fdt_header_size_(version); - if (version == 16) - hdrsize = FDT_V16_SIZE; - else if (version == 17) - hdrsize = FDT_V17_SIZE; - else + if ((version != 16) && (version != 17)) CONFIG("Bad version %d", version); expand_buf(buf, hdrsize); diff -Nru device-tree-compiler-1.4.5/tests/mangle-layout.supp device-tree-compiler-1.4.7/tests/mangle-layout.supp --- device-tree-compiler-1.4.5/tests/mangle-layout.supp 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/mangle-layout.supp 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -{ - uninitialized alignment gaps can be dumped to output - Memcheck:Param - write(buf) - obj:/lib/ld-*.so - fun:main -} diff -Nru device-tree-compiler-1.4.5/tests/node_check_compatible.c device-tree-compiler-1.4.7/tests/node_check_compatible.c --- device-tree-compiler-1.4.5/tests/node_check_compatible.c 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/node_check_compatible.c 2018-07-23 03:00:50.000000000 +0000 @@ -45,6 +45,23 @@ FAIL("%s is not compatible with \"%s\"", path, compat); } +static void check_not_compatible(const void *fdt, const char *path, + const char *compat) +{ + int offset, err; + + offset = fdt_path_offset(fdt, path); + if (offset < 0) + FAIL("fdt_path_offset(%s): %s", path, fdt_strerror(offset)); + + err = fdt_node_check_compatible(fdt, offset, compat); + if (err < 0) + FAIL("fdt_node_check_compatible(%s): %s", path, + fdt_strerror(err)); + if (err == 0) + FAIL("%s is incorrectly compatible with \"%s\"", path, compat); +} + int main(int argc, char *argv[]) { void *fdt; @@ -55,8 +72,10 @@ check_compatible(fdt, "/", "test_tree1"); check_compatible(fdt, "/subnode@1/subsubnode", "subsubnode1"); check_compatible(fdt, "/subnode@1/subsubnode", "subsubnode"); + check_not_compatible(fdt, "/subnode@1/subsubnode", "subsubnode2"); check_compatible(fdt, "/subnode@2/subsubnode", "subsubnode2"); check_compatible(fdt, "/subnode@2/subsubnode", "subsubnode"); + check_not_compatible(fdt, "/subnode@2/subsubnode", "subsubnode1"); PASS(); } diff -Nru device-tree-compiler-1.4.5/tests/omit-no-ref.dts device-tree-compiler-1.4.7/tests/omit-no-ref.dts --- device-tree-compiler-1.4.5/tests/omit-no-ref.dts 1970-01-01 00:00:00.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/omit-no-ref.dts 2018-07-23 03:00:50.000000000 +0000 @@ -0,0 +1,26 @@ +/dts-v1/; + +/ { + test-phandle = <&node3>; + test-path = &node4; + + /omit-if-no-ref/ node1: node1 { + bar = <0xdeadbeef>; + }; + + node2: node2 { + foo = <0x42>; + }; + + node3: node3 { + test = "test"; + }; + + node4: node4 { + test; + }; +}; + +/omit-if-no-ref/ &node2; +/omit-if-no-ref/ &node3; +/omit-if-no-ref/ &node4; diff -Nru device-tree-compiler-1.4.5/tests/open_pack.supp device-tree-compiler-1.4.7/tests/open_pack.supp --- device-tree-compiler-1.4.5/tests/open_pack.supp 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/open_pack.supp 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -{ - opened blob dumps uninitialized data - Memcheck:Param - write(buf) - obj:/lib/ld-*.so - fun:main -} diff -Nru device-tree-compiler-1.4.5/tests/overlay_overlay_bypath.dts device-tree-compiler-1.4.7/tests/overlay_overlay_bypath.dts --- device-tree-compiler-1.4.5/tests/overlay_overlay_bypath.dts 1970-01-01 00:00:00.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/overlay_overlay_bypath.dts 2018-07-23 03:00:50.000000000 +0000 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016 NextThing Co + * Copyright (c) 2016 Free Electrons + * Copyright (c) 2016 Konsulko Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/dts-v1/; +/plugin/; + +/* Test that we can change an int by another */ +&{/test-node} { + test-int-property = <43>; +}; + +/* Test that we can replace a string by a longer one */ +&{/test-node} { + test-str-property = "foobar"; +}; + +/* Test that we add a new property */ +&{/test-node} { + test-str-property-2 = "foobar2"; +}; + +/* Test that we add a new node (by phandle) */ +&{/test-node} { + new-node { + new-property; + }; +}; + +&{/} { + local: new-local-node { + new-property; + }; +}; + +&{/} { + test-several-phandle = <&local>, <&local>; +}; + +&{/test-node} { + sub-test-node { + new-sub-test-property; + }; +}; diff -Nru device-tree-compiler-1.4.5/tests/overlay_overlay.dts device-tree-compiler-1.4.7/tests/overlay_overlay.dts --- device-tree-compiler-1.4.5/tests/overlay_overlay.dts 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/overlay_overlay.dts 2018-07-23 03:00:50.000000000 +0000 @@ -9,78 +9,44 @@ /dts-v1/; /plugin/; -/ { - /* Test that we can change an int by another */ - fragment@0 { - target = <&test>; - - __overlay__ { - test-int-property = <43>; - }; - }; - - /* Test that we can replace a string by a longer one */ - fragment@1 { - target = <&test>; - - __overlay__ { - test-str-property = "foobar"; - }; - }; - - /* Test that we add a new property */ - fragment@2 { - target = <&test>; - - __overlay__ { - test-str-property-2 = "foobar2"; - }; - }; +/* Test that we can change an int by another */ +&test { + test-int-property = <43>; +}; - /* Test that we add a new node (by phandle) */ - fragment@3 { - target = <&test>; - - __overlay__ { - new-node { - new-property; - }; - }; - }; +/* Test that we can replace a string by a longer one */ +&test { + test-str-property = "foobar"; +}; - fragment@5 { - target = <&test>; +/* Test that we add a new property */ +&test { + test-str-property-2 = "foobar2"; +}; - __overlay__ { - local: new-local-node { - new-property; - }; - }; +/* Test that we add a new node (by phandle) */ +&test { + new-node { + new-property; }; +}; - fragment@6 { - target = <&test>; - - __overlay__ { - test-phandle = <&test>, <&local>; - }; +&test { + local: new-local-node { + new-property; }; +}; - fragment@7 { - target = <&test>; - - __overlay__ { - test-several-phandle = <&local>, <&local>; - }; - }; +&test { + test-phandle = <&test>, <&local>; +}; - fragment@8 { - target = <&test>; +&test { + test-several-phandle = <&local>, <&local>; +}; - __overlay__ { - sub-test-node { - new-sub-test-property; - }; - }; +&test { + sub-test-node { + new-sub-test-property; }; }; diff -Nru device-tree-compiler-1.4.5/tests/overlay_overlay_manual_fixups.dts device-tree-compiler-1.4.7/tests/overlay_overlay_manual_fixups.dts --- device-tree-compiler-1.4.5/tests/overlay_overlay_manual_fixups.dts 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/overlay_overlay_manual_fixups.dts 2018-07-23 03:00:50.000000000 +0000 @@ -50,7 +50,7 @@ }; }; - fragment@5 { + fragment@4 { target = <0xffffffff /*&test*/>; __overlay__ { @@ -60,7 +60,7 @@ }; }; - fragment@6 { + fragment@5 { target = <0xffffffff /*&test*/>; __overlay__ { @@ -68,7 +68,7 @@ }; }; - fragment@7 { + fragment@6 { target = <0xffffffff /*&test*/>; __overlay__ { @@ -76,7 +76,7 @@ }; }; - fragment@8 { + fragment@7 { target = <0xffffffff /*&test*/>; __overlay__ { @@ -86,27 +86,27 @@ }; }; + __fixups__ { + test = "/fragment@0:target:0", + "/fragment@1:target:0", + "/fragment@2:target:0", + "/fragment@3:target:0", + "/fragment@4:target:0", + "/fragment@5:target:0", + "/fragment@5/__overlay__:test-phandle:0", + "/fragment@6:target:0", + "/fragment@7:target:0"; + }; __local_fixups__ { - fragment@6 { + fragment@5 { __overlay__ { test-phandle = <4>; }; }; - fragment@7 { + fragment@6 { __overlay__ { test-several-phandle = <0 4>; }; }; }; - __fixups__ { - test = "/fragment@0:target:0", - "/fragment@1:target:0", - "/fragment@2:target:0", - "/fragment@3:target:0", - "/fragment@5:target:0", - "/fragment@6:target:0", - "/fragment@6/__overlay__:test-phandle:0", - "/fragment@7:target:0", - "/fragment@8:target:0"; - }; }; diff -Nru device-tree-compiler-1.4.5/tests/overlay_overlay_nosugar.dts device-tree-compiler-1.4.7/tests/overlay_overlay_nosugar.dts --- device-tree-compiler-1.4.5/tests/overlay_overlay_nosugar.dts 1970-01-01 00:00:00.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/overlay_overlay_nosugar.dts 2018-07-23 03:00:50.000000000 +0000 @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2016 NextThing Co + * Copyright (c) 2016 Free Electrons + * Copyright (c) 2016 Konsulko Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/dts-v1/; +/plugin/; + +/ { + /* Test that we can change an int by another */ + fragment@0 { + target = <&test>; + + __overlay__ { + test-int-property = <43>; + }; + }; + + /* Test that we can replace a string by a longer one */ + fragment@1 { + target = <&test>; + + __overlay__ { + test-str-property = "foobar"; + }; + }; + + /* Test that we add a new property */ + fragment@2 { + target = <&test>; + + __overlay__ { + test-str-property-2 = "foobar2"; + }; + }; + + /* Test that we add a new node (by phandle) */ + fragment@3 { + target = <&test>; + + __overlay__ { + new-node { + new-property; + }; + }; + }; + + fragment@5 { + target = <&test>; + + __overlay__ { + local: new-local-node { + new-property; + }; + }; + }; + + fragment@6 { + target = <&test>; + + __overlay__ { + test-phandle = <&test>, <&local>; + }; + }; + + fragment@7 { + target = <&test>; + + __overlay__ { + test-several-phandle = <&local>, <&local>; + }; + }; + + fragment@8 { + target = <&test>; + + __overlay__ { + sub-test-node { + new-sub-test-property; + }; + }; + }; +}; diff -Nru device-tree-compiler-1.4.5/tests/pci-bridge-bad1.dts device-tree-compiler-1.4.7/tests/pci-bridge-bad1.dts --- device-tree-compiler-1.4.5/tests/pci-bridge-bad1.dts 1970-01-01 00:00:00.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/pci-bridge-bad1.dts 2018-07-23 03:00:50.000000000 +0000 @@ -0,0 +1,16 @@ +/dts-v1/; + +/ { + compatible = "example,pci-bridge-ok"; + #address-cells = < 2 >; + #size-cells = < 2 >; + abadname@0 { + device_type = "pci"; + compatible = "example,pci-bridge"; + #address-cells = < 3 >; + #size-cells = < 2 >; + reg = <0 0 0 0x1000>; + bus-range = <0 0xff>; + ranges = <0 0 0 0 0 0 0x10000>; + }; +}; diff -Nru device-tree-compiler-1.4.5/tests/pci-bridge-bad2.dts device-tree-compiler-1.4.7/tests/pci-bridge-bad2.dts --- device-tree-compiler-1.4.5/tests/pci-bridge-bad2.dts 1970-01-01 00:00:00.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/pci-bridge-bad2.dts 2018-07-23 03:00:50.000000000 +0000 @@ -0,0 +1,16 @@ +/dts-v1/; + +/ { + compatible = "example,pci-bridge-ok"; + #address-cells = < 2 >; + #size-cells = < 2 >; + p@0 { + device_type = "pci"; + compatible = "example,pci-bridge"; + #address-cells = < 3 >; + #size-cells = < 2 >; + reg = <0 0 0 0x1000>; + bus-range = <0 0xff>; + ranges = <0 0 0 0 0 0 0x10000>; + }; +}; diff -Nru device-tree-compiler-1.4.5/tests/pci-bridge-ok.dts device-tree-compiler-1.4.7/tests/pci-bridge-ok.dts --- device-tree-compiler-1.4.5/tests/pci-bridge-ok.dts 1970-01-01 00:00:00.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/pci-bridge-ok.dts 2018-07-23 03:00:50.000000000 +0000 @@ -0,0 +1,25 @@ +/dts-v1/; + +/ { + compatible = "example,pci-bridge-ok"; + #address-cells = < 2 >; + #size-cells = < 2 >; + pci@0 { + device_type = "pci"; + compatible = "example,pci-bridge"; + #address-cells = < 3 >; + #size-cells = < 2 >; + reg = <0 0 0 0x1000>; + bus-range = <0 0xff>; + ranges = <0 0 0 0 0 0 0x10000>; + }; + pcie@10000000000 { + device_type = "pci"; + compatible = "example,pcie-bridge"; + #address-cells = < 3 >; + #size-cells = < 2 >; + reg = <0x10 0x00000000 0 0x1000>; + bus-range = <0 0xff>; + ranges = <0 0 0 0 0 0 0x10000>; + }; +}; diff -Nru device-tree-compiler-1.4.5/tests/pylibfdt_tests.py device-tree-compiler-1.4.7/tests/pylibfdt_tests.py --- device-tree-compiler-1.4.5/tests/pylibfdt_tests.py 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/pylibfdt_tests.py 2018-07-23 03:00:50.000000000 +0000 @@ -49,13 +49,43 @@ # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # +import struct import sys import types import unittest sys.path.insert(0, '../pylibfdt') import libfdt -from libfdt import FdtException, QUIET_NOTFOUND, QUIET_ALL +from libfdt import Fdt, FdtSw, FdtException, QUIET_NOTFOUND, QUIET_ALL + +TEST_ADDR_1H = 0xdeadbeef +TEST_ADDR_1L = 0x00000000 +TEST_ADDR_1 = (TEST_ADDR_1H << 32) | TEST_ADDR_1L +TEST_ADDR_1 = 0x8000000000000000 +TEST_SIZE_1H = 0x00000000 +TEST_SIZE_1L = 0x00100000 +TEST_SIZE_1 = (TEST_SIZE_1H << 32) | TEST_SIZE_1L +TEST_ADDR_2H = 0 +TEST_ADDR_2L = 123456789 +TEST_ADDR_2 = (TEST_ADDR_2H << 32) | TEST_ADDR_2L +TEST_SIZE_2H = 0 +TEST_SIZE_2L = 010000 +TEST_SIZE_2 = (TEST_SIZE_2H << 32) | TEST_SIZE_2L + +TEST_VALUE_1 = 0xdeadbeef +TEST_VALUE_2 = 123456789 + +TEST_VALUE64_1H = 0xdeadbeef +TEST_VALUE64_1L = 0x01abcdef +TEST_VALUE64_1 = (TEST_VALUE64_1H << 32) | TEST_VALUE64_1L + +PHANDLE_1 = 0x2000 +PHANDLE_2 = 0x2001 + +TEST_STRING_1 = 'hello world' +TEST_STRING_2 = 'hi world' +TEST_STRING_3 = u'unicode ' + unichr(467) + def get_err(err_code): """Convert an error code into an error message @@ -79,8 +109,8 @@ """ return libfdt.Fdt(open(fname).read()) -class PyLibfdtTests(unittest.TestCase): - """Test class for pylibfdt +class PyLibfdtBasicTests(unittest.TestCase): + """Test class for basic pylibfdt access functions Properties: fdt: Device tree file used for testing @@ -89,6 +119,7 @@ def setUp(self): """Read in the device tree we use for testing""" self.fdt = _ReadFdt('test_tree1.dtb') + self.fdt2 = _ReadFdt('test_props.dtb') def GetPropList(self, node_path): """Read a list of properties from a node @@ -190,7 +221,7 @@ poffset = self.fdt.first_property_offset(root) prop = self.fdt.get_property_by_offset(poffset) self.assertEquals(prop.name, 'compatible') - self.assertEquals(prop.value, 'test_tree1\0') + self.assertEquals(prop, 'test_tree1\0') with self.assertRaises(FdtException) as e: self.fdt.get_property_by_offset(-2) @@ -220,6 +251,24 @@ self.assertEquals(libfdt.strerror(-libfdt.NOTFOUND), 'FDT_ERR_NOTFOUND') + def testNextNodeOffset(self): + """Check that we can walk through nodes""" + node_list = [] + node = 0 + depth = 0 + while depth >= 0: + node_list.append([depth, self.fdt.get_name(node)]) + node, depth = self.fdt.next_node(node, depth, (libfdt.BADOFFSET,)) + self.assertEquals(node_list, [ + [0, ''], + [1, 'subnode@1'], + [2, 'subsubnode'], + [2, 'ss1'], + [1, 'subnode@2'], + [2, 'subsubnode@0'], + [2, 'ss2'], + ]) + def testFirstNextSubnodeOffset(self): """Check that we can walk through subnodes""" node_list = [] @@ -257,8 +306,16 @@ def testHeader(self): """Test that we can access the header values""" + self.assertEquals(self.fdt.magic(), 0xd00dfeed) self.assertEquals(self.fdt.totalsize(), len(self.fdt._fdt)) self.assertEquals(self.fdt.off_dt_struct(), 88) + self.assertEquals(self.fdt.off_dt_strings(), 652) + self.assertEquals(self.fdt.off_mem_rsvmap(), 40) + self.assertEquals(self.fdt.version(), 17) + self.assertEquals(self.fdt.last_comp_version(), 16) + self.assertEquals(self.fdt.boot_cpuid_phys(), 0) + self.assertEquals(self.fdt.size_dt_strings(), 105) + self.assertEquals(self.fdt.size_dt_struct(), 564) def testPack(self): """Test that we can pack the tree after deleting something""" @@ -268,6 +325,7 @@ self.assertEquals(orig_size, self.fdt.totalsize()) self.assertEquals(self.fdt.pack(), 0) self.assertTrue(self.fdt.totalsize() < orig_size) + self.assertEquals(self.fdt.totalsize(), len(self.fdt.as_bytearray())) def testBadPropertyOffset(self): """Test that bad property offsets are detected""" @@ -329,6 +387,208 @@ node2 = self.fdt.path_offset('/subnode@2/subsubnode@0') self.assertEquals(node2, self.fdt.node_offset_by_phandle(0x2001)) + def get_prop(self, name): + return self.fdt2.getprop(0, name) + + def testGetIntProperties(self): + """Test that we can access properties as integers""" + self.assertEquals(0xdeadbeef, self.get_prop("prop-hex32").as_uint32()) + self.assertEquals(123, self.get_prop("prop-uint32").as_uint32()) + self.assertEquals(-2, self.get_prop("prop-int32").as_int32()) + self.assertEquals(9223372036854775807, + self.get_prop("prop-uint64").as_uint64()) + self.assertEquals(-2, self.get_prop("prop-int64").as_int64()) + + def testReserveMap(self): + """Test that we can access the memory reserve map""" + self.assertEquals(2, self.fdt.num_mem_rsv()) + self.assertEquals([ 0xdeadbeef00000000, 0x100000], + self.fdt.get_mem_rsv(0)) + self.assertEquals([123456789, 010000], self.fdt.get_mem_rsv(1)) + + def testEmpty(self): + """Test that we can create an empty tree""" + self.assertEquals(-libfdt.NOSPACE, + Fdt.create_empty_tree(1, (libfdt.NOSPACE,))) + fdt = Fdt.create_empty_tree(128) + self.assertEquals(128, fdt.totalsize()) + + def testOpenInto(self): + """Test that we can resize a tree""" + fdt = Fdt.create_empty_tree(128) + self.assertEquals(128, fdt.totalsize()) + fdt.resize(256) + self.assertEquals(256, fdt.totalsize()) + fdt.pack() + self.assertTrue(fdt.totalsize() < 128) + + def testSetProp(self): + """Test that we can update and create properties""" + node = self.fdt.path_offset('/subnode@1') + self.fdt.setprop(node, 'compatible', TEST_STRING_1) + self.assertEquals(TEST_STRING_1, self.fdt.getprop(node, 'compatible')) + + # Check that this property is missing, and that we don't have space to + # add it + self.assertEquals(-libfdt.NOTFOUND, + self.fdt.getprop(node, 'missing', QUIET_NOTFOUND)) + self.assertEquals(-libfdt.NOSPACE, + self.fdt.setprop(node, 'missing', TEST_STRING_1, + quiet=(libfdt.NOSPACE,))) + + # Expand the device tree so we now have room + self.fdt.resize(self.fdt.totalsize() + 50) + self.fdt.setprop(node, 'missing', TEST_STRING_1) + self.assertEquals(TEST_STRING_1, self.fdt.getprop(node, 'missing')) + + def testSetPropU32(self): + """Test that we can update and create integer properties""" + node = 0 + prop = 'prop-int' + self.fdt.setprop_u32(node, prop, TEST_VALUE_1) + self.assertEquals(struct.pack('>I', TEST_VALUE_1), + self.fdt.getprop(node, prop)) + + def testSetPropU64(self): + """Test that we can update and create integer properties""" + node = 0 + prop = 'prop-int64' + self.fdt.setprop_u64(node, prop, TEST_VALUE64_1) + self.assertEquals(struct.pack('>Q', TEST_VALUE64_1), + self.fdt.getprop(node, prop)) + + def testSetPropStr(self): + """Test that we can set a property to a particular string""" + node = 0 + prop = 'prop-str' + self.assertEquals(TEST_STRING_1, self.fdt.getprop(node, prop).as_str()) + self.fdt.setprop_str(node, prop, TEST_STRING_2) + self.assertEquals(TEST_STRING_2, self.fdt.getprop(node, prop).as_str()) + with self.assertRaises(ValueError) as e: + self.fdt.getprop(node, 'prop-int').as_str() + self.assertIn('lacks nul termination', str(e.exception)) + + node2 = self.fdt.path_offset('/subnode@1/subsubnode') + with self.assertRaises(ValueError) as e: + self.fdt.getprop(node2, 'compatible').as_str() + self.assertIn('embedded nul', str(e.exception)) + + # Expand the device tree so we now have room + self.fdt.resize(self.fdt.totalsize() + 50) + prop = 'prop-unicode' + self.fdt.setprop_str(node, prop, TEST_STRING_3) + self.assertEquals(TEST_STRING_3, + self.fdt.getprop(node, prop).as_str()) + + def testSetName(self): + """Test that we can update a node name""" + node = self.fdt.path_offset('/subnode@1') + old_val = self.fdt.get_name(node) + self.fdt.set_name(node, 'test') + self.assertEquals('test', self.fdt.get_name(node)) + + with self.assertRaises(ValueError) as e: + self.fdt.set_name(node, 'some\0name') + self.assertIn('embedded nul', str(e.exception)) + + with self.assertRaises(ValueError) as e: + self.fdt.set_name(node, 'name\0') + self.assertIn('embedded nul', str(e.exception)) + + +class PyLibfdtSwTests(unittest.TestCase): + """Test class for pylibfdt sequential-write DT creation + """ + def assertOk(self, err_code): + self.assertEquals(0, err_code) + + def testCreate(self): + # First check the minimum size and also the FdtSw() constructor + with self.assertRaisesRegexp(FdtException, get_err(libfdt.NOSPACE)): + self.assertEquals(-libfdt.NOSPACE, FdtSw(3)) + + sw = FdtSw() + sw.add_reservemap_entry(TEST_ADDR_1, TEST_SIZE_1) + sw.add_reservemap_entry(TEST_ADDR_2, TEST_SIZE_2) + sw.finish_reservemap() + + sw.begin_node('') + sw.property_string('compatible', 'test_tree1') + sw.property_u32('prop-int', TEST_VALUE_1) + + sw.property_u32('prop-int', TEST_VALUE_1) + sw.property_u64('prop-int64', TEST_VALUE64_1) + sw.property_string('prop-str', TEST_STRING_1) + sw.property_u32('#address-cells', 1) + sw.property_u32('#size-cells', 0) + + sw.begin_node('subnode@1') + sw.property_string('compatible', 'subnode1') + sw.property_u32('reg', 1) + sw.property_cell('prop-int', TEST_VALUE_1) + sw.begin_node('subsubnode') + sw.property('compatible', 'subsubnode1\0subsubnode') + sw.property_cell('prop-int', TEST_VALUE_1) + sw.end_node() + sw.begin_node('ss1') + sw.end_node() + sw.end_node() + + for i in range(2, 11): + with sw.add_node('subnode@%d' % i): + sw.property_u32('reg', 2) + sw.property_cell('linux,phandle', PHANDLE_1) + sw.property_cell('prop-int', TEST_VALUE_2) + sw.property_u32('#address-cells', 1) + sw.property_u32('#size-cells', 0) + with sw.add_node('subsubnode@0'): + sw.property_u32('reg', 0) + sw.property_cell('phandle', PHANDLE_2) + sw.property('compatible', 'subsubnode2\0subsubnode') + sw.property_cell('prop-int', TEST_VALUE_2) + with sw.add_node('ss2'): + pass + sw.end_node() + + fdt = sw.as_fdt() + self.assertEqual(2, fdt.num_mem_rsv()) + self.assertEqual([TEST_ADDR_1, TEST_SIZE_1], fdt.get_mem_rsv(0)) + + # Make sure we can add a few more things + with sw.add_node('another'): + sw.property_u32('reg', 3) + + # Make sure we can read from the tree too + node = sw.path_offset('/subnode@1') + self.assertEqual('subnode1' + chr(0), sw.getprop(node, 'compatible')) + + # Make sure we did at least two resizes + self.assertTrue(len(fdt.as_bytearray()) > FdtSw.INC_SIZE * 2) + + +class PyLibfdtRoTests(unittest.TestCase): + """Test class for read-only pylibfdt access functions + + This just tests a few simple cases. Most of the tests are in + PyLibfdtBasicTests. + + Properties: + fdt: Device tree file used for testing + """ + + def setUp(self): + """Read in the device tree we use for testing""" + self.fdt = libfdt.FdtRo(open('test_tree1.dtb').read()) + + def testAccess(self): + """Basic sanity check for the FdtRo class""" + node = self.fdt.path_offset('/subnode@1') + self.assertEqual('subnode1' + chr(0), + self.fdt.getprop(node, 'compatible')) + node = self.fdt.first_subnode(node) + self.assertEqual('this is a placeholder string\0string2\0', + self.fdt.getprop(node, 'placeholder')) + if __name__ == "__main__": unittest.main() diff -Nru device-tree-compiler-1.4.5/tests/run_tests.sh device-tree-compiler-1.4.7/tests/run_tests.sh --- device-tree-compiler-1.4.5/tests/run_tests.sh 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/run_tests.sh 2018-07-23 03:00:50.000000000 +0000 @@ -6,6 +6,18 @@ CC=gcc fi +# stat differs between platforms +if [ -z "$STATSZ" ]; then + stat --version 2>/dev/null | grep -q 'GNU' + GNUSTAT=$? + if [ "$GNUSTAT" -ne 0 ]; then + # Assume BSD stat if we can't detect as GNU stat + STATSZ="stat -f %Uz" + else + STATSZ="stat -c %s" + fi +fi + export QUIET_TEST=1 STOP_ON_FAIL=0 @@ -114,7 +126,7 @@ # $2: align base check_align () { shorten_echo "check_align $@: " - local size=$(stat -c %s "$1") + local size=$($STATSZ "$1") local align="$2" ( if [ $(($size % $align)) -eq 0 ] ;then @@ -205,6 +217,12 @@ run_test overlay overlay_base_manual_symbols.test.dtb overlay_overlay_manual_fixups.test.dtb + # test simplified plugin syntax + run_dtc_test -@ -I dts -O dtb -o overlay_overlay_simple.dtb overlay_overlay_simple.dts + + # verify non-generation of local fixups + run_test check_path overlay_overlay_simple.dtb not-exists "/__local_fixups__" + # Bad fixup tests for test in $BAD_FIXUP_TREES; do tree="overlay_bad_fixup_$test" @@ -221,12 +239,37 @@ run_test check_path overlay_base.test.dtb not-exists "/__fixups__" run_test check_path overlay_base.test.dtb not-exists "/__local_fixups__" + # With syntactic sugar run_dtc_test -I dts -O dtb -o overlay_overlay.test.dtb overlay_overlay.dts run_test check_path overlay_overlay.test.dtb not-exists "/__symbols__" run_test check_path overlay_overlay.test.dtb exists "/__fixups__" run_test check_path overlay_overlay.test.dtb exists "/__local_fixups__" + # Without syntactic sugar + run_dtc_test -I dts -O dtb -o overlay_overlay_nosugar.test.dtb overlay_overlay.dts + run_test check_path overlay_overlay_nosugar.test.dtb not-exists "/__symbols__" + run_test check_path overlay_overlay_nosugar.test.dtb exists "/__fixups__" + run_test check_path overlay_overlay_nosugar.test.dtb exists "/__local_fixups__" + + # Using target-path + run_dtc_test -I dts -O dtb -o overlay_overlay_bypath.test.dtb overlay_overlay_bypath.dts + run_test check_path overlay_overlay_bypath.test.dtb not-exists "/__symbols__" + run_test check_path overlay_overlay_bypath.test.dtb not-exists "/__fixups__" + run_test check_path overlay_overlay_bypath.test.dtb exists "/__local_fixups__" + + # Check building works the same as manual constructions + run_test dtbs_equal_ordered overlay_overlay.test.dtb overlay_overlay_nosugar.test.dtb + + run_dtc_test -I dts -O dtb -o overlay_overlay_manual_fixups.test.dtb overlay_overlay_manual_fixups.dts + run_test dtbs_equal_ordered overlay_overlay.test.dtb overlay_overlay_manual_fixups.test.dtb + + run_dtc_test -I dts -O dtb -o overlay_overlay_no_fixups.test.dtb overlay_overlay_no_fixups.dts + run_test dtbs_equal_ordered overlay_overlay_bypath.test.dtb overlay_overlay_no_fixups.test.dtb + + # Check we can actually apply the result + run_dtc_test -I dts -O dtb -o overlay_base_no_symbols.test.dtb overlay_base.dts run_test overlay overlay_base.test.dtb overlay_overlay.test.dtb + run_test overlay overlay_base_no_symbols.test.dtb overlay_overlay_bypath.test.dtb # test plugin source to dtb and back run_dtc_test -I dtb -O dts -o overlay_overlay_decompile.test.dts overlay_overlay.test.dtb @@ -293,6 +336,8 @@ run_dtc_test -I dts -O dtb -o addresses.test.dtb addresses.dts run_test addr_size_cells addresses.test.dtb + run_dtc_test -I dts -O dtb -o addresses2.test.dtb empty.dts + run_test addr_size_cells2 addresses2.test.dtb run_dtc_test -I dts -O dtb -o stringlist.test.dtb stringlist.dts run_test stringlist stringlist.test.dtb @@ -302,9 +347,10 @@ tree1_tests sw_tree1.test.dtb tree1_tests unfinished_tree1.test.dtb run_test dtbs_equal_ordered test_tree1.dtb sw_tree1.test.dtb + run_test sw_states # Resizing tests - for mode in resize realloc; do + for mode in resize realloc newalloc; do run_test sw_tree1 $mode tree1_tests sw_tree1.test.dtb tree1_tests unfinished_tree1.test.dtb @@ -371,6 +417,8 @@ # Tests for behaviour on various sorts of corrupted trees run_test truncated_property + run_test truncated_string + run_test truncated_memrsv # Check aliases support in fdt_path_offset run_dtc_test -I dts -O dtb -o aliases.dtb aliases.dts @@ -397,6 +445,17 @@ run_wrap_error_test $DTC nul-in-line-info2.dts run_wrap_error_test $DTC -I dtb -O dts -o /dev/null ovf_size_strings.dtb + + run_test check_header test_tree1.dtb + + # check full tests + for good in test_tree1.dtb; do + run_test check_full $good + done + for bad in truncated_property.dtb truncated_string.dtb \ + truncated_memrsv.dtb; do + run_test check_full -n $bad + done } dtc_tests () { @@ -494,6 +553,13 @@ run_test dtbs_equal_ordered $tree odts_$tree.test.dtb done + # Check -Odts preserving type information + for tree in type-preservation.dts; do + run_dtc_test -I dts -O dts -o $tree.test.dts $tree + run_dtc_test -I dts -O dts $tree.test.dts + run_wrap_test cmp $tree $tree.test.dts + done + # Check version conversions for tree in test_tree1.dtb ; do for aver in 1 2 3 16 17; do @@ -525,6 +591,13 @@ run_dtc_test -I dts -O dtb -o dtc_tree1_delete.test.dtb test_tree1_delete.dts tree1_tests dtc_tree1_delete.test.dtb + # Check omit-if-no-ref functionality + run_dtc_test -I dts -O dtb -o omit-no-ref.test.dtb omit-no-ref.dts + run_test check_path omit-no-ref.test.dtb not-exists "/node1" + run_test check_path omit-no-ref.test.dtb not-exists "/node2" + run_test check_path omit-no-ref.test.dtb exists "/node3" + run_test check_path omit-no-ref.test.dtb exists "/node4" + run_dtc_test -I dts -O dts -o delete_reinstate_multilabel.dts.test.dts delete_reinstate_multilabel.dts run_wrap_test cmp delete_reinstate_multilabel.dts.test.dts delete_reinstate_multilabel_ref.dts @@ -540,7 +613,10 @@ check_tests bad-name-property.dts name_properties check_tests bad-ncells.dts address_cells_is_cell size_cells_is_cell interrupt_cells_is_cell - check_tests bad-string-props.dts device_type_is_string model_is_string status_is_string + check_tests bad-string-props.dts device_type_is_string model_is_string status_is_string label_is_string compatible_is_string_list names_is_string_list + check_tests bad-chosen.dts chosen_node_is_root + check_tests bad-chosen.dts chosen_node_bootargs + check_tests bad-chosen.dts chosen_node_stdout_path check_tests bad-reg-ranges.dts reg_format ranges_format check_tests bad-empty-ranges.dts ranges_format check_tests reg-ranges-root.dts reg_format ranges_format @@ -550,13 +626,17 @@ check_tests unit-addr-without-reg.dts unit_address_vs_reg check_tests unit-addr-leading-0x.dts unit_address_format check_tests unit-addr-leading-0s.dts unit_address_format + check_tests unit-addr-unique.dts unique_unit_address check_tests bad-phandle-cells.dts interrupts_extended_property check_tests bad-gpio.dts gpios_property + check_tests bad-graph.dts graph_child_address + check_tests bad-graph.dts graph_port + check_tests bad-graph.dts graph_endpoint run_sh_test dtc-checkfails.sh deprecated_gpio_property -- -Wdeprecated_gpio_property -I dts -O dtb bad-gpio.dts check_tests bad-interrupt-cells.dts interrupts_property run_sh_test dtc-checkfails.sh node_name_chars -- -I dtb -O dtb bad_node_char.dtb run_sh_test dtc-checkfails.sh node_name_format -- -I dtb -O dtb bad_node_format.dtb - run_sh_test dtc-checkfails.sh prop_name_chars -- -I dtb -O dtb bad_prop_char.dtb + run_sh_test dtc-checkfails.sh property_name_chars -- -I dtb -O dtb bad_prop_char.dtb run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label1.dts run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label2.dts @@ -568,6 +648,10 @@ run_test check_path test_tree1.dtb exists "/subnode@1" run_test check_path test_tree1.dtb not-exists "/subnode@10" + check_tests pci-bridge-ok.dts -n pci_bridge + check_tests pci-bridge-bad1.dts pci_bridge + check_tests pci-bridge-bad2.dts pci_bridge + # Check warning options run_sh_test dtc-checkfails.sh address_cells_is_cell interrupt_cells_is_cell -n size_cells_is_cell -- -Wno_size_cells_is_cell -I dts -O dtb bad-ncells.dts run_sh_test dtc-fails.sh -n test-warn-output.test.dtb -I dts -O dtb bad-ncells.dts @@ -704,7 +788,7 @@ text=lorem.txt # Allow just enough space for $text - run_dtc_test -O dtb -p $(stat -c %s $text) -o $dtb $dts + run_dtc_test -O dtb -p $($STATSZ $text) -o $dtb $dts # run_fdtput_test run_fdtput_test "a_model" $dtb / model -ts "a_model" @@ -723,7 +807,7 @@ run_fdtput_test "$(cat $text $text)" $dtb /randomnode blob -ts "$(cat $text $text)" # Start again with a fresh dtb - run_dtc_test -O dtb -p $(stat -c %s $text) -o $dtb $dts + run_dtc_test -O dtb -p $($STATSZ $text) -o $dtb $dts # Node creation run_wrap_error_test $DTPUT $dtb -c /baldrick sod @@ -751,7 +835,7 @@ run_wrap_test $DTPUT $dtb -cp /chosen/son # Start again with a fresh dtb - run_dtc_test -O dtb -p $(stat -c %s $text) -o $dtb $dts + run_dtc_test -O dtb -p $($STATSZ $text) -o $dtb $dts # Node delete run_wrap_test $DTPUT $dtb -c /chosen/node1 /chosen/node2 /chosen/node3 @@ -813,6 +897,7 @@ } pylibfdt_tests () { + run_dtc_test -I dts -O dtb -o test_props.dtb test_props.dts TMP=/tmp/tests.stderr.$$ python pylibfdt_tests.py -v 2> $TMP diff -Nru device-tree-compiler-1.4.5/tests/stringlist.c device-tree-compiler-1.4.7/tests/stringlist.c --- device-tree-compiler-1.4.5/tests/stringlist.c 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/stringlist.c 2018-07-23 03:00:50.000000000 +0000 @@ -60,10 +60,11 @@ FAIL("empty string not found in #address-cells: %d\n", err); /* - * fdt_get_string() can successfully extract strings from non-string - * properties. This is because it doesn't necessarily parse the whole - * property value, which would be necessary for it to determine if a - * valid string or string list is present. + * fdt_getprop_string() can successfully extract strings from + * non-string properties. This is because it doesn't + * necessarily parse the whole property value, which would be + * necessary for it to determine if a valid string or string + * list is present. */ } diff -Nru device-tree-compiler-1.4.5/tests/sw_states.c device-tree-compiler-1.4.7/tests/sw_states.c --- device-tree-compiler-1.4.5/tests/sw_states.c 1970-01-01 00:00:00.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/sw_states.c 2018-07-23 03:00:50.000000000 +0000 @@ -0,0 +1,140 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for error handling with sequential write states + * Copyright (C) 2018 David Gibson, Red Hat Inc. + * + * 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 +#include +#include +#include +#include + +#include + +#include "tests.h" +#include "testdata.h" + +#define SPACE 65536 + +#define CHECK_OK(code) \ + do { \ + verbose_printf(" OK: %s\n", #code); \ + err = (code); \ + if (err) \ + FAIL(#code ": %s", fdt_strerror(err)); \ + } while (0) + +#define CHECK_BADSTATE(code) \ + do { \ + verbose_printf("BAD: %s\n", #code); \ + err = (code); \ + if (err == 0) \ + FAIL(#code ": succeeded in bad state"); \ + else if (err != -FDT_ERR_BADSTATE) \ + FAIL(#code ": %s", fdt_strerror(err)); \ + } while (0) + +int main(int argc, char *argv[]) +{ + void *fdt = NULL; + int err; + + test_init(argc, argv); + + fdt = xmalloc(SPACE); + + err = fdt_create(fdt, SPACE); + if (err) + FAIL("fdt_create(): %s", fdt_strerror(err)); + + /* Memory reserve state */ + + CHECK_BADSTATE(fdt_begin_node(fdt, "")); + CHECK_BADSTATE(fdt_property_string(fdt, "bad-str", "TEST_STRING_1")); + CHECK_BADSTATE(fdt_end_node(fdt)); + CHECK_BADSTATE(fdt_finish(fdt)); + + CHECK_OK(fdt_add_reservemap_entry(fdt, TEST_ADDR_1, TEST_SIZE_1)); + CHECK_OK(fdt_add_reservemap_entry(fdt, TEST_ADDR_2, TEST_SIZE_2)); + + CHECK_BADSTATE(fdt_begin_node(fdt, "")); + CHECK_BADSTATE(fdt_property_string(fdt, "bad-str", "TEST_STRING_1")); + CHECK_BADSTATE(fdt_end_node(fdt)); + CHECK_BADSTATE(fdt_finish(fdt)); + + CHECK_OK(fdt_finish_reservemap(fdt)); + + /* Structure state */ + + CHECK_BADSTATE(fdt_add_reservemap_entry(fdt, TEST_ADDR_1, TEST_SIZE_1)); + CHECK_BADSTATE(fdt_finish_reservemap(fdt)); + + CHECK_OK(fdt_begin_node(fdt, "")); + CHECK_OK(fdt_property_string(fdt, "compatible", "test_tree1")); + CHECK_OK(fdt_property_u32(fdt, "prop-int", TEST_VALUE_1)); + CHECK_OK(fdt_property_u64(fdt, "prop-int64", TEST_VALUE64_1)); + CHECK_OK(fdt_property_string(fdt, "prop-str", TEST_STRING_1)); + CHECK_OK(fdt_property_u32(fdt, "#address-cells", 1)); + CHECK_OK(fdt_property_u32(fdt, "#size-cells", 0)); + + CHECK_OK(fdt_begin_node(fdt, "subnode@1")); + CHECK_OK(fdt_property_string(fdt, "compatible", "subnode1")); + CHECK_OK(fdt_property_u32(fdt, "reg", 1)); + CHECK_OK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_1)); + CHECK_OK(fdt_begin_node(fdt, "subsubnode")); + CHECK_OK(fdt_property(fdt, "compatible", "subsubnode1\0subsubnode", + 23)); + CHECK_OK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_1)); + CHECK_OK(fdt_end_node(fdt)); + CHECK_OK(fdt_begin_node(fdt, "ss1")); + CHECK_OK(fdt_end_node(fdt)); + CHECK_OK(fdt_end_node(fdt)); + + CHECK_OK(fdt_begin_node(fdt, "subnode@2")); + CHECK_OK(fdt_property_u32(fdt, "reg", 2)); + CHECK_OK(fdt_property_cell(fdt, "linux,phandle", PHANDLE_1)); + CHECK_OK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_2)); + CHECK_OK(fdt_property_u32(fdt, "#address-cells", 1)); + CHECK_OK(fdt_property_u32(fdt, "#size-cells", 0)); + CHECK_OK(fdt_begin_node(fdt, "subsubnode@0")); + CHECK_OK(fdt_property_u32(fdt, "reg", 0)); + CHECK_OK(fdt_property_cell(fdt, "phandle", PHANDLE_2)); + CHECK_OK(fdt_property(fdt, "compatible", "subsubnode2\0subsubnode", + 23)); + CHECK_OK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_2)); + CHECK_OK(fdt_end_node(fdt)); + CHECK_OK(fdt_begin_node(fdt, "ss2")); + CHECK_OK(fdt_end_node(fdt)); + + CHECK_OK(fdt_end_node(fdt)); + + CHECK_OK(fdt_end_node(fdt)); + + CHECK_OK(fdt_finish(fdt)); + + /* Completed state */ + + CHECK_BADSTATE(fdt_add_reservemap_entry(fdt, TEST_ADDR_1, TEST_SIZE_1)); + CHECK_BADSTATE(fdt_finish_reservemap(fdt)); + CHECK_BADSTATE(fdt_begin_node(fdt, "")); + CHECK_BADSTATE(fdt_property_string(fdt, "bad-str", "TEST_STRING_1")); + CHECK_BADSTATE(fdt_end_node(fdt)); + CHECK_BADSTATE(fdt_finish(fdt)); + + PASS(); +} diff -Nru device-tree-compiler-1.4.5/tests/sw_tree1.c device-tree-compiler-1.4.7/tests/sw_tree1.c --- device-tree-compiler-1.4.5/tests/sw_tree1.c 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/sw_tree1.c 2018-07-23 03:00:50.000000000 +0000 @@ -35,10 +35,13 @@ FIXED = 0, RESIZE, REALLOC, + NEWALLOC, } alloc_mode; static void realloc_fdt(void **fdt, size_t *size, bool created) { + int err; + switch (alloc_mode) { case FIXED: if (!(*fdt)) @@ -52,7 +55,10 @@ *fdt = xmalloc(SPACE); } else if (*size < SPACE) { *size += 1; - fdt_resize(*fdt, *fdt, *size); + err = fdt_resize(*fdt, *fdt, *size); + if (err < 0) + FAIL("fdt_resize() failed: %s", + fdt_strerror(err)); } else { FAIL("Ran out of space"); } @@ -61,9 +67,29 @@ case REALLOC: *size += 1; *fdt = xrealloc(*fdt, *size); - if (created) - fdt_resize(*fdt, *fdt, *size); + if (created) { + err = fdt_resize(*fdt, *fdt, *size); + if (err < 0) + FAIL("fdt_resize() failed: %s", + fdt_strerror(err)); + } + return; + + case NEWALLOC: { + void *buf; + + *size += 1; + buf = xmalloc(*size); + if (created) { + err = fdt_resize(*fdt, buf, *size); + if (err < 0) + FAIL("fdt_resize() failed: %s", + fdt_strerror(err)); + } + free(*fdt); + *fdt = buf; return; + } default: CONFIG("Bad allocation mode"); @@ -101,6 +127,9 @@ } else if (streq(argv[1], "realloc")) { alloc_mode = REALLOC; size = 0; + } else if (streq(argv[1], "newalloc")) { + alloc_mode = NEWALLOC; + size = 0; } else { char *endp; @@ -111,6 +140,8 @@ CONFIG("Bad allocation mode \"%s\" specified", argv[1]); } + } else { + CONFIG("sw_tree1 []"); } fdt = xmalloc(size); diff -Nru device-tree-compiler-1.4.5/tests/sw_tree1.supp device-tree-compiler-1.4.7/tests/sw_tree1.supp --- device-tree-compiler-1.4.5/tests/sw_tree1.supp 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/sw_tree1.supp 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -{ - allocation methods causes uninitialized data in alignment gap - Memcheck:Param - write(buf) - fun:__write_nocancel - fun:utilfdt_write_err - fun:save_blob - fun:main -} -{ - allocation methods causes uninitialized data in alignment gap - Memcheck:Param - write(buf) - fun:__write_nocancel - fun:utilfdt_write_err - fun:save_blob - fun:main -} diff -Nru device-tree-compiler-1.4.5/tests/testdata.h device-tree-compiler-1.4.7/tests/testdata.h --- device-tree-compiler-1.4.5/tests/testdata.h 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/testdata.h 2018-07-23 03:00:50.000000000 +0000 @@ -4,15 +4,25 @@ #define ASM_CONST_LL(x) (x##ULL) #endif -#define TEST_ADDR_1 ASM_CONST_LL(0xdeadbeef00000000) -#define TEST_SIZE_1 ASM_CONST_LL(0x100000) -#define TEST_ADDR_2 ASM_CONST_LL(123456789) -#define TEST_SIZE_2 ASM_CONST_LL(010000) +#define TEST_ADDR_1H ASM_CONST_LL(0xdeadbeef) +#define TEST_ADDR_1L ASM_CONST_LL(0x00000000) +#define TEST_ADDR_1 ((TEST_ADDR_1H << 32) | TEST_ADDR_1L) +#define TEST_SIZE_1H ASM_CONST_LL(0x00000000) +#define TEST_SIZE_1L ASM_CONST_LL(0x00100000) +#define TEST_SIZE_1 ((TEST_SIZE_1H << 32) | TEST_SIZE_1L) +#define TEST_ADDR_2H ASM_CONST_LL(0) +#define TEST_ADDR_2L ASM_CONST_LL(123456789) +#define TEST_ADDR_2 ((TEST_ADDR_2H << 32) | TEST_ADDR_2L) +#define TEST_SIZE_2H ASM_CONST_LL(0) +#define TEST_SIZE_2L ASM_CONST_LL(010000) +#define TEST_SIZE_2 ((TEST_SIZE_2H << 32) | TEST_SIZE_2L) #define TEST_VALUE_1 0xdeadbeef #define TEST_VALUE_2 123456789 -#define TEST_VALUE64_1 ASM_CONST_LL(0xdeadbeef01abcdef) +#define TEST_VALUE64_1H ASM_CONST_LL(0xdeadbeef) +#define TEST_VALUE64_1L ASM_CONST_LL(0x01abcdef) +#define TEST_VALUE64_1 ((TEST_VALUE64_1H << 32) | TEST_VALUE64_1L) #define PHANDLE_1 0x2000 #define PHANDLE_2 0x2001 @@ -31,10 +41,12 @@ #define TEST_CHAR5 '\xff' #ifndef __ASSEMBLY__ -extern struct fdt_header _test_tree1; -extern struct fdt_header _truncated_property; -extern struct fdt_header _bad_node_char; -extern struct fdt_header _bad_node_format; -extern struct fdt_header _bad_prop_char; -extern struct fdt_header _ovf_size_strings; +extern struct fdt_header test_tree1; +extern struct fdt_header truncated_property; +extern struct fdt_header bad_node_char; +extern struct fdt_header bad_node_format; +extern struct fdt_header bad_prop_char; +extern struct fdt_header ovf_size_strings; +extern struct fdt_header truncated_string; +extern struct fdt_header truncated_memrsv; #endif /* ! __ASSEMBLY */ diff -Nru device-tree-compiler-1.4.5/tests/test_props.dts device-tree-compiler-1.4.7/tests/test_props.dts --- device-tree-compiler-1.4.5/tests/test_props.dts 1970-01-01 00:00:00.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/test_props.dts 2018-07-23 03:00:50.000000000 +0000 @@ -0,0 +1,11 @@ +/dts-v1/; + +/ { + compatible = "test_props"; + prop-hex32 = <0xdeadbeef>; + prop-uint32 = <123>; + prop-int32 = <0xfffffffe>; + prop-hex64 = /bits/ 64 <0xdeadbeef01abcdef>; + prop-uint64 = /bits/ 64 <9223372036854775807>; + prop-int64 = /bits/ 64 <0xfffffffffffffffe>; +}; diff -Nru device-tree-compiler-1.4.5/tests/tests.h device-tree-compiler-1.4.7/tests/tests.h --- device-tree-compiler-1.4.5/tests/tests.h 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/tests.h 2018-07-23 03:00:50.000000000 +0000 @@ -1,5 +1,5 @@ -#ifndef _TESTS_H -#define _TESTS_H +#ifndef TESTS_H +#define TESTS_H /* * libfdt - Flat Device Tree manipulation * Testcase definitions @@ -119,6 +119,7 @@ #define check_getprop_string(fdt, nodeoffset, name, s) \ check_getprop((fdt), (nodeoffset), (name), strlen(s)+1, (s)) int nodename_eq(const char *s1, const char *s2); +void vg_prepare_blob(void *fdt, size_t bufsize); void *load_blob(const char *filename); void *load_blob_arg(int argc, char *argv[]); void save_blob(const char *filename, void *blob); @@ -126,4 +127,4 @@ #include "util.h" -#endif /* _TESTS_H */ +#endif /* TESTS_H */ diff -Nru device-tree-compiler-1.4.5/tests/testutils.c device-tree-compiler-1.4.7/tests/testutils.c --- device-tree-compiler-1.4.5/tests/testutils.c 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/testutils.c 2018-07-23 03:00:50.000000000 +0000 @@ -30,10 +30,15 @@ #include #include +#include + #include #include "tests.h" +/* For FDT_SW_MAGIC */ +#include "libfdt_internal.h" + int verbose_test = 1; char *test_name; @@ -88,7 +93,7 @@ int len, const void *val) { const struct fdt_property *prop; - int retlen; + int retlen, namelen; uint32_t tag, nameoff, proplen; const char *propname; @@ -106,8 +111,13 @@ if (tag != FDT_PROP) FAIL("Incorrect tag 0x%08x on property \"%s\"", tag, name); - propname = fdt_string(fdt, nameoff); - if (!propname || !streq(propname, name)) + propname = fdt_get_string(fdt, nameoff, &namelen); + if (!propname) + FAIL("Couldn't get property name: %s", fdt_strerror(namelen)); + if (namelen != strlen(propname)) + FAIL("Incorrect prop name length: %d instead of %zd", + namelen, strlen(propname)); + if (!streq(propname, name)) FAIL("Property name mismatch \"%s\" instead of \"%s\"", propname, name); if (proplen != retlen) @@ -117,7 +127,7 @@ if (proplen != len) FAIL("Size mismatch on property \"%s\": %d insead of %d", name, proplen, len); - if (memcmp(val, prop->data, len) != 0) + if (len && memcmp(val, prop->data, len) != 0) FAIL("Data mismatch on property \"%s\"", name); } @@ -134,7 +144,7 @@ if (proplen != len) FAIL("Size mismatch on property \"%s\": %d insead of %d", name, proplen, len); - if (memcmp(val, propval, len) != 0) + if (len && memcmp(val, propval, len) != 0) FAIL("Data mismatch on property \"%s\"", name); return propval; @@ -154,16 +164,66 @@ return 0; } -#define CHUNKSIZE 128 +void vg_prepare_blob(void *fdt, size_t bufsize) +{ + char *blob = fdt; + int off_memrsv, off_strings, off_struct; + int num_memrsv; + size_t size_memrsv, size_strings, size_struct; + + off_memrsv = fdt_off_mem_rsvmap(fdt); + num_memrsv = fdt_num_mem_rsv(fdt); + if (num_memrsv < 0) + size_memrsv = fdt_totalsize(fdt) - off_memrsv; + else + size_memrsv = (num_memrsv + 1) + * sizeof(struct fdt_reserve_entry); + + VALGRIND_MAKE_MEM_UNDEFINED(blob, bufsize); + VALGRIND_MAKE_MEM_DEFINED(blob, FDT_V1_SIZE); + VALGRIND_MAKE_MEM_DEFINED(blob, fdt_header_size(fdt)); + + if (fdt_magic(fdt) == FDT_MAGIC) { + off_strings = fdt_off_dt_strings(fdt); + if (fdt_version(fdt) >= 3) + size_strings = fdt_size_dt_strings(fdt); + else + size_strings = fdt_totalsize(fdt) - off_strings; + + off_struct = fdt_off_dt_struct(fdt); + if (fdt_version(fdt) >= 17) + size_struct = fdt_size_dt_struct(fdt); + else + size_struct = fdt_totalsize(fdt) - off_struct; + } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { + size_strings = fdt_size_dt_strings(fdt); + off_strings = fdt_off_dt_strings(fdt) - size_strings; + + off_struct = fdt_off_dt_struct(fdt); + size_struct = fdt_size_dt_struct(fdt); + size_struct = fdt_totalsize(fdt) - off_struct; + + } else { + CONFIG("Bad magic on vg_prepare_blob()"); + } + + VALGRIND_MAKE_MEM_DEFINED(blob + off_memrsv, size_memrsv); + VALGRIND_MAKE_MEM_DEFINED(blob + off_strings, size_strings); + VALGRIND_MAKE_MEM_DEFINED(blob + off_struct, size_struct); +} void *load_blob(const char *filename) { char *blob; - int ret = utilfdt_read_err(filename, &blob); + size_t len; + int ret = utilfdt_read_err(filename, &blob, &len); if (ret) CONFIG("Couldn't open blob from \"%s\": %s", filename, strerror(ret)); + + vg_prepare_blob(blob, len); + return blob; } @@ -176,11 +236,20 @@ void save_blob(const char *filename, void *fdt) { - int ret = utilfdt_write_err(filename, fdt); - + size_t size = fdt_totalsize(fdt); + void *tmp; + int ret; + + /* Make a temp copy of the blob so that valgrind won't check + * about uninitialized bits in the pieces between blocks */ + tmp = xmalloc(size); + fdt_move(fdt, tmp, size); + VALGRIND_MAKE_MEM_DEFINED(tmp, size); + ret = utilfdt_write_err(filename, tmp); if (ret) CONFIG("Couldn't write blob to \"%s\": %s", filename, strerror(ret)); + free(tmp); } void *open_blob_rw(void *blob) diff -Nru device-tree-compiler-1.4.5/tests/trees.S device-tree-compiler-1.4.7/tests/trees.S --- device-tree-compiler-1.4.5/tests/trees.S 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/trees.S 2018-07-23 03:00:50.000000000 +0000 @@ -7,20 +7,9 @@ .byte ((val) >> 8) & 0xff ; \ .byte (val) & 0xff ; -#define FDTQUAD(val) \ - .byte ((val) >> 56) & 0xff ; \ - .byte ((val) >> 48) & 0xff ; \ - .byte ((val) >> 40) & 0xff ; \ - .byte ((val) >> 32) & 0xff ; \ - .byte ((val) >> 24) & 0xff ; \ - .byte ((val) >> 16) & 0xff ; \ - .byte ((val) >> 8) & 0xff ; \ - .byte (val) & 0xff ; - #define TREE_HDR(tree) \ .balign 8 ; \ - .globl _##tree ; \ -_##tree: \ + .globl tree ; \ tree: \ FDTLONG(FDT_MAGIC) ; \ FDTLONG(tree##_end - tree) ; \ @@ -33,14 +22,16 @@ FDTLONG(tree##_strings_end - tree##_strings) ; \ FDTLONG(tree##_struct_end - tree##_struct) ; -#define RSVMAP_ENTRY(addr, len) \ - FDTQUAD(addr) ; \ - FDTQUAD(len) ; \ +#define RSVMAP_ENTRY(addrh, addrl, lenh, lenl) \ + FDTLONG(addrh) ; \ + FDTLONG(addrl) ; \ + FDTLONG(lenh) ; \ + FDTLONG(lenl) #define EMPTY_RSVMAP(tree) \ .balign 8 ; \ tree##_rsvmap: ; \ - RSVMAP_ENTRY(0, 0) \ + RSVMAP_ENTRY(0, 0, 0, 0) \ tree##_rsvmap_end: ; #define PROPHDR(tree, name, len) \ @@ -48,13 +39,17 @@ FDTLONG(len) ; \ FDTLONG(tree##_##name - tree##_strings) ; +#define PROP_EMPTY(tree, name) \ + PROPHDR(tree, name, 0) ; + #define PROP_INT(tree, name, val) \ PROPHDR(tree, name, 4) \ FDTLONG(val) ; -#define PROP_INT64(tree, name, val) \ +#define PROP_INT64(tree, name, valh, vall) \ PROPHDR(tree, name, 8) \ - FDTQUAD(val) ; + FDTLONG(valh) ; \ + FDTLONG(vall) ; #define PROP_STR(tree, name, str) \ PROPHDR(tree, name, 55f - 54f) \ @@ -81,16 +76,16 @@ .balign 8 test_tree1_rsvmap: - RSVMAP_ENTRY(TEST_ADDR_1, TEST_SIZE_1) - RSVMAP_ENTRY(TEST_ADDR_2, TEST_SIZE_2) - RSVMAP_ENTRY(0, 0) + RSVMAP_ENTRY(TEST_ADDR_1H, TEST_ADDR_1L, TEST_SIZE_1H, TEST_SIZE_1L) + RSVMAP_ENTRY(TEST_ADDR_2H, TEST_ADDR_2L, TEST_SIZE_2H, TEST_SIZE_2L) + RSVMAP_ENTRY(0, 0, 0, 0) test_tree1_rsvmap_end: test_tree1_struct: BEGIN_NODE("") PROP_STR(test_tree1, compatible, "test_tree1") PROP_INT(test_tree1, prop_int, TEST_VALUE_1) - PROP_INT64(test_tree1, prop_int64, TEST_VALUE64_1) + PROP_INT64(test_tree1, prop_int64, TEST_VALUE64_1H, TEST_VALUE64_1L) PROP_STR(test_tree1, prop_str, TEST_STRING_1) PROP_INT(test_tree1, address_cells, 1) PROP_INT(test_tree1, size_cells, 0) @@ -215,8 +210,7 @@ /* overflow_size_strings */ .balign 8 - .globl _ovf_size_strings -_ovf_size_strings: + .globl ovf_size_strings ovf_size_strings: FDTLONG(FDT_MAGIC) FDTLONG(ovf_size_strings_end - ovf_size_strings) @@ -242,3 +236,46 @@ ovf_size_strings_bad_string = ovf_size_strings_strings + 0x10000000 ovf_size_strings_strings_end: ovf_size_strings_end: + + + /* truncated_string */ + TREE_HDR(truncated_string) + EMPTY_RSVMAP(truncated_string) + +truncated_string_struct: + BEGIN_NODE("") + PROP_EMPTY(truncated_string, good_string) + PROP_EMPTY(truncated_string, bad_string) + END_NODE + FDTLONG(FDT_END) +truncated_string_struct_end: + +truncated_string_strings: + STRING(truncated_string, good_string, "good") +truncated_string_bad_string: + .byte 'b' + .byte 'a' + .byte 'd' + /* NOTE: terminating \0 deliberately missing */ +truncated_string_strings_end: +truncated_string_end: + + + /* truncated_memrsv */ + TREE_HDR(truncated_memrsv) + +truncated_memrsv_struct: + BEGIN_NODE("") + END_NODE + FDTLONG(FDT_END) +truncated_memrsv_struct_end: + +truncated_memrsv_strings: +truncated_memrsv_strings_end: + + .balign 8 +truncated_memrsv_rsvmap: + RSVMAP_ENTRY(TEST_ADDR_1H, TEST_ADDR_1L, TEST_SIZE_1H, TEST_SIZE_1L) +truncated_memrsv_rsvmap_end: + +truncated_memrsv_end: diff -Nru device-tree-compiler-1.4.5/tests/truncated_memrsv.c device-tree-compiler-1.4.7/tests/truncated_memrsv.c --- device-tree-compiler-1.4.5/tests/truncated_memrsv.c 1970-01-01 00:00:00.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/truncated_memrsv.c 2018-07-23 03:00:50.000000000 +0000 @@ -0,0 +1,63 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for misbehaviour on a truncated string + * Copyright (C) 2018 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 +#include +#include +#include + +#include + +#include "tests.h" +#include "testdata.h" + +int main(int argc, char *argv[]) +{ + void *fdt = &truncated_memrsv; + int err; + uint64_t addr, size; + + test_init(argc, argv); + + err = fdt_check_header(fdt); + if (err != 0) + FAIL("Bad header: %s", fdt_strerror(err)); + + err = fdt_num_mem_rsv(fdt); + if (err != -FDT_ERR_TRUNCATED) + FAIL("fdt_num_mem_rsv() returned %d instead of -FDT_ERR_TRUNCATED", + err); + + err = fdt_get_mem_rsv(fdt, 0, &addr, &size); + if (err != 0) + FAIL("fdt_get_mem_rsv() failed on first entry: %s", + fdt_strerror(err)); + if ((addr != TEST_ADDR_1) || (size != TEST_SIZE_1)) + FAIL("Entry doesn't match: (0x%llx, 0x%llx) != (0x%llx, 0x%llx)", + (unsigned long long)addr, (unsigned long long)size, + TEST_ADDR_1, TEST_SIZE_1); + + err = fdt_get_mem_rsv(fdt, 1, &addr, &size); + if (err != -FDT_ERR_BADOFFSET) + FAIL("fdt_get_mem_rsv(1) returned %d instead of -FDT_ERR_BADOFFSET", + err); + + PASS(); +} diff -Nru device-tree-compiler-1.4.5/tests/truncated_property.c device-tree-compiler-1.4.7/tests/truncated_property.c --- device-tree-compiler-1.4.5/tests/truncated_property.c 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/truncated_property.c 2018-07-23 03:00:50.000000000 +0000 @@ -30,12 +30,14 @@ int main(int argc, char *argv[]) { - void *fdt = &_truncated_property; + void *fdt = &truncated_property; const void *prop; int len; test_init(argc, argv); + vg_prepare_blob(fdt, fdt_totalsize(fdt)); + prop = fdt_getprop(fdt, 0, "truncated", &len); if (prop) FAIL("fdt_getprop() succeeded on truncated property"); diff -Nru device-tree-compiler-1.4.5/tests/truncated_string.c device-tree-compiler-1.4.7/tests/truncated_string.c --- device-tree-compiler-1.4.5/tests/truncated_string.c 1970-01-01 00:00:00.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/truncated_string.c 2018-07-23 03:00:50.000000000 +0000 @@ -0,0 +1,81 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for misbehaviour on a truncated string + * Copyright (C) 2018 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 +#include +#include +#include + +#include + +#include "tests.h" +#include "testdata.h" + +int main(int argc, char *argv[]) +{ + void *fdt = &truncated_string; + const struct fdt_property *good, *bad; + int off, len; + const char *name; + + test_init(argc, argv); + + vg_prepare_blob(fdt, fdt_totalsize(fdt)); + + off = fdt_first_property_offset(fdt, 0); + good = fdt_get_property_by_offset(fdt, off, NULL); + + off = fdt_next_property_offset(fdt, off); + bad = fdt_get_property_by_offset(fdt, off, NULL); + + if (fdt32_to_cpu(good->len) != 0) + FAIL("Unexpected length for good property"); + name = fdt_get_string(fdt, fdt32_to_cpu(good->nameoff), &len); + if (!name) + FAIL("fdt_get_string() failed on good property: %s", + fdt_strerror(len)); + if (len != 4) + FAIL("fdt_get_string() returned length %d (not 4) on good property", + len); + if (!streq(name, "good")) + FAIL("fdt_get_string() returned \"%s\" (not \"good\") on good property", + name); + + if (fdt32_to_cpu(bad->len) != 0) + FAIL("Unexpected length for bad property\n"); + name = fdt_get_string(fdt, fdt32_to_cpu(bad->nameoff), &len); + if (name) + FAIL("fdt_get_string() succeeded incorrectly on bad property"); + else if (len != -FDT_ERR_TRUNCATED) + FAIL("fdt_get_string() gave unexpected error on bad property: %s", + fdt_strerror(len)); + + /* Make sure the 'good' property breaks correctly if we + * truncate the strings section */ + fdt_set_size_dt_strings(fdt, fdt32_to_cpu(good->nameoff) + 4); + name = fdt_get_string(fdt, fdt32_to_cpu(good->nameoff), &len); + if (name) + FAIL("fdt_get_string() succeeded incorrectly on mangled property"); + else if (len != -FDT_ERR_TRUNCATED) + FAIL("fdt_get_string() gave unexpected error on mangled property: %s", + fdt_strerror(len)); + + PASS(); +} diff -Nru device-tree-compiler-1.4.5/tests/type-preservation.dts device-tree-compiler-1.4.7/tests/type-preservation.dts --- device-tree-compiler-1.4.5/tests/type-preservation.dts 1970-01-01 00:00:00.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/type-preservation.dts 2018-07-23 03:00:50.000000000 +0000 @@ -0,0 +1,28 @@ +/dts-v1/; + +/ { + #address-cells = < 0x01 >; + #size-cells = < 0x00 >; + + sub1: subnode@1 { + prop_label: compatible = value_label: "subnode1"; + reg = < 0x01 >; + int-array = < 0x00 0x01 >, int_value_label: < 0x02 0x03 >; + int8 = [ 56 ]; + int8-array = [ 00 12 34 56 label: ]; + int16 = /bits/ 16 < 0x3210 >; + int16-array = /bits/ 16 < 0x1234 0x5678 0x90ab 0xcdef >; + int16-matrix = /bits/ 16 < 0x1234 0x5678 >, < 0x90ab 0xcdef >; + int64 = /bits/ 64 < 0x200000000 >; + int64-array = /bits/ 64 < 0x100000000 0x00 int64_array_label_end: >; + a-string-with-nulls = "foo\0bar", "baz"; + + subsub1: subsubnode { + compatible = "subsubnode1", "subsubnode"; + + subsubsub1: subsubsubnode { + compatible = "subsubsubnode1", < 0x1234 >, valuea: valueb: "subsubsubnode"; + }; + }; + }; +}; diff -Nru device-tree-compiler-1.4.5/tests/unit-addr-unique.dts device-tree-compiler-1.4.7/tests/unit-addr-unique.dts --- device-tree-compiler-1.4.5/tests/unit-addr-unique.dts 1970-01-01 00:00:00.000000000 +0000 +++ device-tree-compiler-1.4.7/tests/unit-addr-unique.dts 2018-07-23 03:00:50.000000000 +0000 @@ -0,0 +1,14 @@ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <0>; + + foo@1 { + reg = <1>; + }; + + bar@1 { + reg = <1>; + }; +}; diff -Nru device-tree-compiler-1.4.5/.travis.yml device-tree-compiler-1.4.7/.travis.yml --- device-tree-compiler-1.4.5/.travis.yml 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/.travis.yml 2018-07-23 03:00:50.000000000 +0000 @@ -13,6 +13,7 @@ packages: - swig - python-dev + - valgrind coverity_scan: project: name: dtc @@ -20,11 +21,15 @@ notification_email: david@gibson.dropbear.id.au build_command: make branch_pattern: coverity_scan + script: + - make + - make check && make checkm + # Check it builds properly without the python bits - addons: apt: packages: - -script: + - valgrind + script: - make - make check diff -Nru device-tree-compiler-1.4.5/treesource.c device-tree-compiler-1.4.7/treesource.c --- device-tree-compiler-1.4.5/treesource.c 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/treesource.c 2018-07-23 03:00:50.000000000 +0000 @@ -61,24 +61,14 @@ || strchr("\a\b\t\n\v\f\r", c)); } -static void write_propval_string(FILE *f, struct data val) +static void write_propval_string(FILE *f, const char *s, size_t len) { - const char *str = val.val; - int i; - struct marker *m = val.markers; - - assert(str[val.len-1] == '\0'); + const char *end = s + len - 1; + assert(*end == '\0'); - while (m && (m->offset == 0)) { - if (m->type == LABEL) - fprintf(f, "%s: ", m->ref); - m = m->next; - } fprintf(f, "\""); - - for (i = 0; i < (val.len-1); i++) { - char c = str[i]; - + while (s < end) { + char c = *s++; switch (c) { case '\a': fprintf(f, "\\a"); @@ -108,91 +98,73 @@ fprintf(f, "\\\""); break; case '\0': - fprintf(f, "\", "); - while (m && (m->offset <= (i + 1))) { - if (m->type == LABEL) { - assert(m->offset == (i+1)); - fprintf(f, "%s: ", m->ref); - } - m = m->next; - } - fprintf(f, "\""); + fprintf(f, "\\0"); break; default: if (isprint((unsigned char)c)) fprintf(f, "%c", c); else - fprintf(f, "\\x%02hhx", c); + fprintf(f, "\\x%02"PRIx8, c); } } fprintf(f, "\""); - - /* Wrap up any labels at the end of the value */ - for_each_marker_of_type(m, LABEL) { - assert (m->offset == val.len); - fprintf(f, " %s:", m->ref); - } } -static void write_propval_cells(FILE *f, struct data val) +static void write_propval_int(FILE *f, const char *p, size_t len, size_t width) { - void *propend = val.val + val.len; - fdt32_t *cp = (fdt32_t *)val.val; - struct marker *m = val.markers; - - fprintf(f, "<"); - for (;;) { - while (m && (m->offset <= ((char *)cp - val.val))) { - if (m->type == LABEL) { - assert(m->offset == ((char *)cp - val.val)); - fprintf(f, "%s: ", m->ref); - } - m = m->next; - } + const char *end = p + len; + assert(len % width == 0); - fprintf(f, "0x%x", fdt32_to_cpu(*cp++)); - if ((void *)cp >= propend) + for (; p < end; p += width) { + switch (width) { + case 1: + fprintf(f, " %02"PRIx8, *(const uint8_t*)p); break; - fprintf(f, " "); - } - - /* Wrap up any labels at the end of the value */ - for_each_marker_of_type(m, LABEL) { - assert (m->offset == val.len); - fprintf(f, " %s:", m->ref); + case 2: + fprintf(f, " 0x%02"PRIx16, fdt16_to_cpu(*(const fdt16_t*)p)); + break; + case 4: + fprintf(f, " 0x%02"PRIx32, fdt32_to_cpu(*(const fdt32_t*)p)); + break; + case 8: + fprintf(f, " 0x%02"PRIx64, fdt64_to_cpu(*(const fdt64_t*)p)); + break; + } } - fprintf(f, ">"); } -static void write_propval_bytes(FILE *f, struct data val) +static struct marker *next_type_marker(struct marker *m) { - void *propend = val.val + val.len; - const char *bp = val.val; - struct marker *m = val.markers; - - fprintf(f, "["); - for (;;) { - while (m && (m->offset == (bp-val.val))) { - if (m->type == LABEL) - fprintf(f, "%s: ", m->ref); - m = m->next; - } + while (m && (m->type == LABEL || m->type == REF_PHANDLE || m->type == REF_PATH)) + m = m->next; + return m; +} - fprintf(f, "%02hhx", (unsigned char)(*bp++)); - if ((const void *)bp >= propend) - break; - fprintf(f, " "); - } +static size_t type_marker_length(struct marker *m) +{ + struct marker *next = next_type_marker(m->next); - /* Wrap up any labels at the end of the value */ - for_each_marker_of_type(m, LABEL) { - assert (m->offset == val.len); - fprintf(f, " %s:", m->ref); - } - fprintf(f, "]"); + if (next) + return next->offset - m->offset; + return 0; } -static void write_propval(FILE *f, struct property *prop) +static const char *delim_start[] = { + [TYPE_UINT8] = "[", + [TYPE_UINT16] = "/bits/ 16 <", + [TYPE_UINT32] = "<", + [TYPE_UINT64] = "/bits/ 64 <", + [TYPE_STRING] = "", +}; +static const char *delim_end[] = { + [TYPE_UINT8] = " ]", + [TYPE_UINT16] = " >", + [TYPE_UINT32] = " >", + [TYPE_UINT64] = " >", + [TYPE_STRING] = "", +}; + +static enum markertype guess_value_type(struct property *prop) { int len = prop->val.len; const char *p = prop->val.val; @@ -201,11 +173,6 @@ int nnotstringlbl = 0, nnotcelllbl = 0; int i; - if (len == 0) { - fprintf(f, ";\n"); - return; - } - for (i = 0; i < len; i++) { if (! isstring(p[i])) nnotstring++; @@ -220,17 +187,91 @@ nnotcelllbl++; } - fprintf(f, " = "); if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul)) && (nnotstringlbl == 0)) { - write_propval_string(f, prop->val); + return TYPE_STRING; } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) { - write_propval_cells(f, prop->val); - } else { - write_propval_bytes(f, prop->val); + return TYPE_UINT32; } - fprintf(f, ";\n"); + return TYPE_UINT8; +} + +static void write_propval(FILE *f, struct property *prop) +{ + size_t len = prop->val.len; + struct marker *m = prop->val.markers; + struct marker dummy_marker; + enum markertype emit_type = TYPE_NONE; + + if (len == 0) { + fprintf(f, ";\n"); + return; + } + + fprintf(f, " = "); + + if (!next_type_marker(m)) { + /* data type information missing, need to guess */ + dummy_marker.type = guess_value_type(prop); + dummy_marker.next = prop->val.markers; + dummy_marker.offset = 0; + dummy_marker.ref = NULL; + m = &dummy_marker; + } + + struct marker *m_label = prop->val.markers; + for_each_marker(m) { + size_t chunk_len; + const char *p = &prop->val.val[m->offset]; + + if (m->type < TYPE_UINT8) + continue; + + chunk_len = type_marker_length(m); + if (!chunk_len) + chunk_len = len - m->offset; + + if (emit_type != TYPE_NONE) + fprintf(f, "%s, ", delim_end[emit_type]); + emit_type = m->type; + + for_each_marker_of_type(m_label, LABEL) { + if (m_label->offset > m->offset) + break; + fprintf(f, "%s: ", m_label->ref); + } + + fprintf(f, "%s", delim_start[emit_type]); + + if (chunk_len <= 0) + continue; + + switch(emit_type) { + case TYPE_UINT16: + write_propval_int(f, p, chunk_len, 2); + break; + case TYPE_UINT32: + write_propval_int(f, p, chunk_len, 4); + break; + case TYPE_UINT64: + write_propval_int(f, p, chunk_len, 8); + break; + case TYPE_STRING: + write_propval_string(f, p, chunk_len); + break; + default: + write_propval_int(f, p, chunk_len, 1); + } + } + + /* Wrap up any labels at the end of the value */ + for_each_marker_of_type(m_label, LABEL) { + assert (m_label->offset == len); + fprintf(f, " %s:", m_label->ref); + } + + fprintf(f, "%s;\n", delim_end[emit_type] ? : ""); } static void write_tree_source_node(FILE *f, struct node *tree, int level) @@ -281,4 +322,3 @@ write_tree_source_node(f, dti->dt, 0); } - diff -Nru device-tree-compiler-1.4.5/util.c device-tree-compiler-1.4.7/util.c --- device-tree-compiler-1.4.5/util.c 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/util.c 2018-07-23 03:00:50.000000000 +0000 @@ -227,11 +227,11 @@ return val; } -int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len) +int utilfdt_read_err(const char *filename, char **buffp, size_t *len) { int fd = 0; /* assume stdin */ char *buf = NULL; - off_t bufsize = 1024, offset = 0; + size_t bufsize = 1024, offset = 0; int ret = 0; *buffp = NULL; @@ -264,20 +264,15 @@ free(buf); else *buffp = buf; - *len = bufsize; + if (len) + *len = bufsize; return ret; } -int utilfdt_read_err(const char *filename, char **buffp) -{ - off_t len; - return utilfdt_read_err_len(filename, buffp, &len); -} - -char *utilfdt_read_len(const char *filename, off_t *len) +char *utilfdt_read(const char *filename, size_t *len) { char *buff; - int ret = utilfdt_read_err_len(filename, &buff, len); + int ret = utilfdt_read_err(filename, &buff, len); if (ret) { fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename, @@ -288,12 +283,6 @@ return buff; } -char *utilfdt_read(const char *filename) -{ - off_t len; - return utilfdt_read_len(filename, &len); -} - int utilfdt_write_err(const char *filename, const void *blob) { int fd = 1; /* assume stdout */ diff -Nru device-tree-compiler-1.4.5/util.h device-tree-compiler-1.4.7/util.h --- device-tree-compiler-1.4.5/util.h 2017-09-27 10:00:10.000000000 +0000 +++ device-tree-compiler-1.4.7/util.h 2018-07-23 03:00:50.000000000 +0000 @@ -1,5 +1,5 @@ -#ifndef _UTIL_H -#define _UTIL_H +#ifndef UTIL_H +#define UTIL_H #include #include @@ -35,6 +35,9 @@ #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#define stringify(s) stringify_(s) +#define stringify_(s) #s + static inline void NORETURN PRINTF(1, 2) die(const char *str, ...) { va_list ap; @@ -95,16 +98,10 @@ * stderr. * * @param filename The filename to read, or - for stdin - * @return Pointer to allocated buffer containing fdt, or NULL on error - */ -char *utilfdt_read(const char *filename); - -/** - * Like utilfdt_read(), but also passes back the size of the file read. - * * @param len If non-NULL, the amount of data we managed to read + * @return Pointer to allocated buffer containing fdt, or NULL on error */ -char *utilfdt_read_len(const char *filename, off_t *len); +char *utilfdt_read(const char *filename, size_t *len); /** * Read a device tree file into a buffer. Does not report errors, but only @@ -113,16 +110,10 @@ * * @param filename The filename to read, or - for stdin * @param buffp Returns pointer to buffer containing fdt - * @return 0 if ok, else an errno value representing the error - */ -int utilfdt_read_err(const char *filename, char **buffp); - -/** - * Like utilfdt_read_err(), but also passes back the size of the file read. - * * @param len If non-NULL, the amount of data we managed to read + * @return 0 if ok, else an errno value representing the error */ -int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len); +int utilfdt_read_err(const char *filename, char **buffp, size_t *len); /** * Write a device tree buffer to a file. This will report any errors on @@ -260,4 +251,4 @@ case 'V': util_version(); \ case '?': usage("unknown option"); -#endif /* _UTIL_H */ +#endif /* UTIL_H */