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
Unified · Split
| @@ -352,7 +352,7 @@ static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti, · 351 unmodified lines | |||
| 352 | FAIL(c, dti, node, "node has a reg or ranges property, but no unit name"); | 352 | FAIL(c, dti, node, "node has a reg or ranges property, but no unit name"); |
| 353 | } else { | 353 | } else { |
| 354 | if (unitname[0]) | 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 | WARNING(unit_address_vs_reg, check_unit_address_vs_reg, NULL); | 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 | struct property *prop; | 766 | struct property *prop; |
| 767 | int c_addr_cells, p_addr_cells, c_size_cells, p_size_cells, entrylen; | 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 | if (!prop) | 771 | if (!prop) |
| 771 | return; | 772 | return; |
| 772 | 773 | ||
| 773 | if (!node->parent) { | 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 | return; | 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 | if (prop->val.len == 0) { | 786 | if (prop->val.len == 0) { |
| 785 | if (p_addr_cells != c_addr_cells) | 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 | "#address-cells (%d) differs from %s (%d)", | 789 | "#address-cells (%d) differs from %s (%d)", |
| 788 | c_addr_cells, node->parent->fullpath, | 790 | ranges, c_addr_cells, node->parent->fullpath, |
| 789 | p_addr_cells); | 791 | p_addr_cells); |
| 790 | if (p_size_cells != c_size_cells) | 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 | "#size-cells (%d) differs from %s (%d)", | 794 | "#size-cells (%d) differs from %s (%d)", |
| 793 | c_size_cells, node->parent->fullpath, | 795 | ranges, c_size_cells, node->parent->fullpath, |
| 794 | p_size_cells); | 796 | p_size_cells); |
| 795 | } else if ((prop->val.len % entrylen) != 0) { | 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 | "(parent #address-cells == %d, child #address-cells == %d, " | 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 | p_addr_cells, c_addr_cells, c_size_cells); | 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 | static const struct bus_type pci_bus = { | 807 | static const struct bus_type pci_bus = { |
| 805 | .name = "PCI", | 808 | .name = "PCI", |
| @@ -1780,7 +1783,7 @@ static struct check *check_table[] = { · 974 unmodified lines | |||
| 1780 | &property_name_chars_strict, | 1783 | &property_name_chars_strict, |
| 1781 | &node_name_chars_strict, | 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 | &unit_address_vs_reg, | 1788 | &unit_address_vs_reg, |
| 1786 | &unit_address_format, | 1789 | &unit_address_format, |
| @@ -23,7 +23,6 @@ LINECOMMENT "//".*\n · 22 unmodified lines | |||
| 23 | #include "srcpos.h" | 23 | #include "srcpos.h" |
| 24 | #include "dtc-parser.tab.h" | 24 | #include "dtc-parser.tab.h" |
| 25 | 25 | ||
| 26 | YYLTYPE yylloc; | ||
| 27 | extern bool treesource_error; | 26 | extern bool treesource_error; |
| 28 | 27 | ||
| 29 | /* CAUTION: this will stop working if we ever use yyless() or yyunput() */ | 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 | uint32_t totalsize = fdt_totalsize(fdt); | 20 | uint32_t totalsize = fdt_totalsize(fdt); |
| 21 | 21 | ||
| 22 | if (can_assume(VALID_DTB)) | ||
| 23 | return totalsize; | ||
| 24 | |||
| 22 | if (fdt_magic(fdt) == FDT_MAGIC) { | 25 | if (fdt_magic(fdt) == FDT_MAGIC) { |
| 23 | /* Complete tree */ | 26 | /* Complete tree */ |
| 24 | if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) | 27 | if (!can_assume(LATEST)) { |
| 25 | return -FDT_ERR_BADVERSION; | 28 | if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) |
| 26 | if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) | 29 | return -FDT_ERR_BADVERSION; |
| 27 | return -FDT_ERR_BADVERSION; | 30 | if (fdt_last_comp_version(fdt) > |
| 31 | FDT_LAST_SUPPORTED_VERSION) | ||
| 32 | return -FDT_ERR_BADVERSION; | ||
| 33 | } | ||
| 28 | } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { | 34 | } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { |
| 29 | /* Unfinished sequential-write blob */ | 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 | return -FDT_ERR_BADSTATE; | 37 | return -FDT_ERR_BADSTATE; |
| 32 | } else { | 38 | } else { |
| 33 | return -FDT_ERR_BADMAGIC; | 39 | return -FDT_ERR_BADMAGIC; |
| @@ -70,44 +76,59 @@ size_t fdt_header_size_(uint32_t version) · 36 unmodified lines | |||
| 70 | return FDT_V17_SIZE; | 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 | int fdt_check_header(const void *fdt) | 85 | int fdt_check_header(const void *fdt) |
| 74 | { | 86 | { |
| 75 | size_t hdrsize; | 87 | size_t hdrsize; |
| 76 | 88 | ||
| 77 | if (fdt_magic(fdt) != FDT_MAGIC) | 89 | if (fdt_magic(fdt) != FDT_MAGIC) |
| 78 | return -FDT_ERR_BADMAGIC; | 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 | hdrsize = fdt_header_size(fdt); | 99 | hdrsize = fdt_header_size(fdt); |
| 80 | if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) | 100 | if (!can_assume(VALID_DTB)) { |
| 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; | ||
| 89 | 101 | ||
| 90 | /* Bounds check memrsv block */ | 102 | if ((fdt_totalsize(fdt) < hdrsize) |
| 91 | if (!check_off_(hdrsize, fdt_totalsize(fdt), fdt_off_mem_rsvmap(fdt))) | 103 | || (fdt_totalsize(fdt) > INT_MAX)) |
| 92 | return -FDT_ERR_TRUNCATED; | 104 | return -FDT_ERR_TRUNCATED; |
| 93 | 105 | ||
| 94 | /* Bounds check structure block */ | 106 | /* Bounds check memrsv block */ |
| 95 | if (fdt_version(fdt) < 17) { | ||
| 96 | if (!check_off_(hdrsize, fdt_totalsize(fdt), | 107 | if (!check_off_(hdrsize, fdt_totalsize(fdt), |
| 97 | fdt_off_dt_struct(fdt))) | 108 | fdt_off_mem_rsvmap(fdt))) |
| 98 | return -FDT_ERR_TRUNCATED; | 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 | if (!check_block_(hdrsize, fdt_totalsize(fdt), | 126 | if (!check_block_(hdrsize, fdt_totalsize(fdt), |
| 101 | fdt_off_dt_struct(fdt), | 127 | fdt_off_dt_strings(fdt), |
| 102 | fdt_size_dt_struct(fdt))) | 128 | fdt_size_dt_strings(fdt))) |
| 103 | return -FDT_ERR_TRUNCATED; | 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 | return 0; | 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 | unsigned absoffset = offset + fdt_off_dt_struct(fdt); | 137 | unsigned absoffset = offset + fdt_off_dt_struct(fdt); |
| 117 | 138 | ||
| 118 | if ((absoffset < offset) | 139 | if (!can_assume(VALID_INPUT)) |
| 119 | || ((absoffset + len) < absoffset) | 140 | if ((absoffset < offset) |
| 120 | || (absoffset + len) > fdt_totalsize(fdt)) | 141 | || ((absoffset + len) < absoffset) |
| 121 | return NULL; | 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 | if (((offset + len) < offset) | 146 | if (((offset + len) < offset) |
| 125 | || ((offset + len) > fdt_size_dt_struct(fdt))) | 147 | || ((offset + len) > fdt_size_dt_struct(fdt))) |
| 126 | return NULL; | 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 | *nextoffset = -FDT_ERR_TRUNCATED; | 160 | *nextoffset = -FDT_ERR_TRUNCATED; |
| 139 | tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE); | 161 | tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE); |
| 140 | if (!tagp) | 162 | if (!can_assume(VALID_DTB) && !tagp) |
| 141 | return FDT_END; /* premature end */ | 163 | return FDT_END; /* premature end */ |
| 142 | tag = fdt32_to_cpu(*tagp); | 164 | tag = fdt32_to_cpu(*tagp); |
| 143 | offset += FDT_TAGSIZE; | 165 | offset += FDT_TAGSIZE; |
| @@ -149,18 +171,19 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) · 5 unmodified lines | |||
| 149 | do { | 171 | do { |
| 150 | p = fdt_offset_ptr(fdt, offset++, 1); | 172 | p = fdt_offset_ptr(fdt, offset++, 1); |
| 151 | } while (p && (*p != '\0')); | 173 | } while (p && (*p != '\0')); |
| 152 | if (!p) | 174 | if (!can_assume(VALID_DTB) && !p) |
| 153 | return FDT_END; /* premature end */ | 175 | return FDT_END; /* premature end */ |
| 154 | break; | 176 | break; |
| 155 | 177 | ||
| 156 | case FDT_PROP: | 178 | case FDT_PROP: |
| 157 | lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); | 179 | lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); |
| 158 | if (!lenp) | 180 | if (!can_assume(VALID_DTB) && !lenp) |
| 159 | return FDT_END; /* premature end */ | 181 | return FDT_END; /* premature end */ |
| 160 | /* skip-name offset, length and value */ | 182 | /* skip-name offset, length and value */ |
| 161 | offset += sizeof(struct fdt_property) - FDT_TAGSIZE | 183 | offset += sizeof(struct fdt_property) - FDT_TAGSIZE |
| 162 | + fdt32_to_cpu(*lenp); | 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 | ((offset - fdt32_to_cpu(*lenp)) % 8) != 0) | 187 | ((offset - fdt32_to_cpu(*lenp)) % 8) != 0) |
| 165 | offset += 4; | 188 | offset += 4; |
| 166 | break; | 189 | break; |
| @@ -183,6 +206,8 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) · 16 unmodified lines | |||
| 183 | 206 | ||
| 184 | int fdt_check_node_offset_(const void *fdt, int offset) | 207 | int fdt_check_node_offset_(const void *fdt, int offset) |
| 185 | { | 208 | { |
| 209 | if (can_assume(VALID_INPUT)) | ||
| 210 | return offset; | ||
| 186 | if ((offset < 0) || (offset % FDT_TAGSIZE) | 211 | if ((offset < 0) || (offset % FDT_TAGSIZE) |
| 187 | || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE)) | 212 | || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE)) |
| 188 | return -FDT_ERR_BADOFFSET; | 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 | const char *fdt_get_string(const void *fdt, int stroffset, int *lenp) | 34 | const char *fdt_get_string(const void *fdt, int stroffset, int *lenp) |
| 35 | { | 35 | { |
| 36 | int32_t totalsize = fdt_ro_probe_(fdt); | 36 | int32_t totalsize; |
| 37 | uint32_t absoffset = stroffset + fdt_off_dt_strings(fdt); | 37 | uint32_t absoffset; |
| 38 | size_t len; | 38 | size_t len; |
| 39 | int err; | 39 | int err; |
| 40 | const char *s, *n; | 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 | err = totalsize; | 50 | err = totalsize; |
| 43 | if (totalsize < 0) | 51 | if (totalsize < 0) |
| 44 | goto fail; | 52 | goto fail; |
| 45 | 53 | ||
| 46 | err = -FDT_ERR_BADOFFSET; | 54 | err = -FDT_ERR_BADOFFSET; |
| 55 | absoffset = stroffset + fdt_off_dt_strings(fdt); | ||
| 47 | if (absoffset >= totalsize) | 56 | if (absoffset >= totalsize) |
| 48 | goto fail; | 57 | goto fail; |
| 49 | len = totalsize - absoffset; | 58 | len = totalsize - absoffset; |
| @@ -51,7 +60,7 @@ const char *fdt_get_string(const void *fdt, int stroffset, int *lenp) · 1 unmodified line | |||
| 51 | if (fdt_magic(fdt) == FDT_MAGIC) { | 60 | if (fdt_magic(fdt) == FDT_MAGIC) { |
| 52 | if (stroffset < 0) | 61 | if (stroffset < 0) |
| 53 | goto fail; | 62 | goto fail; |
| 54 | if (fdt_version(fdt) >= 17) { | 63 | if (can_assume(LATEST) || fdt_version(fdt) >= 17) { |
| 55 | if (stroffset >= fdt_size_dt_strings(fdt)) | 64 | if (stroffset >= fdt_size_dt_strings(fdt)) |
| 56 | goto fail; | 65 | goto fail; |
| 57 | if ((fdt_size_dt_strings(fdt) - stroffset) < len) | 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 | int offset = n * sizeof(struct fdt_reserve_entry); | 160 | int offset = n * sizeof(struct fdt_reserve_entry); |
| 152 | int absoffset = fdt_off_mem_rsvmap(fdt) + offset; | 161 | int absoffset = fdt_off_mem_rsvmap(fdt) + offset; |
| 153 | 162 | ||
| 154 | if (absoffset < fdt_off_mem_rsvmap(fdt)) | 163 | if (!can_assume(VALID_INPUT)) { |
| 155 | return NULL; | 164 | if (absoffset < fdt_off_mem_rsvmap(fdt)) |
| 156 | if (absoffset > fdt_totalsize(fdt) - sizeof(struct fdt_reserve_entry)) | 165 | return NULL; |
| 157 | return NULL; | 166 | if (absoffset > fdt_totalsize(fdt) - |
| 167 | sizeof(struct fdt_reserve_entry)) | ||
| 168 | return NULL; | ||
| 169 | } | ||
| 158 | return fdt_mem_rsv_(fdt, n); | 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 | FDT_RO_PROBE(fdt); | 177 | FDT_RO_PROBE(fdt); |
| 166 | re = fdt_mem_rsv(fdt, n); | 178 | re = fdt_mem_rsv(fdt, n); |
| 167 | if (!re) | 179 | if (!can_assume(VALID_INPUT) && !re) |
| 168 | return -FDT_ERR_BADOFFSET; | 180 | return -FDT_ERR_BADOFFSET; |
| 169 | 181 | ||
| 170 | *address = fdt64_ld(&re->address); | 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 | nameptr = nh->name; | 308 | nameptr = nh->name; |
| 297 | 309 | ||
| 298 | if (fdt_version(fdt) < 0x10) { | 310 | if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) { |
| 299 | /* | 311 | /* |
| 300 | * For old FDT versions, match the naming conventions of V16: | 312 | * For old FDT versions, match the naming conventions of V16: |
| 301 | * give only the leaf name (after all /). The actual tree | 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 | int err; | 358 | int err; |
| 347 | const struct fdt_property *prop; | 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 | if (lenp) | 363 | if (lenp) |
| 351 | *lenp = err; | 364 | *lenp = err; |
| 352 | return NULL; | 365 | return NULL; |
| @@ -367,7 +380,7 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt, · 14 unmodified lines | |||
| 367 | /* Prior to version 16, properties may need realignment | 380 | /* Prior to version 16, properties may need realignment |
| 368 | * and this API does not work. fdt_getprop_*() will, however. */ | 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 | if (lenp) | 384 | if (lenp) |
| 372 | *lenp = -FDT_ERR_BADVERSION; | 385 | *lenp = -FDT_ERR_BADVERSION; |
| 373 | return NULL; | 386 | return NULL; |
| @@ -388,7 +401,8 @@ static const struct fdt_property *fdt_get_property_namelen_(const void *fdt, · 14 unmodified lines | |||
| 388 | (offset = fdt_next_property_offset(fdt, offset))) { | 401 | (offset = fdt_next_property_offset(fdt, offset))) { |
| 389 | const struct fdt_property *prop; | 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 | offset = -FDT_ERR_INTERNAL; | 406 | offset = -FDT_ERR_INTERNAL; |
| 393 | break; | 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 | /* Prior to version 16, properties may need realignment | 428 | /* Prior to version 16, properties may need realignment |
| 415 | * and this API does not work. fdt_getprop_*() will, however. */ | 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 | if (lenp) | 431 | if (lenp) |
| 418 | *lenp = -FDT_ERR_BADVERSION; | 432 | *lenp = -FDT_ERR_BADVERSION; |
| 419 | return NULL; | 433 | return NULL; |
| @@ -444,8 +458,8 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, · 24 unmodified lines | |||
| 444 | return NULL; | 458 | return NULL; |
| 445 | 459 | ||
| 446 | /* Handle realignment */ | 460 | /* Handle realignment */ |
| 447 | if (fdt_version(fdt) < 0x10 && (poffset + sizeof(*prop)) % 8 && | 461 | if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 && |
| 448 | fdt32_ld(&prop->len) >= 8) | 462 | (poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8) |
| 449 | return prop->data + 4; | 463 | return prop->data + 4; |
| 450 | return prop->data; | 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 | if (namep) { | 475 | if (namep) { |
| 462 | const char *name; | 476 | const char *name; |
| 463 | int namelen; | 477 | int namelen; |
| 464 | name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff), | 478 | |
| 465 | &namelen); | 479 | if (!can_assume(VALID_INPUT)) { |
| 466 | if (!name) { | 480 | name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff), |
| 467 | if (lenp) | 481 | &namelen); |
| 468 | *lenp = namelen; | 482 | if (!name) { |
| 469 | return NULL; | 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 | /* Handle realignment */ | 493 | /* Handle realignment */ |
| 475 | if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 && | 494 | if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 && |
| 476 | fdt32_ld(&prop->len) >= 8) | 495 | (offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8) |
| 477 | return prop->data + 4; | 496 | return prop->data + 4; |
| 478 | return prop->data; | 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)) | 620 | if (!can_assume(VALID_INPUT)) { |
| 602 | return -FDT_ERR_BADOFFSET; | 621 | if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) |
| 603 | else if (offset == -FDT_ERR_BADOFFSET) | 622 | return -FDT_ERR_BADOFFSET; |
| 604 | return -FDT_ERR_BADSTRUCTURE; | 623 | else if (offset == -FDT_ERR_BADOFFSET) |
| 624 | return -FDT_ERR_BADSTRUCTURE; | ||
| 625 | } | ||
| 605 | 626 | ||
| 606 | return offset; /* error from fdt_next_node() */ | 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 | err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth); | 635 | err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth); |
| 615 | if (err) | 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 | return nodedepth; | 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 | return offset; /* error from fdt_next_node() */ | 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 | static int fdt_rw_probe_(void *fdt) | 25 | static int fdt_rw_probe_(void *fdt) |
| 26 | { | 26 | { |
| 27 | if (can_assume(VALID_DTB)) | ||
| 28 | return 0; | ||
| 27 | FDT_RO_PROBE(fdt); | 29 | FDT_RO_PROBE(fdt); |
| 28 | 30 | ||
| 29 | if (fdt_version(fdt) < 17) | 31 | if (!can_assume(LATEST) && fdt_version(fdt) < 17) |
| 30 | return -FDT_ERR_BADVERSION; | 32 | return -FDT_ERR_BADVERSION; |
| 31 | if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry), | 33 | if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry), |
| 32 | fdt_size_dt_struct(fdt))) | 34 | fdt_size_dt_struct(fdt))) |
| 33 | return -FDT_ERR_BADLAYOUT; | 35 | return -FDT_ERR_BADLAYOUT; |
| 34 | if (fdt_version(fdt) > 17) | 36 | if (!can_assume(LATEST) && fdt_version(fdt) > 17) |
| 35 | fdt_set_version(fdt, 17); | 37 | fdt_set_version(fdt, 17); |
| 36 | 38 | ||
| 37 | return 0; | 39 | return 0; |
| @@ -44,7 +46,7 @@ static int fdt_rw_probe_(void *fdt) · 6 unmodified lines | |||
| 44 | return err_; \ | 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 | return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); | 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 | static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen) | 54 | static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen) |
| 53 | { | 55 | { |
| 54 | char *p = splicepoint; | 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 | return -FDT_ERR_BADOFFSET; | 61 | return -FDT_ERR_BADOFFSET; |
| 59 | if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt)) | 62 | if ((p < (char *)fdt) || (dsize + newlen < oldlen)) |
| 60 | return -FDT_ERR_BADOFFSET; | 63 | return -FDT_ERR_BADOFFSET; |
| 61 | if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt))) | 64 | if (dsize - oldlen + newlen > fdt_totalsize(fdt)) |
| 62 | return -FDT_ERR_NOSPACE; | 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 | return 0; | 67 | return 0; |
| 65 | } | 68 | } |
| 66 | 69 | ||
| @@ -112,6 +115,15 @@ static int fdt_splice_string_(void *fdt, int newlen) · 45 unmodified lines | |||
| 112 | return 0; | 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 | static int fdt_find_add_string_(void *fdt, const char *s, int *allocated) | 127 | static int fdt_find_add_string_(void *fdt, const char *s, int *allocated) |
| 116 | { | 128 | { |
| 117 | char *strtab = (char *)fdt + fdt_off_dt_strings(fdt); | 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 | int len = strlen(s) + 1; | 132 | int len = strlen(s) + 1; |
| 121 | int err; | 133 | int err; |
| 122 | 134 | ||
| 123 | *allocated = 0; | 135 | if (!can_assume(NO_ROLLBACK)) |
| 136 | *allocated = 0; | ||
| 124 | 137 | ||
| 125 | p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s); | 138 | p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s); |
| 126 | if (p) | 139 | if (p) |
| @@ -132,7 +145,8 @@ static int fdt_find_add_string_(void *fdt, const char *s, int *allocated) · 5 unmodified lines | |||
| 132 | if (err) | 145 | if (err) |
| 133 | return err; | 146 | return err; |
| 134 | 147 | ||
| 135 | *allocated = 1; | 148 | if (!can_assume(NO_ROLLBACK)) |
| 149 | *allocated = 1; | ||
| 136 | 150 | ||
| 137 | memcpy(new, s, len); | 151 | memcpy(new, s, len); |
| 138 | return (new - strtab); | 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 | err = fdt_splice_struct_(fdt, *prop, 0, proplen); | 221 | err = fdt_splice_struct_(fdt, *prop, 0, proplen); |
| 208 | if (err) { | 222 | if (err) { |
| 209 | if (allocated) | 223 | /* Delete the string if we failed to add it */ |
| 224 | if (!can_assume(NO_ROLLBACK) && allocated) | ||
| 210 | fdt_del_last_string_(fdt, name); | 225 | fdt_del_last_string_(fdt, name); |
| 211 | return err; | 226 | return err; |
| 212 | } | 227 | } |
| @@ -411,7 +426,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize) · 198 unmodified lines | |||
| 411 | mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) | 426 | mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) |
| 412 | * sizeof(struct fdt_reserve_entry); | 427 | * sizeof(struct fdt_reserve_entry); |
| 413 | 428 | ||
| 414 | if (fdt_version(fdt) >= 17) { | 429 | if (can_assume(LATEST) || fdt_version(fdt) >= 17) { |
| 415 | struct_size = fdt_size_dt_struct(fdt); | 430 | struct_size = fdt_size_dt_struct(fdt); |
| 416 | } else { | 431 | } else { |
| 417 | struct_size = 0; | 432 | struct_size = 0; |
| @@ -421,7 +436,8 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize) · 3 unmodified lines | |||
| 421 | return struct_size; | 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 | /* no further work necessary */ | 441 | /* no further work necessary */ |
| 426 | err = fdt_move(fdt, buf, bufsize); | 442 | err = fdt_move(fdt, buf, bufsize); |
| 427 | if (err) | 443 | if (err) |
| @@ -12,10 +12,13 @@ · 11 unmodified lines | |||
| 12 | 12 | ||
| 13 | static int fdt_sw_probe_(void *fdt) | 13 | static int fdt_sw_probe_(void *fdt) |
| 14 | { | 14 | { |
| 15 | if (fdt_magic(fdt) == FDT_MAGIC) | 15 | if (!can_assume(VALID_INPUT)) { |
| 16 | return -FDT_ERR_BADSTATE; | 16 | if (fdt_magic(fdt) == FDT_MAGIC) |
| 17 | else if (fdt_magic(fdt) != FDT_SW_MAGIC) | 17 | return -FDT_ERR_BADSTATE; |
| 18 | return -FDT_ERR_BADMAGIC; | 18 | else if (fdt_magic(fdt) != FDT_SW_MAGIC) |
| 19 | return -FDT_ERR_BADMAGIC; | ||
| 20 | } | ||
| 21 | |||
| 19 | return 0; | 22 | return 0; |
| 20 | } | 23 | } |
| 21 | 24 | ||
| @@ -38,7 +41,7 @@ static int fdt_sw_probe_memrsv_(void *fdt) · 16 unmodified lines | |||
| 38 | if (err) | 41 | if (err) |
| 39 | return err; | 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 | return -FDT_ERR_BADSTATE; | 45 | return -FDT_ERR_BADSTATE; |
| 43 | return 0; | 46 | return 0; |
| 44 | } | 47 | } |
| @@ -64,7 +67,8 @@ static int fdt_sw_probe_struct_(void *fdt) · 19 unmodified lines | |||
| 64 | if (err) | 67 | if (err) |
| 65 | return err; | 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 | return -FDT_ERR_BADSTATE; | 72 | return -FDT_ERR_BADSTATE; |
| 69 | return 0; | 73 | return 0; |
| 70 | } | 74 | } |
| @@ -151,7 +155,8 @@ int fdt_resize(void *fdt, void *buf, int bufsize) · 80 unmodified lines | |||
| 151 | headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); | 155 | headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); |
| 152 | tailsize = fdt_size_dt_strings(fdt); | 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 | return -FDT_ERR_INTERNAL; | 160 | return -FDT_ERR_INTERNAL; |
| 156 | 161 | ||
| 157 | if ((headsize + tailsize) > bufsize) | 162 | if ((headsize + tailsize) > bufsize) |
| @@ -266,11 +266,12 @@ fdt_set_hdr_(size_dt_struct); · 265 unmodified lines | |||
| 266 | * fdt_header_size - return the size of the tree's header | 266 | * fdt_header_size - return the size of the tree's header |
| 267 | * @fdt: pointer to a flattened device tree | 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 | size_t fdt_header_size_(uint32_t version); | 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 | * fdt_check_header - sanity check a device tree header | 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 | #define FDT_SW_MAGIC (~FDT_MAGIC) | 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 | #endif /* LIBFDT_INTERNAL_H */ | 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" |