This adds the following commits from upstream: 87a656ae5ff9 check: Inform about missing ranges 73d6e9ecb417 libfdt: fix undefined behaviour in fdt_splice_() 2525da3dba9b Bump version to v1.6.0 62cb4ad286ff Execute tests on FreeBSD with Cirrus CI 1f9a41750883 tests: Allow running the testsuite on already installed binary / libraries c5995ddf4c20 tests: Honour NO_YAML make variable e4ce227e89d7 tests: Properly clean up .bak file from tests 9b75292c335c tests: Honour $(NO_PYTHON) flag from Makefile in run_tests.sh 6c253afd07d4 Encode $(NO_PYTHON) consistently with other variables 95ec8ef706bd tests: No need to explicitly pass $PYTHON from Make to run_tests.sh 2b5f62d109a2 tests: Let run_tests.sh run Python tests without Makefile assistance 76b43dcbd18a checks: Add 'dma-ranges' check e5c92a4780c6 libfdt: Use VALID_INPUT for FDT_ERR_BADSTATE checks e5cc26b68bc0 libfdt: Add support for disabling internal checks 28fd7590aad2 libfdt: Improve comments in some of the assumptions fc207c32341b libfdt: Fix a few typos 0f61c72dedc4 libfdt: Allow exclusion of fdt_check_full() f270f45fd5d2 libfdt: Add support for disabling ordering check/fixup c18bae9a4c96 libfdt: Add support for disabling version checks fc03c4a2e04e libfdt: Add support for disabling rollback handling 77563ae72b7c libfdt: Add support for disabling sanity checks 57bc6327b80b libfdt: Add support for disabling dtb checks 464962489dcc Add a way to control the level of checks in the code 0c5326cb2845 libfdt: De-inline fdt_header_size() cc6a5a071504 Revert "yamltree: Ensure consistent bracketing of properties with phandles" 0e9225eb0dfe Remove redundant YYLOC global declaration cab09eedd644 Move -DNO_VALGRIND into CPPFLAGS 0eb1cb0b531e Makefile: pass $(CFLAGS) also during dependency generation
Showing the changes to scripts (9 of 9 files). Show all
Unified · Split
| @@ -352,7 +352,7 @@ static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti, · 351 unmodified lines | ||
| 352 | 352 | FAIL(c, dti, node, "node has a reg or ranges property, but no unit name"); |
| 353 | 353 | } else { |
| 354 | 354 | if (unitname[0]) |
| 355 | − FAIL(c, dti, node, "node has a unit name, but no reg property"); | |
| 355 | + FAIL(c, dti, node, "node has a unit name, but no reg or ranges property"); | |
| 356 | 356 | } |
| 357 | 357 | } |
| 358 | 358 | WARNING(unit_address_vs_reg, check_unit_address_vs_reg, NULL); |
| @@ -765,13 +765,15 @@ static void check_ranges_format(struct check *c, struct dt_info *dti, · 406 unmodified lines | ||
| 765 | 765 | { |
| 766 | 766 | struct property *prop; |
| 767 | 767 | int c_addr_cells, p_addr_cells, c_size_cells, p_size_cells, entrylen; |
| 768 | + const char *ranges = c->data; | |
| 768 | 769 | |
| 769 | − prop = get_property(node, "ranges"); | |
| 770 | + prop = get_property(node, ranges); | |
| 770 | 771 | if (!prop) |
| 771 | 772 | return; |
| 772 | 773 | |
| 773 | 774 | if (!node->parent) { |
| 774 | − FAIL_PROP(c, dti, node, prop, "Root node has a \"ranges\" property"); | |
| 775 | + FAIL_PROP(c, dti, node, prop, "Root node has a \"%s\" property", | |
| 776 | + ranges); | |
| 775 | 777 | return; |
| 776 | 778 | } |
| 777 | 779 | |
| @@ -783,23 +785,24 @@ static void check_ranges_format(struct check *c, struct dt_info *dti, · 5 unmodified lines | ||
| 783 | 785 | |
| 784 | 786 | if (prop->val.len == 0) { |
| 785 | 787 | if (p_addr_cells != c_addr_cells) |
| 786 | − FAIL_PROP(c, dti, node, prop, "empty \"ranges\" property but its " | |
| 788 | + FAIL_PROP(c, dti, node, prop, "empty \"%s\" property but its " | |
| 787 | 789 | "#address-cells (%d) differs from %s (%d)", |
| 788 | − c_addr_cells, node->parent->fullpath, | |
| 790 | + ranges, c_addr_cells, node->parent->fullpath, | |
| 789 | 791 | p_addr_cells); |
| 790 | 792 | if (p_size_cells != c_size_cells) |
| 791 | − FAIL_PROP(c, dti, node, prop, "empty \"ranges\" property but its " | |
| 793 | + FAIL_PROP(c, dti, node, prop, "empty \"%s\" property but its " | |
| 792 | 794 | "#size-cells (%d) differs from %s (%d)", |
| 793 | − c_size_cells, node->parent->fullpath, | |
| 795 | + ranges, c_size_cells, node->parent->fullpath, | |
| 794 | 796 | p_size_cells); |
| 795 | 797 | } else if ((prop->val.len % entrylen) != 0) { |
| 796 | − FAIL_PROP(c, dti, node, prop, "\"ranges\" property has invalid length (%d bytes) " | |
| 798 | + FAIL_PROP(c, dti, node, prop, "\"%s\" property has invalid length (%d bytes) " | |
| 797 | 799 | "(parent #address-cells == %d, child #address-cells == %d, " |
| 798 | − "#size-cells == %d)", prop->val.len, | |
| 800 | + "#size-cells == %d)", ranges, prop->val.len, | |
| 799 | 801 | p_addr_cells, c_addr_cells, c_size_cells); |
| 800 | 802 | } |
| 801 | 803 | } |
| 802 | −WARNING(ranges_format, check_ranges_format, NULL, &addr_size_cells); | |
| 804 | +WARNING(ranges_format, check_ranges_format, "ranges", &addr_size_cells); | |
| 805 | +WARNING(dma_ranges_format, check_ranges_format, "dma-ranges", &addr_size_cells); | |
| 803 | 806 | |
| 804 | 807 | static const struct bus_type pci_bus = { |
| 805 | 808 | .name = "PCI", |
| @@ -1780,7 +1783,7 @@ static struct check *check_table[] = { · 974 unmodified lines | ||
| 1780 | 1783 | &property_name_chars_strict, |
| 1781 | 1784 | &node_name_chars_strict, |
| 1782 | 1785 | |
| 1783 | − &addr_size_cells, ®_format, &ranges_format, | |
| 1786 | + &addr_size_cells, ®_format, &ranges_format, &dma_ranges_format, | |
| 1784 | 1787 | |
| 1785 | 1788 | &unit_address_vs_reg, |
| 1786 | 1789 | &unit_address_format, |
| @@ -23,7 +23,6 @@ LINECOMMENT "//".*\n · 22 unmodified lines | ||
| 23 | 23 | #include "srcpos.h" |
| 24 | 24 | #include "dtc-parser.tab.h" |
| 25 | 25 | |
| 26 | −YYLTYPE yylloc; | |
| 27 | 26 | extern bool treesource_error; |
| 28 | 27 | |
| 29 | 28 | /* CAUTION: this will stop working if we ever use yyless() or yyunput() */ |
| @@ -19,15 +19,21 @@ int32_t fdt_ro_probe_(const void *fdt) · 18 unmodified lines | ||
| 19 | 19 | { |
| 20 | 20 | uint32_t totalsize = fdt_totalsize(fdt); |
| 21 | 21 | |
| 22 | + if (can_assume(VALID_DTB)) | |
| 23 | + return totalsize; | |
| 24 | + | |
| 22 | 25 | if (fdt_magic(fdt) == FDT_MAGIC) { |
| 23 | 26 | /* Complete tree */ |
| 24 | − if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) | |
| 25 | − return -FDT_ERR_BADVERSION; | |
| 26 | − if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) | |
| 27 | − return -FDT_ERR_BADVERSION; | |
| 27 | + if (!can_assume(LATEST)) { | |
| 28 | + if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) | |
| 29 | + return -FDT_ERR_BADVERSION; | |
| 30 | + if (fdt_last_comp_version(fdt) > | |
| 31 | + FDT_LAST_SUPPORTED_VERSION) | |
| 32 | + return -FDT_ERR_BADVERSION; | |
| 33 | + } | |
| 28 | 34 | } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { |
| 29 | 35 | /* Unfinished sequential-write blob */ |
| 30 | − if (fdt_size_dt_struct(fdt) == 0) | |
| 36 | + if (!can_assume(VALID_INPUT) && fdt_size_dt_struct(fdt) == 0) | |
| 31 | 37 | return -FDT_ERR_BADSTATE; |
| 32 | 38 | } else { |
| 33 | 39 | return -FDT_ERR_BADMAGIC; |
| @@ -70,44 +76,59 @@ size_t fdt_header_size_(uint32_t version) · 36 unmodified lines | ||
| 70 | 76 | return FDT_V17_SIZE; |
| 71 | 77 | } |
| 72 | 78 | |
| 79 | +size_t fdt_header_size(const void *fdt) | |
| 80 | +{ | |
| 81 | + return can_assume(LATEST) ? FDT_V17_SIZE : | |
| 82 | + fdt_header_size_(fdt_version(fdt)); | |
| 83 | +} | |
| 84 | + | |
| 73 | 85 | int fdt_check_header(const void *fdt) |
| 74 | 86 | { |
| 75 | 87 | size_t hdrsize; |
| 76 | 88 | |
| 77 | 89 | if (fdt_magic(fdt) != FDT_MAGIC) |
| 78 | 90 | return -FDT_ERR_BADMAGIC; |
| 91 | + if (!can_assume(LATEST)) { | |
| 92 | + if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) | |
| 93 | + || (fdt_last_comp_version(fdt) > | |
| 94 | + FDT_LAST_SUPPORTED_VERSION)) | |
| 95 | + return -FDT_ERR_BADVERSION; | |
| 96 | + if (fdt_version(fdt) < fdt_last_comp_version(fdt)) | |
| 97 | + return -FDT_ERR_BADVERSION; | |
| 98 | + } | |
| 79 | 99 | hdrsize = fdt_header_size(fdt); |
| 80 | − if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) | |
| 81 | − || (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)) | |
| 82 | − return -FDT_ERR_BADVERSION; | |
| 83 | − if (fdt_version(fdt) < fdt_last_comp_version(fdt)) | |
| 84 | − return -FDT_ERR_BADVERSION; | |
| 85 | − | |
| 86 | − if ((fdt_totalsize(fdt) < hdrsize) | |
| 87 | − || (fdt_totalsize(fdt) > INT_MAX)) | |
| 88 | − return -FDT_ERR_TRUNCATED; | |
| 100 | + if (!can_assume(VALID_DTB)) { | |
| 89 | 101 | |
| 90 | − /* Bounds check memrsv block */ | |
| 91 | − if (!check_off_(hdrsize, fdt_totalsize(fdt), fdt_off_mem_rsvmap(fdt))) | |
| 92 | − return -FDT_ERR_TRUNCATED; | |
| 102 | + if ((fdt_totalsize(fdt) < hdrsize) | |
| 103 | + || (fdt_totalsize(fdt) > INT_MAX)) | |
| 104 | + return -FDT_ERR_TRUNCATED; | |
| 93 | 105 | |
| 94 | − /* Bounds check structure block */ | |
| 95 | − if (fdt_version(fdt) < 17) { | |
| 106 | + /* Bounds check memrsv block */ | |
| 96 | 107 | if (!check_off_(hdrsize, fdt_totalsize(fdt), |
| 97 | − fdt_off_dt_struct(fdt))) | |
| 108 | + fdt_off_mem_rsvmap(fdt))) | |
| 98 | 109 | return -FDT_ERR_TRUNCATED; |
| 99 | − } else { | |
| 110 | + } | |
| 111 | + | |
| 112 | + if (!can_assume(VALID_DTB)) { | |
| 113 | + /* Bounds check structure block */ | |
| 114 | + if (!can_assume(LATEST) && fdt_version(fdt) < 17) { | |
| 115 | + if (!check_off_(hdrsize, fdt_totalsize(fdt), | |
| 116 | + fdt_off_dt_struct(fdt))) | |
| 117 | + return -FDT_ERR_TRUNCATED; | |
| 118 | + } else { | |
| 119 | + if (!check_block_(hdrsize, fdt_totalsize(fdt), | |
| 120 | + fdt_off_dt_struct(fdt), | |
| 121 | + fdt_size_dt_struct(fdt))) | |
| 122 | + return -FDT_ERR_TRUNCATED; | |
| 123 | + } | |
| 124 | + | |
| 125 | + /* Bounds check strings block */ | |
| 100 | 126 | if (!check_block_(hdrsize, fdt_totalsize(fdt), |
| 101 | − fdt_off_dt_struct(fdt), | |
| 102 | − fdt_size_dt_struct(fdt))) | |
| 127 | + fdt_off_dt_strings(fdt), | |
| 128 | + fdt_size_dt_strings(fdt))) | |
| 103 | 129 | return -FDT_ERR_TRUNCATED; |
| 104 | 130 | } |
| 105 | 131 | |
| 106 | − /* Bounds check strings block */ | |
| 107 | − if (!check_block_(hdrsize, fdt_totalsize(fdt), | |
| 108 | − fdt_off_dt_strings(fdt), fdt_size_dt_strings(fdt))) | |
| 109 | − return -FDT_ERR_TRUNCATED; | |
| 110 | − | |
| 111 | 132 | return 0; |
| 112 | 133 | } |
| 113 | 134 | |
| @@ -115,12 +136,13 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) · 1 unmodified line | ||
| 115 | 136 | { |
| 116 | 137 | unsigned absoffset = offset + fdt_off_dt_struct(fdt); |
| 117 | 138 | |
| 118 | − if ((absoffset < offset) | |
| 119 | − || ((absoffset + len) < absoffset) | |
| 120 | − || (absoffset + len) > fdt_totalsize(fdt)) | |
| 121 | − return NULL; | |
| 139 | + if (!can_assume(VALID_INPUT)) | |
| 140 | + if ((absoffset < offset) | |
| 141 | + || ((absoffset + len) < absoffset) | |
| 142 | + || (absoffset + len) > fdt_totalsize(fdt)) | |
| 143 | + return NULL; | |
| 122 | 144 | |
| 123 | − if (fdt_version(fdt) >= 0x11) | |
| 145 | + if (can_assume(LATEST) || fdt_version(fdt) >= 0x11) | |
| 124 | 146 | if (((offset + len) < offset) |
| 125 | 147 | || ((offset + len) > fdt_size_dt_struct(fdt))) |
| 126 | 148 | return NULL; |
| @@ -137,7 +159,7 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) · 10 unmodified lines | ||
| 137 | 159 | |
| 138 | 160 | *nextoffset = -FDT_ERR_TRUNCATED; |
| 139 | 161 | tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE); |
| 140 | − if (!tagp) | |
| 162 | + if (!can_assume(VALID_DTB) && !tagp) | |
| 141 | 163 | return FDT_END; /* premature end */ |
| 142 | 164 | tag = fdt32_to_cpu(*tagp); |
| 143 | 165 | offset += FDT_TAGSIZE; |
| @@ -149,18 +171,19 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) · 5 unmodified lines | ||
| 149 | 171 | do { |
| 150 | 172 | p = fdt_offset_ptr(fdt, offset++, 1); |
| 151 | 173 | } while (p && (*p != '\0')); |
| 152 | − if (!p) | |
| 174 | + if (!can_assume(VALID_DTB) && !p) | |
| 153 | 175 | return FDT_END; /* premature end */ |
| 154 | 176 | break; |
| 155 | 177 | |
| 156 | 178 | case FDT_PROP: |
| 157 | 179 | lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); |
| 158 | − if (!lenp) | |
| 180 | + if (!can_assume(VALID_DTB) && !lenp) | |
| 159 | 181 | return FDT_END; /* premature end */ |
| 160 | 182 | /* skip-name offset, length and value */ |
| 161 | 183 | offset += sizeof(struct fdt_property) - FDT_TAGSIZE |
| 162 | 184 | + fdt32_to_cpu(*lenp); |
| 163 | − if (fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 && | |
| 185 | + if (!can_assume(LATEST) && | |
| 186 | + fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 && | |
| 164 | 187 | ((offset - fdt32_to_cpu(*lenp)) % 8) != 0) |
| 165 | 188 | offset += 4; |
| 166 | 189 | break; |
| @@ -183,6 +206,8 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) · 16 unmodified lines | ||
| 183 | 206 | |
| 184 | 207 | int fdt_check_node_offset_(const void *fdt, int offset) |
| 185 | 208 | { |
| 209 | + if (can_assume(VALID_INPUT)) | |
| 210 | + return offset; | |
| 186 | 211 | if ((offset < 0) || (offset % FDT_TAGSIZE) |
| 187 | 212 | || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE)) |
| 188 | 213 | return -FDT_ERR_BADOFFSET; |
| @@ -33,17 +33,26 @@ static int fdt_nodename_eq_(const void *fdt, int offset, · 32 unmodified lines | ||
| 33 | 33 | |
| 34 | 34 | const char *fdt_get_string(const void *fdt, int stroffset, int *lenp) |
| 35 | 35 | { |
| 36 | − int32_t totalsize = fdt_ro_probe_(fdt); | |
| 37 | − uint32_t absoffset = stroffset + fdt_off_dt_strings(fdt); | |
| 36 | + int32_t totalsize; | |
| 37 | + uint32_t absoffset; | |
| 38 | 38 | size_t len; |
| 39 | 39 | int err; |
| 40 | 40 | const char *s, *n; |
| 41 | 41 | |
| 42 | + if (can_assume(VALID_INPUT)) { | |
| 43 | + s = (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; | |
| 44 | + | |
| 45 | + if (lenp) | |
| 46 | + *lenp = strlen(s); | |
| 47 | + return s; | |
| 48 | + } | |
| 49 | + totalsize = fdt_ro_probe_(fdt); | |
| 42 | 50 | err = totalsize; |
| 43 | 51 | if (totalsize < 0) |
| 44 | 52 | goto fail; |
| 45 | 53 | |
| 46 | 54 | err = -FDT_ERR_BADOFFSET; |
| 55 | + absoffset = stroffset + fdt_off_dt_strings(fdt); | |
| 47 | 56 | if (absoffset >= totalsize) |
| 48 | 57 | goto fail; |
| 49 | 58 | len = totalsize - absoffset; |
| @@ -51,7 +60,7 @@ const char *fdt_get_string(const void *fdt, int stroffset, int *lenp) · 1 unmodified line | ||
| 51 | 60 | if (fdt_magic(fdt) == FDT_MAGIC) { |
| 52 | 61 | if (stroffset < 0) |
| 53 | 62 | goto fail; |
| 54 | − if (fdt_version(fdt) >= 17) { | |
| 63 | + if (can_assume(LATEST) || fdt_version(fdt) >= 17) { | |
| 55 | 64 | if (stroffset >= fdt_size_dt_strings(fdt)) |
| 56 | 65 | goto fail; |
| 57 | 66 | if ((fdt_size_dt_strings(fdt) - stroffset) < len) |
| @@ -151,10 +160,13 @@ static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n) · 93 unmodified lines | ||
| 151 | 160 | int offset = n * sizeof(struct fdt_reserve_entry); |
| 152 | 161 | int absoffset = fdt_off_mem_rsvmap(fdt) + offset; |
| 153 | 162 | |
| 154 | − if (absoffset < fdt_off_mem_rsvmap(fdt)) | |
| 155 | − return NULL; | |
| 156 | − if (absoffset > fdt_totalsize(fdt) - sizeof(struct fdt_reserve_entry)) | |
| 157 | − return NULL; | |
| 163 | + if (!can_assume(VALID_INPUT)) { | |
| 164 | + if (absoffset < fdt_off_mem_rsvmap(fdt)) | |
| 165 | + return NULL; | |
| 166 | + if (absoffset > fdt_totalsize(fdt) - | |
| 167 | + sizeof(struct fdt_reserve_entry)) | |
| 168 | + return NULL; | |
| 169 | + } | |
| 158 | 170 | return fdt_mem_rsv_(fdt, n); |
| 159 | 171 | } |
| 160 | 172 | |
| @@ -164,7 +176,7 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) · 3 unmodified lines | ||
| 164 | 176 | |
| 165 | 177 | FDT_RO_PROBE(fdt); |
| 166 | 178 | re = fdt_mem_rsv(fdt, n); |
| 167 | − if (!re) | |
| 179 | + if (!can_assume(VALID_INPUT) && !re) | |
| 168 | 180 | return -FDT_ERR_BADOFFSET; |
| 169 | 181 | |
| 170 | 182 | *address = fdt64_ld(&re->address); |
| @@ -295,7 +307,7 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) · 124 unmodified lines | ||
| 295 | 307 | |
| 296 | 308 | nameptr = nh->name; |
| 297 | 309 | |
| 298 | − if (fdt_version(fdt) < 0x10) { | |
| 310 | + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) { | |
| 299 | 311 | /* |
| 300 | 312 | * For old FDT versions, match the naming conventions of V16: |
| 301 | 313 | * give only the leaf name (after all /). The actual tree |
| @@ -346,7 +358,8 @@ static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt, · 44 unmodified lines | ||
| 346 | 358 | int err; |
| 347 | 359 | const struct fdt_property *prop; |
| 348 | 360 | |
| 349 | − if ((err = fdt_check_prop_offset_(fdt, offset)) < 0) { | |
| 361 | + if (!can_assume(VALID_INPUT) && | |
| 362 | + (err = fdt_check_prop_offset_(fdt, offset)) < 0) { | |
| 350 | 363 | if (lenp) |
| 351 | 364 | *lenp = err; |
| 352 | 365 | return NULL; |
| @@ -367,7 +380,7 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt, · 14 unmodified lines | ||
| 367 | 380 | /* Prior to version 16, properties may need realignment |
| 368 | 381 | * and this API does not work. fdt_getprop_*() will, however. */ |
| 369 | 382 | |
| 370 | − if (fdt_version(fdt) < 0x10) { | |
| 383 | + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) { | |
| 371 | 384 | if (lenp) |
| 372 | 385 | *lenp = -FDT_ERR_BADVERSION; |
| 373 | 386 | return NULL; |
| @@ -388,7 +401,8 @@ static const struct fdt_property *fdt_get_property_namelen_(const void *fdt, · 14 unmodified lines | ||
| 388 | 401 | (offset = fdt_next_property_offset(fdt, offset))) { |
| 389 | 402 | const struct fdt_property *prop; |
| 390 | 403 | |
| 391 | − if (!(prop = fdt_get_property_by_offset_(fdt, offset, lenp))) { | |
| 404 | + prop = fdt_get_property_by_offset_(fdt, offset, lenp); | |
| 405 | + if (!can_assume(LIBFDT_FLAWLESS) && !prop) { | |
| 392 | 406 | offset = -FDT_ERR_INTERNAL; |
| 393 | 407 | break; |
| 394 | 408 | } |
| @@ -413,7 +427,7 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt, · 18 unmodified lines | ||
| 413 | 427 | { |
| 414 | 428 | /* Prior to version 16, properties may need realignment |
| 415 | 429 | * and this API does not work. fdt_getprop_*() will, however. */ |
| 416 | − if (fdt_version(fdt) < 0x10) { | |
| 430 | + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) { | |
| 417 | 431 | if (lenp) |
| 418 | 432 | *lenp = -FDT_ERR_BADVERSION; |
| 419 | 433 | return NULL; |
| @@ -444,8 +458,8 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, · 24 unmodified lines | ||
| 444 | 458 | return NULL; |
| 445 | 459 | |
| 446 | 460 | /* Handle realignment */ |
| 447 | − if (fdt_version(fdt) < 0x10 && (poffset + sizeof(*prop)) % 8 && | |
| 448 | − fdt32_ld(&prop->len) >= 8) | |
| 461 | + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 && | |
| 462 | + (poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8) | |
| 449 | 463 | return prop->data + 4; |
| 450 | 464 | return prop->data; |
| 451 | 465 | } |
| @@ -461,19 +475,24 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset, · 9 unmodified lines | ||
| 461 | 475 | if (namep) { |
| 462 | 476 | const char *name; |
| 463 | 477 | int namelen; |
| 464 | − name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff), | |
| 465 | − &namelen); | |
| 466 | − if (!name) { | |
| 467 | − if (lenp) | |
| 468 | − *lenp = namelen; | |
| 469 | − return NULL; | |
| 478 | + | |
| 479 | + if (!can_assume(VALID_INPUT)) { | |
| 480 | + name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff), | |
| 481 | + &namelen); | |
| 482 | + if (!name) { | |
| 483 | + if (lenp) | |
| 484 | + *lenp = namelen; | |
| 485 | + return NULL; | |
| 486 | + } | |
| 487 | + *namep = name; | |
| 488 | + } else { | |
| 489 | + *namep = fdt_string(fdt, fdt32_ld(&prop->nameoff)); | |
| 470 | 490 | } |
| 471 | − *namep = name; | |
| 472 | 491 | } |
| 473 | 492 | |
| 474 | 493 | /* Handle realignment */ |
| 475 | − if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 && | |
| 476 | − fdt32_ld(&prop->len) >= 8) | |
| 494 | + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 && | |
| 495 | + (offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8) | |
| 477 | 496 | return prop->data + 4; |
| 478 | 497 | return prop->data; |
| 479 | 498 | } |
| @@ -598,10 +617,12 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, · 118 unmodified lines | ||
| 598 | 617 | } |
| 599 | 618 | } |
| 600 | 619 | |
| 601 | − if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) | |
| 602 | − return -FDT_ERR_BADOFFSET; | |
| 603 | − else if (offset == -FDT_ERR_BADOFFSET) | |
| 604 | − return -FDT_ERR_BADSTRUCTURE; | |
| 620 | + if (!can_assume(VALID_INPUT)) { | |
| 621 | + if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) | |
| 622 | + return -FDT_ERR_BADOFFSET; | |
| 623 | + else if (offset == -FDT_ERR_BADOFFSET) | |
| 624 | + return -FDT_ERR_BADSTRUCTURE; | |
| 625 | + } | |
| 605 | 626 | |
| 606 | 627 | return offset; /* error from fdt_next_node() */ |
| 607 | 628 | } |
| @@ -613,7 +634,8 @@ int fdt_node_depth(const void *fdt, int nodeoffset) · 5 unmodified lines | ||
| 613 | 634 | |
| 614 | 635 | err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth); |
| 615 | 636 | if (err) |
| 616 | − return (err < 0) ? err : -FDT_ERR_INTERNAL; | |
| 637 | + return (can_assume(LIBFDT_FLAWLESS) || err < 0) ? err : | |
| 638 | + -FDT_ERR_INTERNAL; | |
| 617 | 639 | return nodedepth; |
| 618 | 640 | } |
| 619 | 641 | |
| @@ -833,66 +855,3 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset, · 213 unmodified lines | ||
| 833 | 855 | |
| 834 | 856 | return offset; /* error from fdt_next_node() */ |
| 835 | 857 | } |
| 836 | − | |
| 837 | −int fdt_check_full(const void *fdt, size_t bufsize) | |
| 838 | −{ | |
| 839 | − int err; | |
| 840 | − int num_memrsv; | |
| 841 | − int offset, nextoffset = 0; | |
| 842 | − uint32_t tag; | |
| 843 | − unsigned depth = 0; | |
| 844 | − const void *prop; | |
| 845 | − const char *propname; | |
| 846 | − | |
| 847 | − if (bufsize < FDT_V1_SIZE) | |
| 848 | − return -FDT_ERR_TRUNCATED; | |
| 849 | − err = fdt_check_header(fdt); | |
| 850 | − if (err != 0) | |
| 851 | − return err; | |
| 852 | − if (bufsize < fdt_totalsize(fdt)) | |
| 853 | − return -FDT_ERR_TRUNCATED; | |
| 854 | − | |
| 855 | − num_memrsv = fdt_num_mem_rsv(fdt); | |
| 856 | − if (num_memrsv < 0) | |
| 857 | − return num_memrsv; | |
| 858 | − | |
| 859 | − while (1) { | |
| 860 | − offset = nextoffset; | |
| 861 | − tag = fdt_next_tag(fdt, offset, &nextoffset); | |
| 862 | − | |
| 863 | − if (nextoffset < 0) | |
| 864 | − return nextoffset; | |
| 865 | − | |
| 866 | − switch (tag) { | |
| 867 | − case FDT_NOP: | |
| 868 | − break; | |
| 869 | − | |
| 870 | − case FDT_END: | |
| 871 | − if (depth != 0) | |
| 872 | − return -FDT_ERR_BADSTRUCTURE; | |
| 873 | − return 0; | |
| 874 | − | |
| 875 | − case FDT_BEGIN_NODE: | |
| 876 | − depth++; | |
| 877 | − if (depth > INT_MAX) | |
| 878 | − return -FDT_ERR_BADSTRUCTURE; | |
| 879 | − break; | |
| 880 | − | |
| 881 | − case FDT_END_NODE: | |
| 882 | − if (depth == 0) | |
| 883 | − return -FDT_ERR_BADSTRUCTURE; | |
| 884 | − depth--; | |
| 885 | − break; | |
| 886 | − | |
| 887 | − case FDT_PROP: | |
| 888 | − prop = fdt_getprop_by_offset(fdt, offset, &propname, | |
| 889 | − &err); | |
| 890 | − if (!prop) | |
| 891 | − return err; | |
| 892 | − break; | |
| 893 | − | |
| 894 | − default: | |
| 895 | − return -FDT_ERR_INTERNAL; | |
| 896 | − } | |
| 897 | − } | |
| 898 | −} | |
| @@ -24,14 +24,16 @@ static int fdt_blocks_misordered_(const void *fdt, · 23 unmodified lines | ||
| 24 | 24 | |
| 25 | 25 | static int fdt_rw_probe_(void *fdt) |
| 26 | 26 | { |
| 27 | + if (can_assume(VALID_DTB)) | |
| 28 | + return 0; | |
| 27 | 29 | FDT_RO_PROBE(fdt); |
| 28 | 30 | |
| 29 | − if (fdt_version(fdt) < 17) | |
| 31 | + if (!can_assume(LATEST) && fdt_version(fdt) < 17) | |
| 30 | 32 | return -FDT_ERR_BADVERSION; |
| 31 | 33 | if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry), |
| 32 | 34 | fdt_size_dt_struct(fdt))) |
| 33 | 35 | return -FDT_ERR_BADLAYOUT; |
| 34 | − if (fdt_version(fdt) > 17) | |
| 36 | + if (!can_assume(LATEST) && fdt_version(fdt) > 17) | |
| 35 | 37 | fdt_set_version(fdt, 17); |
| 36 | 38 | |
| 37 | 39 | return 0; |
| @@ -44,7 +46,7 @@ static int fdt_rw_probe_(void *fdt) · 6 unmodified lines | ||
| 44 | 46 | return err_; \ |
| 45 | 47 | } |
| 46 | 48 | |
| 47 | −static inline int fdt_data_size_(void *fdt) | |
| 49 | +static inline unsigned int fdt_data_size_(void *fdt) | |
| 48 | 50 | { |
| 49 | 51 | return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); |
| 50 | 52 | } |
| @@ -52,15 +54,16 @@ static inline int fdt_data_size_(void *fdt) · 1 unmodified line | ||
| 52 | 54 | static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen) |
| 53 | 55 | { |
| 54 | 56 | char *p = splicepoint; |
| 55 | − char *end = (char *)fdt + fdt_data_size_(fdt); | |
| 57 | + unsigned int dsize = fdt_data_size_(fdt); | |
| 58 | + size_t soff = p - (char *)fdt; | |
| 56 | 59 | |
| 57 | − if (((p + oldlen) < p) || ((p + oldlen) > end)) | |
| 60 | + if ((oldlen < 0) || (soff + oldlen < soff) || (soff + oldlen > dsize)) | |
| 58 | 61 | return -FDT_ERR_BADOFFSET; |
| 59 | − if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt)) | |
| 62 | + if ((p < (char *)fdt) || (dsize + newlen < oldlen)) | |
| 60 | 63 | return -FDT_ERR_BADOFFSET; |
| 61 | − if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt))) | |
| 64 | + if (dsize - oldlen + newlen > fdt_totalsize(fdt)) | |
| 62 | 65 | return -FDT_ERR_NOSPACE; |
| 63 | − memmove(p + newlen, p + oldlen, end - p - oldlen); | |
| 66 | + memmove(p + newlen, p + oldlen, ((char *)fdt + dsize) - (p + oldlen)); | |
| 64 | 67 | return 0; |
| 65 | 68 | } |
| 66 | 69 | |
| @@ -112,6 +115,15 @@ static int fdt_splice_string_(void *fdt, int newlen) · 45 unmodified lines | ||
| 112 | 115 | return 0; |
| 113 | 116 | } |
| 114 | 117 | |
| 118 | +/** | |
| 119 | + * fdt_find_add_string_() - Find or allocate a string | |
| 120 | + * | |
| 121 | + * @fdt: pointer to the device tree to check/adjust | |
| 122 | + * @s: string to find/add | |
| 123 | + * @allocated: Set to 0 if the string was found, 1 if not found and so | |
| 124 | + * allocated. Ignored if can_assume(NO_ROLLBACK) | |
| 125 | + * @return offset of string in the string table (whether found or added) | |
| 126 | + */ | |
| 115 | 127 | static int fdt_find_add_string_(void *fdt, const char *s, int *allocated) |
| 116 | 128 | { |
| 117 | 129 | char *strtab = (char *)fdt + fdt_off_dt_strings(fdt); |
| @@ -120,7 +132,8 @@ static int fdt_find_add_string_(void *fdt, const char *s, int *allocated) · 2 unmodified lines | ||
| 120 | 132 | int len = strlen(s) + 1; |
| 121 | 133 | int err; |
| 122 | 134 | |
| 123 | − *allocated = 0; | |
| 135 | + if (!can_assume(NO_ROLLBACK)) | |
| 136 | + *allocated = 0; | |
| 124 | 137 | |
| 125 | 138 | p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s); |
| 126 | 139 | if (p) |
| @@ -132,7 +145,8 @@ static int fdt_find_add_string_(void *fdt, const char *s, int *allocated) · 5 unmodified lines | ||
| 132 | 145 | if (err) |
| 133 | 146 | return err; |
| 134 | 147 | |
| 135 | − *allocated = 1; | |
| 148 | + if (!can_assume(NO_ROLLBACK)) | |
| 149 | + *allocated = 1; | |
| 136 | 150 | |
| 137 | 151 | memcpy(new, s, len); |
| 138 | 152 | return (new - strtab); |
| @@ -206,7 +220,8 @@ static int fdt_add_property_(void *fdt, int nodeoffset, const char *name, · 67 unmodified lines | ||
| 206 | 220 | |
| 207 | 221 | err = fdt_splice_struct_(fdt, *prop, 0, proplen); |
| 208 | 222 | if (err) { |
| 209 | − if (allocated) | |
| 223 | + /* Delete the string if we failed to add it */ | |
| 224 | + if (!can_assume(NO_ROLLBACK) && allocated) | |
| 210 | 225 | fdt_del_last_string_(fdt, name); |
| 211 | 226 | return err; |
| 212 | 227 | } |
| @@ -411,7 +426,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize) · 198 unmodified lines | ||
| 411 | 426 | mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) |
| 412 | 427 | * sizeof(struct fdt_reserve_entry); |
| 413 | 428 | |
| 414 | − if (fdt_version(fdt) >= 17) { | |
| 429 | + if (can_assume(LATEST) || fdt_version(fdt) >= 17) { | |
| 415 | 430 | struct_size = fdt_size_dt_struct(fdt); |
| 416 | 431 | } else { |
| 417 | 432 | struct_size = 0; |
| @@ -421,7 +436,8 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize) · 3 unmodified lines | ||
| 421 | 436 | return struct_size; |
| 422 | 437 | } |
| 423 | 438 | |
| 424 | − if (!fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) { | |
| 439 | + if (can_assume(LIBFDT_ORDER) | | |
| 440 | + !fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) { | |
| 425 | 441 | /* no further work necessary */ |
| 426 | 442 | err = fdt_move(fdt, buf, bufsize); |
| 427 | 443 | if (err) |
| @@ -12,10 +12,13 @@ · 11 unmodified lines | ||
| 12 | 12 | |
| 13 | 13 | static int fdt_sw_probe_(void *fdt) |
| 14 | 14 | { |
| 15 | − if (fdt_magic(fdt) == FDT_MAGIC) | |
| 16 | − return -FDT_ERR_BADSTATE; | |
| 17 | − else if (fdt_magic(fdt) != FDT_SW_MAGIC) | |
| 18 | − return -FDT_ERR_BADMAGIC; | |
| 15 | + if (!can_assume(VALID_INPUT)) { | |
| 16 | + if (fdt_magic(fdt) == FDT_MAGIC) | |
| 17 | + return -FDT_ERR_BADSTATE; | |
| 18 | + else if (fdt_magic(fdt) != FDT_SW_MAGIC) | |
| 19 | + return -FDT_ERR_BADMAGIC; | |
| 20 | + } | |
| 21 | + | |
| 19 | 22 | return 0; |
| 20 | 23 | } |
| 21 | 24 | |
| @@ -38,7 +41,7 @@ static int fdt_sw_probe_memrsv_(void *fdt) · 16 unmodified lines | ||
| 38 | 41 | if (err) |
| 39 | 42 | return err; |
| 40 | 43 | |
| 41 | − if (fdt_off_dt_strings(fdt) != 0) | |
| 44 | + if (!can_assume(VALID_INPUT) && fdt_off_dt_strings(fdt) != 0) | |
| 42 | 45 | return -FDT_ERR_BADSTATE; |
| 43 | 46 | return 0; |
| 44 | 47 | } |
| @@ -64,7 +67,8 @@ static int fdt_sw_probe_struct_(void *fdt) · 19 unmodified lines | ||
| 64 | 67 | if (err) |
| 65 | 68 | return err; |
| 66 | 69 | |
| 67 | − if (fdt_off_dt_strings(fdt) != fdt_totalsize(fdt)) | |
| 70 | + if (!can_assume(VALID_INPUT) && | |
| 71 | + fdt_off_dt_strings(fdt) != fdt_totalsize(fdt)) | |
| 68 | 72 | return -FDT_ERR_BADSTATE; |
| 69 | 73 | return 0; |
| 70 | 74 | } |
| @@ -151,7 +155,8 @@ int fdt_resize(void *fdt, void *buf, int bufsize) · 80 unmodified lines | ||
| 151 | 155 | headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); |
| 152 | 156 | tailsize = fdt_size_dt_strings(fdt); |
| 153 | 157 | |
| 154 | − if ((headsize + tailsize) > fdt_totalsize(fdt)) | |
| 158 | + if (!can_assume(VALID_DTB) && | |
| 159 | + headsize + tailsize > fdt_totalsize(fdt)) | |
| 155 | 160 | return -FDT_ERR_INTERNAL; |
| 156 | 161 | |
| 157 | 162 | if ((headsize + tailsize) > bufsize) |
| @@ -266,11 +266,12 @@ fdt_set_hdr_(size_dt_struct); · 265 unmodified lines | ||
| 266 | 266 | * fdt_header_size - return the size of the tree's header |
| 267 | 267 | * @fdt: pointer to a flattened device tree |
| 268 | 268 | */ |
| 269 | +size_t fdt_header_size(const void *fdt); | |
| 270 | + | |
| 271 | +/** | |
| 272 | + * fdt_header_size_ - internal function which takes a version number | |
| 273 | + */ | |
| 269 | 274 | size_t fdt_header_size_(uint32_t version); |
| 270 | −static inline size_t fdt_header_size(const void *fdt) | |
| 271 | −{ | |
| 272 | − return fdt_header_size_(fdt_version(fdt)); | |
| 273 | −} | |
| 274 | 275 | |
| 275 | 276 | /** |
| 276 | 277 | * fdt_check_header - sanity check a device tree header |
| @@ -48,4 +48,126 @@ static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n) · 47 unmodified lines | ||
| 48 | 48 | |
| 49 | 49 | #define FDT_SW_MAGIC (~FDT_MAGIC) |
| 50 | 50 | |
| 51 | +/**********************************************************************/ | |
| 52 | +/* Checking controls */ | |
| 53 | +/**********************************************************************/ | |
| 54 | + | |
| 55 | +#ifndef FDT_ASSUME_MASK | |
| 56 | +#define FDT_ASSUME_MASK 0 | |
| 57 | +#endif | |
| 58 | + | |
| 59 | +/* | |
| 60 | + * Defines assumptions which can be enabled. Each of these can be enabled | |
| 61 | + * individually. For maximum safety, don't enable any assumptions! | |
| 62 | + * | |
| 63 | + * For minimal code size and no safety, use ASSUME_PERFECT at your own risk. | |
| 64 | + * You should have another method of validating the device tree, such as a | |
| 65 | + * signature or hash check before using libfdt. | |
| 66 | + * | |
| 67 | + * For situations where security is not a concern it may be safe to enable | |
| 68 | + * ASSUME_SANE. | |
| 69 | + */ | |
| 70 | +enum { | |
| 71 | + /* | |
| 72 | + * This does essentially no checks. Only the latest device-tree | |
| 73 | + * version is correctly handled. Inconsistencies or errors in the device | |
| 74 | + * tree may cause undefined behaviour or crashes. Invalid parameters | |
| 75 | + * passed to libfdt may do the same. | |
| 76 | + * | |
| 77 | + * If an error occurs when modifying the tree it may leave the tree in | |
| 78 | + * an intermediate (but valid) state. As an example, adding a property | |
| 79 | + * where there is insufficient space may result in the property name | |
| 80 | + * being added to the string table even though the property itself is | |
| 81 | + * not added to the struct section. | |
| 82 | + * | |
| 83 | + * Only use this if you have a fully validated device tree with | |
| 84 | + * the latest supported version and wish to minimise code size. | |
| 85 | + */ | |
| 86 | + ASSUME_PERFECT = 0xff, | |
| 87 | + | |
| 88 | + /* | |
| 89 | + * This assumes that the device tree is sane. i.e. header metadata | |
| 90 | + * and basic hierarchy are correct. | |
| 91 | + * | |
| 92 | + * With this assumption enabled, normal device trees produced by libfdt | |
| 93 | + * and the compiler should be handled safely. Malicious device trees and | |
| 94 | + * complete garbage may cause libfdt to behave badly or crash. Truncated | |
| 95 | + * device trees (e.g. those only partially loaded) can also cause | |
| 96 | + * problems. | |
| 97 | + * | |
| 98 | + * Note: Only checks that relate exclusively to the device tree itself | |
| 99 | + * (not the parameters passed to libfdt) are disabled by this | |
| 100 | + * assumption. This includes checking headers, tags and the like. | |
| 101 | + */ | |
| 102 | + ASSUME_VALID_DTB = 1 << 0, | |
| 103 | + | |
| 104 | + /* | |
| 105 | + * This builds on ASSUME_VALID_DTB and further assumes that libfdt | |
| 106 | + * functions are called with valid parameters, i.e. not trigger | |
| 107 | + * FDT_ERR_BADOFFSET or offsets that are out of bounds. It disables any | |
| 108 | + * extensive checking of parameters and the device tree, making various | |
| 109 | + * assumptions about correctness. | |
| 110 | + * | |
| 111 | + * It doesn't make sense to enable this assumption unless | |
| 112 | + * ASSUME_VALID_DTB is also enabled. | |
| 113 | + */ | |
| 114 | + ASSUME_VALID_INPUT = 1 << 1, | |
| 115 | + | |
| 116 | + /* | |
| 117 | + * This disables checks for device-tree version and removes all code | |
| 118 | + * which handles older versions. | |
| 119 | + * | |
| 120 | + * Only enable this if you know you have a device tree with the latest | |
| 121 | + * version. | |
| 122 | + */ | |
| 123 | + ASSUME_LATEST = 1 << 2, | |
| 124 | + | |
| 125 | + /* | |
| 126 | + * This assumes that it is OK for a failed addition to the device tree, | |
| 127 | + * due to lack of space or some other problem, to skip any rollback | |
| 128 | + * steps (such as dropping the property name from the string table). | |
| 129 | + * This is safe to enable in most circumstances, even though it may | |
| 130 | + * leave the tree in a sub-optimal state. | |
| 131 | + */ | |
| 132 | + ASSUME_NO_ROLLBACK = 1 << 3, | |
| 133 | + | |
| 134 | + /* | |
| 135 | + * This assumes that the device tree components appear in a 'convenient' | |
| 136 | + * order, i.e. the memory reservation block first, then the structure | |
| 137 | + * block and finally the string block. | |
| 138 | + * | |
| 139 | + * This order is not specified by the device-tree specification, | |
| 140 | + * but is expected by libfdt. The device-tree compiler always created | |
| 141 | + * device trees with this order. | |
| 142 | + * | |
| 143 | + * This assumption disables a check in fdt_open_into() and removes the | |
| 144 | + * ability to fix the problem there. This is safe if you know that the | |
| 145 | + * device tree is correctly ordered. See fdt_blocks_misordered_(). | |
| 146 | + */ | |
| 147 | + ASSUME_LIBFDT_ORDER = 1 << 4, | |
| 148 | + | |
| 149 | + /* | |
| 150 | + * This assumes that libfdt itself does not have any internal bugs. It | |
| 151 | + * drops certain checks that should never be needed unless libfdt has an | |
| 152 | + * undiscovered bug. | |
| 153 | + * | |
| 154 | + * This can generally be considered safe to enable. | |
| 155 | + */ | |
| 156 | + ASSUME_LIBFDT_FLAWLESS = 1 << 5, | |
| 157 | +}; | |
| 158 | + | |
| 159 | +/** | |
| 160 | + * can_assume_() - check if a particular assumption is enabled | |
| 161 | + * | |
| 162 | + * @mask: Mask to check (ASSUME_...) | |
| 163 | + * @return true if that assumption is enabled, else false | |
| 164 | + */ | |
| 165 | +static inline bool can_assume_(int mask) | |
| 166 | +{ | |
| 167 | + return FDT_ASSUME_MASK & mask; | |
| 168 | +} | |
| 169 | + | |
| 170 | +/** helper macros for checking assumptions */ | |
| 171 | +#define can_assume(_assume) can_assume_(ASSUME_ ## _assume) | |
| 172 | + | |
| 51 | 173 | #endif /* LIBFDT_INTERNAL_H */ |
| @@ -1 +1 @@ | ||
| 1 | −#define DTC_VERSION "DTC 1.5.0-gc40aeb60" | |
| 1 | +#define DTC_VERSION "DTC 1.6.0-g87a656ae" | |