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