| 1 |
|
| 2 | #ifndef LIBFDT_INTERNAL_H
|
| 3 | #define LIBFDT_INTERNAL_H
|
| 4 | |
| 5 | * libfdt - Flat Device Tree manipulation
|
| 6 | * Copyright (C) 2006 David Gibson, IBM Corporation.
|
| 7 |
|
| 8 | #include <fdt.h>
|
| 9 |
|
| 10 | #define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
|
| 11 | #define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE))
|
| 12 |
|
| 13 | int32_t fdt_ro_probe_(const void *fdt);
|
| 14 | #define FDT_RO_PROBE(fdt) \
|
| 15 | { \
|
| 16 | if (!can_assume(VALID_DTB)) { \
|
| 17 | int32_t totalsize_; \
|
| 18 | if ((totalsize_ = fdt_ro_probe_(fdt)) < 0) \
|
| 19 | return totalsize_; \
|
| 20 | } \
|
| 21 | }
|
| 22 |
|
| 23 | int fdt_check_node_offset_(const void *fdt, int offset);
|
| 24 | int fdt_check_prop_offset_(const void *fdt, int offset);
|
| 25 |
|
| 26 | const char *fdt_find_string_len_(const char *strtab, int tabsize, const char *s,
|
| 27 | int s_len);
|
| 28 | static inline const char *fdt_find_string_(const char *strtab, int tabsize,
|
| 29 | const char *s)
|
| 30 | {
|
| 31 | return fdt_find_string_len_(strtab, tabsize, s, strlen(s));
|
| 32 | }
|
| 33 |
|
| 34 | int fdt_node_end_offset_(void *fdt, int nodeoffset);
|
| 35 |
|
| 36 | static inline const void *fdt_offset_ptr_(const void *fdt, int offset)
|
| 37 | {
|
| 38 | return (const char *)fdt + fdt_off_dt_struct(fdt) + offset;
|
| 39 | }
|
| 40 |
|
| 41 | static inline void *fdt_offset_ptr_w_(void *fdt, int offset)
|
| 42 | {
|
| 43 | return (void *)(uintptr_t)fdt_offset_ptr_(fdt, offset);
|
| 44 | }
|
| 45 |
|
| 46 | static inline const struct fdt_reserve_entry *fdt_mem_rsv_(const void *fdt, int n)
|
| 47 | {
|
| 48 | const struct fdt_reserve_entry *rsv_table =
|
| 49 | (const struct fdt_reserve_entry *)
|
| 50 | ((const char *)fdt + fdt_off_mem_rsvmap(fdt));
|
| 51 |
|
| 52 | return rsv_table + n;
|
| 53 | }
|
| 54 | static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n)
|
| 55 | {
|
| 56 | return (void *)(uintptr_t)fdt_mem_rsv_(fdt, n);
|
| 57 | }
|
| 58 |
|
| 59 | |
| 60 | * Internal helpers to access structural elements of the device tree
|
| 61 | * blob (rather than for example reading integers from within property
|
| 62 | * values). We assume that we are either given a naturally aligned
|
| 63 | * address for the platform or if we are not, we are on a platform
|
| 64 | * where unaligned memory reads will be handled in a graceful manner.
|
| 65 | * If not the external helpers fdtXX_ld() from libfdt.h can be used
|
| 66 | * instead.
|
| 67 |
|
| 68 | static inline uint32_t fdt32_ld_(const fdt32_t *p)
|
| 69 | {
|
| 70 | return fdt32_to_cpu(*p);
|
| 71 | }
|
| 72 |
|
| 73 | static inline uint64_t fdt64_ld_(const fdt64_t *p)
|
| 74 | {
|
| 75 | return fdt64_to_cpu(*p);
|
| 76 | }
|
| 77 |
|
| 78 | #define FDT_SW_MAGIC (~FDT_MAGIC)
|
| 79 |
|
| 80 |
|
| 81 |
|
| 82 |
|
| 83 |
|
| 84 | #ifndef FDT_ASSUME_MASK
|
| 85 | #define FDT_ASSUME_MASK 0
|
| 86 | #endif
|
| 87 |
|
| 88 | |
| 89 | * Defines assumptions which can be enabled. Each of these can be enabled
|
| 90 | * individually. For maximum safety, don't enable any assumptions!
|
| 91 | *
|
| 92 | * For minimal code size and no safety, use ASSUME_PERFECT at your own risk.
|
| 93 | * You should have another method of validating the device tree, such as a
|
| 94 | * signature or hash check before using libfdt.
|
| 95 | *
|
| 96 | * For situations where security is not a concern it may be safe to enable
|
| 97 | * ASSUME_PERFECT.
|
| 98 |
|
| 99 | enum {
|
| 100 | |
| 101 | * This does essentially no checks. Only the latest device-tree
|
| 102 | * version is correctly handled. Inconsistencies or errors in the device
|
| 103 | * tree may cause undefined behaviour or crashes. Invalid parameters
|
| 104 | * passed to libfdt may do the same.
|
| 105 | *
|
| 106 | * If an error occurs when modifying the tree it may leave the tree in
|
| 107 | * an intermediate (but valid) state. As an example, adding a property
|
| 108 | * where there is insufficient space may result in the property name
|
| 109 | * being added to the string table even though the property itself is
|
| 110 | * not added to the struct section.
|
| 111 | *
|
| 112 | * Only use this if you have a fully validated device tree with
|
| 113 | * the latest supported version and wish to minimise code size.
|
| 114 |
|
| 115 | ASSUME_PERFECT = 0xff,
|
| 116 |
|
| 117 | |
| 118 | * This assumes that the device tree is sane. i.e. header metadata
|
| 119 | * and basic hierarchy are correct.
|
| 120 | *
|
| 121 | * With this assumption enabled, normal device trees produced by libfdt
|
| 122 | * and the compiler should be handled safely. Malicious device trees and
|
| 123 | * complete garbage may cause libfdt to behave badly or crash. Truncated
|
| 124 | * device trees (e.g. those only partially loaded) can also cause
|
| 125 | * problems.
|
| 126 | *
|
| 127 | * Note: Only checks that relate exclusively to the device tree itself
|
| 128 | * (not the parameters passed to libfdt) are disabled by this
|
| 129 | * assumption. This includes checking headers, tags and the like.
|
| 130 |
|
| 131 | ASSUME_VALID_DTB = 1 << 0,
|
| 132 |
|
| 133 | |
| 134 | * This builds on ASSUME_VALID_DTB and further assumes that libfdt
|
| 135 | * functions are called with valid parameters, i.e. not trigger
|
| 136 | * FDT_ERR_BADOFFSET or offsets that are out of bounds. It disables any
|
| 137 | * extensive checking of parameters and the device tree, making various
|
| 138 | * assumptions about correctness.
|
| 139 | *
|
| 140 | * It doesn't make sense to enable this assumption unless
|
| 141 | * ASSUME_VALID_DTB is also enabled.
|
| 142 |
|
| 143 | ASSUME_VALID_INPUT = 1 << 1,
|
| 144 |
|
| 145 | |
| 146 | * This disables checks for device-tree version and removes all code
|
| 147 | * which handles older versions.
|
| 148 | *
|
| 149 | * Only enable this if you know you have a device tree with the latest
|
| 150 | * version.
|
| 151 |
|
| 152 | ASSUME_LATEST = 1 << 2,
|
| 153 |
|
| 154 | |
| 155 | * This assumes that it is OK for a failed addition to the device tree,
|
| 156 | * due to lack of space or some other problem, to skip any rollback
|
| 157 | * steps (such as dropping the property name from the string table).
|
| 158 | * This is safe to enable in most circumstances, even though it may
|
| 159 | * leave the tree in a sub-optimal state.
|
| 160 |
|
| 161 | ASSUME_NO_ROLLBACK = 1 << 3,
|
| 162 |
|
| 163 | |
| 164 | * This assumes that the device tree components appear in a 'convenient'
|
| 165 | * order, i.e. the memory reservation block first, then the structure
|
| 166 | * block and finally the string block.
|
| 167 | *
|
| 168 | * This order is not specified by the device-tree specification,
|
| 169 | * but is expected by libfdt. The device-tree compiler always created
|
| 170 | * device trees with this order.
|
| 171 | *
|
| 172 | * This assumption disables a check in fdt_open_into() and removes the
|
| 173 | * ability to fix the problem there. This is safe if you know that the
|
| 174 | * device tree is correctly ordered. See fdt_blocks_misordered_().
|
| 175 |
|
| 176 | ASSUME_LIBFDT_ORDER = 1 << 4,
|
| 177 |
|
| 178 | |
| 179 | * This assumes that libfdt itself does not have any internal bugs. It
|
| 180 | * drops certain checks that should never be needed unless libfdt has an
|
| 181 | * undiscovered bug.
|
| 182 | *
|
| 183 | * This can generally be considered safe to enable.
|
| 184 |
|
| 185 | ASSUME_LIBFDT_FLAWLESS = 1 << 5,
|
| 186 | };
|
| 187 |
|
| 188 | |
| 189 | * can_assume_() - check if a particular assumption is enabled
|
| 190 | *
|
| 191 | * @mask: Mask to check (ASSUME_...)
|
| 192 | * @return true if that assumption is enabled, else false
|
| 193 |
|
| 194 | static inline bool can_assume_(int mask)
|
| 195 | {
|
| 196 | return FDT_ASSUME_MASK & mask;
|
| 197 | }
|
| 198 |
|
| 199 |
|
| 200 | #define can_assume(_assume) can_assume_(ASSUME_ ## _assume)
|
| 201 |
|
| 202 | #endif
|