2540 lines · 87.7 KB · C
RawDownload
/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */#ifndef LIBFDT_H#define LIBFDT_H/* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. */ #include "libfdt_env.h"#include "fdt.h" #ifdef __cplusplusextern "C" {#endif #define FDT_FIRST_SUPPORTED_VERSION	0x02#define FDT_LAST_COMPATIBLE_VERSION	0x10#define FDT_LAST_SUPPORTED_VERSION	0x11 /* Error codes: informative error codes */#define FDT_ERR_NOTFOUND	1	/* FDT_ERR_NOTFOUND: The requested node or property does not exist */#define FDT_ERR_EXISTS		2	/* FDT_ERR_EXISTS: Attempted to create a node or property which	 * already exists */#define FDT_ERR_NOSPACE		3	/* FDT_ERR_NOSPACE: Operation needed to expand the device	 * tree, but its buffer did not have sufficient space to	 * contain the expanded tree. Use fdt_open_into() to move the	 * device tree to a buffer with more space. */ /* Error codes: codes for bad parameters */#define FDT_ERR_BADOFFSET	4	/* FDT_ERR_BADOFFSET: Function was passed a structure block	 * offset which is out-of-bounds, or which points to an	 * unsuitable part of the structure for the operation. */#define FDT_ERR_BADPATH		5	/* FDT_ERR_BADPATH: Function was passed a badly formatted path	 * (e.g. missing a leading / for a function which requires an	 * absolute path) */#define FDT_ERR_BADPHANDLE	6	/* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle.	 * This can be caused either by an invalid phandle property	 * length, or the phandle value was either 0 or -1, which are	 * not permitted. */#define FDT_ERR_BADSTATE	7	/* FDT_ERR_BADSTATE: Function was passed an incomplete device	 * tree created by the sequential-write functions, which is	 * not sufficiently complete for the requested operation. */ /* Error codes: codes for bad device tree blobs */#define FDT_ERR_TRUNCATED	8	/* FDT_ERR_TRUNCATED: FDT or a sub-block is improperly	 * terminated (overflows, goes outside allowed bounds, or	 * isn't properly terminated).  */#define FDT_ERR_BADMAGIC	9	/* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a	 * device tree at all - it is missing the flattened device	 * tree magic number. */#define FDT_ERR_BADVERSION	10	/* FDT_ERR_BADVERSION: Given device tree has a version which	 * can't be handled by the requested operation.  For	 * read-write functions, this may mean that fdt_open_into() is	 * required to convert the tree to the expected version. */#define FDT_ERR_BADSTRUCTURE	11	/* FDT_ERR_BADSTRUCTURE: Given device tree has a corrupt	 * structure block or other serious error (e.g. misnested	 * nodes, or subnodes preceding properties). */#define FDT_ERR_BADLAYOUT	12	/* FDT_ERR_BADLAYOUT: For read-write functions, the given	 * device tree has it's sub-blocks in an order that the	 * function can't handle (memory reserve map, then structure,	 * then strings).  Use fdt_open_into() to reorganize the tree	 * into a form suitable for the read-write operations. */ /* "Can't happen" error indicating a bug in libfdt */#define FDT_ERR_INTERNAL	13	/* FDT_ERR_INTERNAL: libfdt has failed an internal assertion.	 * Should never be returned, if it is, it indicates a bug in	 * libfdt itself. */ /* Errors in device tree content */#define FDT_ERR_BADNCELLS	14	/* FDT_ERR_BADNCELLS: Device tree has a #address-cells, #size-cells	 * or similar property with a bad format or value */ #define FDT_ERR_BADVALUE	15	/* FDT_ERR_BADVALUE: Device tree has a property with an unexpected	 * value. For example: a property expected to contain a string list	 * is not NUL-terminated within the length of its value. */ #define FDT_ERR_BADOVERLAY	16	/* FDT_ERR_BADOVERLAY: The device tree overlay, while	 * correctly structured, cannot be applied due to some	 * unexpected or missing value, property or node. */ #define FDT_ERR_NOPHANDLES	17	/* FDT_ERR_NOPHANDLES: The device tree doesn't have any	 * phandle available anymore without causing an overflow */ #define FDT_ERR_BADFLAGS	18	/* FDT_ERR_BADFLAGS: The function was passed a flags field that	 * contains invalid flags or an invalid combination of flags. */ #define FDT_ERR_ALIGNMENT	19	/* FDT_ERR_ALIGNMENT: The device tree base address is not 8-byte	 * aligned. */ #define FDT_ERR_MAX		19 /* constants */#define FDT_MAX_PHANDLE 0xfffffffe	/* Valid values for phandles range from 1 to 2^32-2. */ /**********************************************************************//* Low-level functions (you probably don't need these)                *//**********************************************************************/ /** * fdt_offset_ptr - safely get a byte range within the device tree blob * @fdt:	Pointer to the device tree blob * @offset:	Offset within the blob to the desired byte range * @checklen:	Required length of the byte range * * fdt_offset_ptr() returns a pointer to the byte range of length @checklen at * the given @offset within the device tree blob, after verifying that the byte * range fits entirely within the blob and does not overflow. * * returns: *	pointer to the byte range, on success *	NULL, if the requested range does not fit within the blob */#ifndef SWIG /* This function is not useful in Python */const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen);#endifstatic inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen){	return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);} /** * fdt_next_tag - get next tag in the device tree * @fdt:	Pointer to the device tree blob * @offset:	Offset within the blob to start searching * @nextoffset:	Pointer to variable to store the offset of the next tag * * fdt_next_tag() returns the tag type of the next tag in the device tree * blob starting from the given @offset. If @nextoffset is non-NULL, it will * be set to the offset immediately following the tag. * * returns: *	the tag type (FDT_BEGIN_NODE, FDT_END_NODE, FDT_PROP, FDT_NOP, FDT_END), *	FDT_END, if offset is out of bounds */uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); /* * External helpers to access words from a device tree blob. They're built * to work even with unaligned pointers on platforms (such as ARMv5) that don't * like unaligned loads and stores. */static inline uint16_t fdt16_ld(const fdt16_t *p){	const uint8_t *bp = (const uint8_t *)p; 	return ((uint16_t)bp[0] << 8) | bp[1];} static inline uint32_t fdt32_ld(const fdt32_t *p){	const uint8_t *bp = (const uint8_t *)p; 	return ((uint32_t)bp[0] << 24)		| ((uint32_t)bp[1] << 16)		| ((uint32_t)bp[2] << 8)		| bp[3];} static inline void fdt32_st(void *property, uint32_t value){	uint8_t *bp = (uint8_t *)property; 	bp[0] = value >> 24;	bp[1] = (value >> 16) & 0xff;	bp[2] = (value >> 8) & 0xff;	bp[3] = value & 0xff;} static inline uint64_t fdt64_ld(const fdt64_t *p){	const uint8_t *bp = (const uint8_t *)p; 	return ((uint64_t)bp[0] << 56)		| ((uint64_t)bp[1] << 48)		| ((uint64_t)bp[2] << 40)		| ((uint64_t)bp[3] << 32)		| ((uint64_t)bp[4] << 24)		| ((uint64_t)bp[5] << 16)		| ((uint64_t)bp[6] << 8)		| bp[7];} static inline void fdt64_st(void *property, uint64_t value){	uint8_t *bp = (uint8_t *)property; 	bp[0] = value >> 56;	bp[1] = (value >> 48) & 0xff;	bp[2] = (value >> 40) & 0xff;	bp[3] = (value >> 32) & 0xff;	bp[4] = (value >> 24) & 0xff;	bp[5] = (value >> 16) & 0xff;	bp[6] = (value >> 8) & 0xff;	bp[7] = value & 0xff;} /**********************************************************************//* Traversal functions                                                *//**********************************************************************/ int fdt_next_node(const void *fdt, int offset, int *depth); /** * fdt_first_subnode() - get offset of first direct subnode * @fdt:	FDT blob * @offset:	Offset of node to check * * Return: offset of first subnode, or -FDT_ERR_NOTFOUND if there is none */int fdt_first_subnode(const void *fdt, int offset); /** * fdt_next_subnode() - get offset of next direct subnode * @fdt:	FDT blob * @offset:	Offset of previous subnode * * After first calling fdt_first_subnode(), call this function repeatedly to * get direct subnodes of a parent node. * * Return: offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more *         subnodes */int fdt_next_subnode(const void *fdt, int offset); /** * fdt_for_each_subnode - iterate over all subnodes of a parent * * @node:	child node (int, lvalue) * @fdt:	FDT blob (const void *) * @parent:	parent node (int) * * This is actually a wrapper around a for loop and would be used like so: * *	fdt_for_each_subnode(node, fdt, parent) { *		Use node *		... *	} * *	if ((node < 0) && (node != -FDT_ERR_NOTFOUND)) { *		Error handling *	} * * Note that this is implemented as a macro and @node is used as * iterator in the loop. The parent variable be constant or even a * literal. */#define fdt_for_each_subnode(node, fdt, parent)		\	for (node = fdt_first_subnode(fdt, parent);	\	     node >= 0;					\	     node = fdt_next_subnode(fdt, node)) /**********************************************************************//* General functions                                                  *//**********************************************************************/#define fdt_get_header(fdt, field) \	(fdt32_ld(&((const struct fdt_header *)(fdt))->field))#define fdt_magic(fdt)			(fdt_get_header(fdt, magic))#define fdt_totalsize(fdt)		(fdt_get_header(fdt, totalsize))#define fdt_off_dt_struct(fdt)		(fdt_get_header(fdt, off_dt_struct))#define fdt_off_dt_strings(fdt)		(fdt_get_header(fdt, off_dt_strings))#define fdt_off_mem_rsvmap(fdt)		(fdt_get_header(fdt, off_mem_rsvmap))#define fdt_version(fdt)		(fdt_get_header(fdt, version))#define fdt_last_comp_version(fdt)	(fdt_get_header(fdt, last_comp_version))#define fdt_boot_cpuid_phys(fdt)	(fdt_get_header(fdt, boot_cpuid_phys))#define fdt_size_dt_strings(fdt)	(fdt_get_header(fdt, size_dt_strings))#define fdt_size_dt_struct(fdt)		(fdt_get_header(fdt, size_dt_struct)) #define fdt_set_hdr_(name) \	static inline void fdt_set_##name(void *fdt, uint32_t val) \	{ \		struct fdt_header *fdth = (struct fdt_header *)fdt; \		fdth->name = cpu_to_fdt32(val); \	}fdt_set_hdr_(magic)fdt_set_hdr_(totalsize)fdt_set_hdr_(off_dt_struct)fdt_set_hdr_(off_dt_strings)fdt_set_hdr_(off_mem_rsvmap)fdt_set_hdr_(version)fdt_set_hdr_(last_comp_version)fdt_set_hdr_(boot_cpuid_phys)fdt_set_hdr_(size_dt_strings)fdt_set_hdr_(size_dt_struct)#undef fdt_set_hdr_ /** * fdt_header_size - return the size of the tree's header * @fdt: pointer to a flattened device tree * * Return: size of DTB header in bytes */size_t fdt_header_size(const void *fdt); /** * fdt_header_size_ - internal function to get header size from a version number * @version: device tree version number * * Return: size of DTB header in bytes */size_t fdt_header_size_(uint32_t version); /** * fdt_check_header - sanity check a device tree header * @fdt: pointer to data which might be a flattened device tree * * fdt_check_header() checks that the given buffer contains what * appears to be a flattened device tree, and that the header contains * valid information (to the extent that can be determined from the * header alone). * * returns: *     0, if the buffer appears to contain a valid device tree *     -FDT_ERR_BADMAGIC, *     -FDT_ERR_BADVERSION, *     -FDT_ERR_BADSTATE, *     -FDT_ERR_TRUNCATED, standard meanings, as above */int fdt_check_header(const void *fdt); /** * fdt_move - move a device tree around in memory * @fdt: pointer to the device tree to move * @buf: pointer to memory where the device is to be moved * @bufsize: size of the memory space at buf * * fdt_move() relocates, if possible, the device tree blob located at * fdt to the buffer at buf of size bufsize.  The buffer may overlap * with the existing device tree blob at fdt.  Therefore, *     fdt_move(fdt, fdt, fdt_totalsize(fdt)) * should always succeed. * * returns: *     0, on success *     -FDT_ERR_NOSPACE, bufsize is insufficient to contain the device tree *     -FDT_ERR_BADMAGIC, *     -FDT_ERR_BADVERSION, *     -FDT_ERR_BADSTATE, standard meanings */int fdt_move(const void *fdt, void *buf, int bufsize); /**********************************************************************//* Read-only functions                                                *//**********************************************************************/ /** * fdt_check_full - check device tree validity * @fdt:	pointer to the device tree blob * @bufsize:	size of the buffer containing the device tree * * fdt_check_full() checks that the given buffer contains a valid * flattened device tree and that the tree structure is internally * consistent. This is a more thorough check than fdt_check_header(). * * returns: *	0, on success *	-FDT_ERR_BADMAGIC, *	-FDT_ERR_BADVERSION, *	-FDT_ERR_BADSTATE, *	-FDT_ERR_BADSTRUCTURE, *	-FDT_ERR_TRUNCATED, standard meanings */int fdt_check_full(const void *fdt, size_t bufsize); /** * fdt_get_string - retrieve a string from the strings block of a device tree * @fdt: pointer to the device tree blob * @stroffset: offset of the string within the strings block (native endian) * @lenp: optional pointer to return the string's length * * fdt_get_string() retrieves a pointer to a single string from the * strings block of the device tree blob at fdt, and optionally also * returns the string's length in *lenp. * * returns: *     a pointer to the string, on success *     NULL, if stroffset is out of bounds, or doesn't point to a valid string */const char *fdt_get_string(const void *fdt, int stroffset, int *lenp); /** * fdt_string - retrieve a string from the strings block of a device tree * @fdt: pointer to the device tree blob * @stroffset: offset of the string within the strings block (native endian) * * fdt_string() retrieves a pointer to a single string from the * strings block of the device tree blob at fdt. * * returns: *     a pointer to the string, on success *     NULL, if stroffset is out of bounds, or doesn't point to a valid string */const char *fdt_string(const void *fdt, int stroffset); /** * fdt_find_max_phandle - find and return the highest phandle in a tree * @fdt: pointer to the device tree blob * @phandle: return location for the highest phandle value found in the tree * * fdt_find_max_phandle() finds the highest phandle value in the given device * tree. The value returned in @phandle is only valid if the function returns * success. * * returns: *     0 on success or a negative error code on failure */int fdt_find_max_phandle(const void *fdt, uint32_t *phandle); /** * fdt_get_max_phandle - retrieves the highest phandle in a tree * @fdt: pointer to the device tree blob * * fdt_get_max_phandle retrieves the highest phandle in the given * device tree. This will ignore badly formatted phandles, or phandles * with a value of 0 or -1. * * This function is deprecated in favour of fdt_find_max_phandle(). * * returns: *      the highest phandle on success *      0, if no phandle was found in the device tree *      -1, if an error occurred */static inline uint32_t fdt_get_max_phandle(const void *fdt){	uint32_t phandle;	int err; 	err = fdt_find_max_phandle(fdt, &phandle);	if (err < 0)		return (uint32_t)-1; 	return phandle;} /** * fdt_generate_phandle - return a new, unused phandle for a device tree blob * @fdt: pointer to the device tree blob * @phandle: return location for the new phandle * * Walks the device tree blob and looks for the highest phandle value. On * success, the new, unused phandle value (one higher than the previously * highest phandle value in the device tree blob) will be returned in the * @phandle parameter. * * Return: 0 on success or a negative error-code on failure */int fdt_generate_phandle(const void *fdt, uint32_t *phandle); /** * fdt_num_mem_rsv - retrieve the number of memory reserve map entries * @fdt: pointer to the device tree blob * * Returns the number of entries in the device tree blob's memory * reservation map.  This does not include the terminating 0,0 entry * or any other (0,0) entries reserved for expansion. * * returns: *     the number of entries */int fdt_num_mem_rsv(const void *fdt); /** * fdt_get_mem_rsv - retrieve one memory reserve map entry * @fdt: pointer to the device tree blob * @n: index of reserve map entry * @address: pointer to 64-bit variable to hold the start address * @size: pointer to 64-bit variable to hold the size of the entry * * On success, @address and @size will contain the address and size of * the n-th reserve map entry from the device tree blob, in * native-endian format. * * returns: *     0, on success *     -FDT_ERR_BADMAGIC, *     -FDT_ERR_BADVERSION, *     -FDT_ERR_BADSTATE, standard meanings */int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size); 

Lines 1–500 of 2540.