添加rtthread相关代码
This commit is contained in:
		
							
								
								
									
										10
									
								
								riscv/rtthread/components/drivers/fdt/libfdt/SConscript
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										10
									
								
								riscv/rtthread/components/drivers/fdt/libfdt/SConscript
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| from building import * | ||||
|  | ||||
| cwd     = GetCurrentDir() | ||||
| src     = Glob('*.c') | ||||
|  | ||||
| CPPPATH = [cwd] | ||||
|  | ||||
| group = DefineGroup('FDT', src, depend = ['RT_USING_FDTLIB'], CPPPATH = CPPPATH) | ||||
|  | ||||
| Return('group') | ||||
							
								
								
									
										249
									
								
								riscv/rtthread/components/drivers/fdt/libfdt/fdt.c
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										249
									
								
								riscv/rtthread/components/drivers/fdt/libfdt/fdt.c
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,249 @@ | ||||
| /* | ||||
|  * libfdt - Flat Device Tree manipulation | ||||
|  * Copyright (C) 2006 David Gibson, IBM Corporation. | ||||
|  * | ||||
|  * libfdt is dual licensed: you can use it either under the terms of | ||||
|  * the GPL, or the BSD license, at your option. | ||||
|  * | ||||
|  *  a) This library is free software; you can redistribute it and/or | ||||
|  *     modify it under the terms of the GNU General Public License as | ||||
|  *     published by the Free Software Foundation; either version 2 of the | ||||
|  *     License, or (at your option) any later version. | ||||
|  * | ||||
|  *     This library is distributed in the hope that it will be useful, | ||||
|  *     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *     GNU General Public License for more details. | ||||
|  * | ||||
|  *     You should have received a copy of the GNU General Public | ||||
|  *     License along with this library; if not, write to the Free | ||||
|  *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | ||||
|  *     MA 02110-1301 USA | ||||
|  * | ||||
|  * Alternatively, | ||||
|  * | ||||
|  *  b) Redistribution and use in source and binary forms, with or | ||||
|  *     without modification, are permitted provided that the following | ||||
|  *     conditions are met: | ||||
|  * | ||||
|  *     1. Redistributions of source code must retain the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer. | ||||
|  *     2. Redistributions in binary form must reproduce the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer in the documentation and/or other materials | ||||
|  *        provided with the distribution. | ||||
|  * | ||||
|  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | ||||
|  *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | ||||
|  *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||||
|  *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||||
|  *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|  *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|  *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||
|  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||||
|  *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||||
|  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| #include "libfdt_env.h" | ||||
| #include "fdt.h" | ||||
| #include "libfdt.h" | ||||
| #include "libfdt_internal.h" | ||||
|  | ||||
| int fdt_check_header(const void *fdt) | ||||
| { | ||||
|     if (fdt_magic(fdt) == FDT_MAGIC) { | ||||
|         /* Complete tree */ | ||||
|         if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) | ||||
|             return -FDT_ERR_BADVERSION; | ||||
|         if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) | ||||
|             return -FDT_ERR_BADVERSION; | ||||
|     } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { | ||||
|         /* Unfinished sequential-write blob */ | ||||
|         if (fdt_size_dt_struct(fdt) == 0) | ||||
|             return -FDT_ERR_BADSTATE; | ||||
|     } else { | ||||
|         return -FDT_ERR_BADMAGIC; | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) | ||||
| { | ||||
|     unsigned absoffset = offset + fdt_off_dt_struct(fdt); | ||||
|  | ||||
|     if ((absoffset < offset) | ||||
|         || ((absoffset + len) < absoffset) | ||||
|         || (absoffset + len) > fdt_totalsize(fdt)) | ||||
|         return NULL; | ||||
|  | ||||
|     if (fdt_version(fdt) >= 0x11) | ||||
|         if (((offset + len) < offset) | ||||
|             || ((offset + len) > fdt_size_dt_struct(fdt))) | ||||
|             return NULL; | ||||
|  | ||||
|     return _fdt_offset_ptr(fdt, offset); | ||||
| } | ||||
|  | ||||
| uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) | ||||
| { | ||||
|     const fdt32_t *tagp, *lenp; | ||||
|     uint32_t tag; | ||||
|     int offset = startoffset; | ||||
|     const char *p; | ||||
|  | ||||
|     *nextoffset = -FDT_ERR_TRUNCATED; | ||||
|     tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE); | ||||
|     if (!tagp) | ||||
|         return FDT_END; /* premature end */ | ||||
|     tag = fdt32_to_cpu(*tagp); | ||||
|     offset += FDT_TAGSIZE; | ||||
|  | ||||
|     *nextoffset = -FDT_ERR_BADSTRUCTURE; | ||||
|     switch (tag) { | ||||
|     case FDT_BEGIN_NODE: | ||||
|         /* skip name */ | ||||
|         do { | ||||
|             p = fdt_offset_ptr(fdt, offset++, 1); | ||||
|         } while (p && (*p != '\0')); | ||||
|         if (!p) | ||||
|             return FDT_END; /* premature end */ | ||||
|         break; | ||||
|  | ||||
|     case FDT_PROP: | ||||
|         lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); | ||||
|         if (!lenp) | ||||
|             return FDT_END; /* premature end */ | ||||
|         /* skip-name offset, length and value */ | ||||
|         offset += sizeof(struct fdt_property) - FDT_TAGSIZE | ||||
|             + fdt32_to_cpu(*lenp); | ||||
|         break; | ||||
|  | ||||
|     case FDT_END: | ||||
|     case FDT_END_NODE: | ||||
|     case FDT_NOP: | ||||
|         break; | ||||
|  | ||||
|     default: | ||||
|         return FDT_END; | ||||
|     } | ||||
|  | ||||
|     if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset)) | ||||
|         return FDT_END; /* premature end */ | ||||
|  | ||||
|     *nextoffset = FDT_TAGALIGN(offset); | ||||
|     return tag; | ||||
| } | ||||
|  | ||||
| int _fdt_check_node_offset(const void *fdt, int offset) | ||||
| { | ||||
|     if ((offset < 0) || (offset % FDT_TAGSIZE) | ||||
|         || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE)) | ||||
|         return -FDT_ERR_BADOFFSET; | ||||
|  | ||||
|     return offset; | ||||
| } | ||||
|  | ||||
| int _fdt_check_prop_offset(const void *fdt, int offset) | ||||
| { | ||||
|     if ((offset < 0) || (offset % FDT_TAGSIZE) | ||||
|         || (fdt_next_tag(fdt, offset, &offset) != FDT_PROP)) | ||||
|         return -FDT_ERR_BADOFFSET; | ||||
|  | ||||
|     return offset; | ||||
| } | ||||
|  | ||||
| int fdt_next_node(const void *fdt, int offset, int *depth) | ||||
| { | ||||
|     int nextoffset = 0; | ||||
|     uint32_t tag; | ||||
|  | ||||
|     if (offset >= 0) | ||||
|         if ((nextoffset = _fdt_check_node_offset(fdt, offset)) < 0) | ||||
|             return nextoffset; | ||||
|  | ||||
|     do { | ||||
|         offset = nextoffset; | ||||
|         tag = fdt_next_tag(fdt, offset, &nextoffset); | ||||
|  | ||||
|         switch (tag) { | ||||
|         case FDT_PROP: | ||||
|         case FDT_NOP: | ||||
|             break; | ||||
|  | ||||
|         case FDT_BEGIN_NODE: | ||||
|             if (depth) | ||||
|                 (*depth)++; | ||||
|             break; | ||||
|  | ||||
|         case FDT_END_NODE: | ||||
|             if (depth && ((--(*depth)) < 0)) | ||||
|                 return nextoffset; | ||||
|             break; | ||||
|  | ||||
|         case FDT_END: | ||||
|             if ((nextoffset >= 0) | ||||
|                 || ((nextoffset == -FDT_ERR_TRUNCATED) && !depth)) | ||||
|                 return -FDT_ERR_NOTFOUND; | ||||
|             else | ||||
|                 return nextoffset; | ||||
|         } | ||||
|     } while (tag != FDT_BEGIN_NODE); | ||||
|  | ||||
|     return offset; | ||||
| } | ||||
|  | ||||
| int fdt_first_subnode(const void *fdt, int offset) | ||||
| { | ||||
|     int depth = 0; | ||||
|  | ||||
|     offset = fdt_next_node(fdt, offset, &depth); | ||||
|     if (offset < 0 || depth != 1) | ||||
|         return -FDT_ERR_NOTFOUND; | ||||
|  | ||||
|     return offset; | ||||
| } | ||||
|  | ||||
| int fdt_next_subnode(const void *fdt, int offset) | ||||
| { | ||||
|     int depth = 1; | ||||
|  | ||||
|     /* | ||||
|      * With respect to the parent, the depth of the next subnode will be | ||||
|      * the same as the last. | ||||
|      */ | ||||
|     do { | ||||
|         offset = fdt_next_node(fdt, offset, &depth); | ||||
|         if (offset < 0 || depth < 1) | ||||
|             return -FDT_ERR_NOTFOUND; | ||||
|     } while (depth > 1); | ||||
|  | ||||
|     return offset; | ||||
| } | ||||
|  | ||||
| const char *_fdt_find_string(const char *strtab, int tabsize, const char *s) | ||||
| { | ||||
|     int len = strlen(s) + 1; | ||||
|     const char *last = strtab + tabsize - len; | ||||
|     const char *p; | ||||
|  | ||||
|     for (p = strtab; p <= last; p++) | ||||
|         if (memcmp(p, s, len) == 0) | ||||
|             return p; | ||||
|     return NULL; | ||||
| } | ||||
|  | ||||
| int fdt_move(const void *fdt, void *buf, int bufsize) | ||||
| { | ||||
|     FDT_CHECK_HEADER(fdt); | ||||
|  | ||||
|     if (fdt_totalsize(fdt) > bufsize) | ||||
|         return -FDT_ERR_NOSPACE; | ||||
|  | ||||
|     memmove(buf, fdt, fdt_totalsize(fdt)); | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										125
									
								
								riscv/rtthread/components/drivers/fdt/libfdt/fdt.h
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										125
									
								
								riscv/rtthread/components/drivers/fdt/libfdt/fdt.h
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,125 @@ | ||||
| /* | ||||
|  * Copyright (c) 2006-2023, RT-Thread Development Team | ||||
|  * | ||||
|  * SPDX-License-Identifier: Apache-2.0 | ||||
|  * | ||||
|  * Change Logs: | ||||
|  * Date           Author       Notes | ||||
|  * 2022-12-20     RT-Thread   the first version | ||||
|  */ | ||||
|  | ||||
| #ifndef _FDT_H | ||||
| #define _FDT_H | ||||
| /* | ||||
|  * libfdt - Flat Device Tree manipulation | ||||
|  * Copyright (C) 2006 David Gibson, IBM Corporation. | ||||
|  * Copyright 2012 Kim Phillips, Freescale Semiconductor. | ||||
|  * | ||||
|  * libfdt is dual licensed: you can use it either under the terms of | ||||
|  * the GPL, or the BSD license, at your option. | ||||
|  * | ||||
|  *  a) This library is free software; you can redistribute it and/or | ||||
|  *     modify it under the terms of the GNU General Public License as | ||||
|  *     published by the Free Software Foundation; either version 2 of the | ||||
|  *     License, or (at your option) any later version. | ||||
|  * | ||||
|  *     This library is distributed in the hope that it will be useful, | ||||
|  *     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *     GNU General Public License for more details. | ||||
|  * | ||||
|  *     You should have received a copy of the GNU General Public | ||||
|  *     License along with this library; if not, write to the Free | ||||
|  *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | ||||
|  *     MA 02110-1301 USA | ||||
|  * | ||||
|  * Alternatively, | ||||
|  * | ||||
|  *  b) Redistribution and use in source and binary forms, with or | ||||
|  *     without modification, are permitted provided that the following | ||||
|  *     conditions are met: | ||||
|  * | ||||
|  *     1. Redistributions of source code must retain the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer. | ||||
|  *     2. Redistributions in binary form must reproduce the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer in the documentation and/or other materials | ||||
|  *        provided with the distribution. | ||||
|  * | ||||
|  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | ||||
|  *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | ||||
|  *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||||
|  *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||||
|  *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|  *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|  *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||
|  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||||
|  *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||||
|  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
|  | ||||
| #ifndef __ASSEMBLY__ | ||||
|  | ||||
| #include <errno.h> | ||||
| #include <unistd.h> | ||||
| #include <fcntl.h> | ||||
|  | ||||
| struct fdt_header { | ||||
|     fdt32_t magic;                  /* magic word FDT_MAGIC */ | ||||
|     fdt32_t totalsize;              /* total size of DT block */ | ||||
|     fdt32_t off_dt_struct;          /* offset to structure */ | ||||
|     fdt32_t off_dt_strings;         /* offset to strings */ | ||||
|     fdt32_t off_mem_rsvmap;         /* offset to memory reserve map */ | ||||
|     fdt32_t version;                /* format version */ | ||||
|     fdt32_t last_comp_version;      /* last compatible version */ | ||||
|  | ||||
|     /* version 2 fields below */ | ||||
|     fdt32_t boot_cpuid_phys;        /* Which physical CPU id we're | ||||
|                                     booting on */ | ||||
|     /* version 3 fields below */ | ||||
|     fdt32_t size_dt_strings;        /* size of the strings block */ | ||||
|  | ||||
|     /* version 17 fields below */ | ||||
|     fdt32_t size_dt_struct;         /* size of the structure block */ | ||||
| }; | ||||
|  | ||||
| struct fdt_reserve_entry { | ||||
|     fdt64_t address; | ||||
|     fdt64_t size; | ||||
| }; | ||||
|  | ||||
| struct fdt_node_header { | ||||
|     fdt32_t tag; | ||||
|     char name[0]; | ||||
| }; | ||||
|  | ||||
| struct fdt_property { | ||||
|     fdt32_t tag; | ||||
|     fdt32_t len; | ||||
|     fdt32_t nameoff; | ||||
|     char data[0]; | ||||
| }; | ||||
|  | ||||
| #endif /* !__ASSEMBLY */ | ||||
|  | ||||
| #define FDT_MAGIC    0xd00dfeed    /* 4: version, 4: total size */ | ||||
| #define FDT_TAGSIZE    sizeof(fdt32_t) | ||||
|  | ||||
| #define FDT_BEGIN_NODE    0x1        /* Start node: full name */ | ||||
| #define FDT_END_NODE    0x2        /* End node */ | ||||
| #define FDT_PROP    0x3        /* Property: name off, | ||||
|                        size, content */ | ||||
| #define FDT_NOP        0x4        /* nop */ | ||||
| #define FDT_END        0x9 | ||||
|  | ||||
| #define FDT_V1_SIZE    (7*sizeof(fdt32_t)) | ||||
| #define FDT_V2_SIZE    (FDT_V1_SIZE + sizeof(fdt32_t)) | ||||
| #define FDT_V3_SIZE    (FDT_V2_SIZE + sizeof(fdt32_t)) | ||||
| #define FDT_V16_SIZE    FDT_V3_SIZE | ||||
| #define FDT_V17_SIZE    (FDT_V16_SIZE + sizeof(fdt32_t)) | ||||
|  | ||||
| #endif /* _FDT_H */ | ||||
							
								
								
									
										99
									
								
								riscv/rtthread/components/drivers/fdt/libfdt/fdt_addresses.c
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										99
									
								
								riscv/rtthread/components/drivers/fdt/libfdt/fdt_addresses.c
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,99 @@ | ||||
| // SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) | ||||
| /* | ||||
|  * libfdt - Flat Device Tree manipulation | ||||
|  * Copyright (C) 2014 David Gibson <david@gibson.dropbear.id.au> | ||||
|  * Copyright (C) 2018 embedded brains GmbH | ||||
|  */ | ||||
| #include "libfdt_env.h" | ||||
| #include <fdt.h> | ||||
| #include <libfdt.h> | ||||
| #include "libfdt_internal.h" | ||||
|  | ||||
| static int fdt_cells(const void *fdt, int nodeoffset, const char *name) | ||||
| { | ||||
|     const fdt32_t *c; | ||||
|     uint32_t val; | ||||
|     int len; | ||||
|  | ||||
|     c = fdt_getprop(fdt, nodeoffset, name, &len); | ||||
|     if (!c) | ||||
|         return len; | ||||
|  | ||||
|     if (len != sizeof(*c)) | ||||
|         return -FDT_ERR_BADNCELLS; | ||||
|  | ||||
|     val = fdt32_to_cpu(*c); | ||||
|     if (val > FDT_MAX_NCELLS) | ||||
|         return -FDT_ERR_BADNCELLS; | ||||
|  | ||||
|     return (int)val; | ||||
| } | ||||
|  | ||||
| int fdt_address_cells(const void *fdt, int nodeoffset) | ||||
| { | ||||
|     int val; | ||||
|  | ||||
|     val = fdt_cells(fdt, nodeoffset, "#address-cells"); | ||||
|     if (val == 0) | ||||
|         return -FDT_ERR_BADNCELLS; | ||||
|     if (val == -FDT_ERR_NOTFOUND) | ||||
|         return 2; | ||||
|     return val; | ||||
| } | ||||
|  | ||||
| int fdt_size_cells(const void *fdt, int nodeoffset) | ||||
| { | ||||
|     int val; | ||||
|  | ||||
|     val = fdt_cells(fdt, nodeoffset, "#size-cells"); | ||||
|     if (val == -FDT_ERR_NOTFOUND) | ||||
|         return 1; | ||||
|     return val; | ||||
| } | ||||
|  | ||||
| /* This function assumes that [address|size]_cells is 1 or 2 */ | ||||
| int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset, | ||||
|                  const char *name, uint64_t addr, uint64_t size) | ||||
| { | ||||
|     int addr_cells, size_cells, ret; | ||||
|     uint8_t data[sizeof(fdt64_t) * 2], *prop; | ||||
|  | ||||
|     ret = fdt_address_cells(fdt, parent); | ||||
|     if (ret < 0) | ||||
|         return ret; | ||||
|     addr_cells = ret; | ||||
|  | ||||
|     ret = fdt_size_cells(fdt, parent); | ||||
|     if (ret < 0) | ||||
|         return ret; | ||||
|     size_cells = ret; | ||||
|  | ||||
|     /* check validity of address */ | ||||
|     prop = data; | ||||
|     if (addr_cells == 1) { | ||||
|         if ((addr > UINT32_MAX) || ((UINT32_MAX + 1 - addr) < size)) | ||||
|             return -FDT_ERR_BADVALUE; | ||||
|  | ||||
|         fdt32_st(prop, (uint32_t)addr); | ||||
|     } else if (addr_cells == 2) { | ||||
|         fdt64_st(prop, addr); | ||||
|     } else { | ||||
|         return -FDT_ERR_BADNCELLS; | ||||
|     } | ||||
|  | ||||
|     /* check validity of size */ | ||||
|     prop += addr_cells * sizeof(fdt32_t); | ||||
|     if (size_cells == 1) { | ||||
|         if (size > UINT32_MAX) | ||||
|             return -FDT_ERR_BADVALUE; | ||||
|  | ||||
|         fdt32_st(prop, (uint32_t)size); | ||||
|     } else if (size_cells == 2) { | ||||
|         fdt64_st(prop, size); | ||||
|     } else { | ||||
|         return -FDT_ERR_BADNCELLS; | ||||
|     } | ||||
|  | ||||
|     return fdt_appendprop(fdt, nodeoffset, name, data, | ||||
|                   (addr_cells + size_cells) * sizeof(fdt32_t)); | ||||
| } | ||||
							
								
								
									
										84
									
								
								riscv/rtthread/components/drivers/fdt/libfdt/fdt_empty_tree.c
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										84
									
								
								riscv/rtthread/components/drivers/fdt/libfdt/fdt_empty_tree.c
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,84 @@ | ||||
| /* | ||||
|  * libfdt - Flat Device Tree manipulation | ||||
|  * Copyright (C) 2012 David Gibson, IBM Corporation. | ||||
|  * | ||||
|  * libfdt is dual licensed: you can use it either under the terms of | ||||
|  * the GPL, or the BSD license, at your option. | ||||
|  * | ||||
|  *  a) This library is free software; you can redistribute it and/or | ||||
|  *     modify it under the terms of the GNU General Public License as | ||||
|  *     published by the Free Software Foundation; either version 2 of the | ||||
|  *     License, or (at your option) any later version. | ||||
|  * | ||||
|  *     This library is distributed in the hope that it will be useful, | ||||
|  *     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *     GNU General Public License for more details. | ||||
|  * | ||||
|  *     You should have received a copy of the GNU General Public | ||||
|  *     License along with this library; if not, write to the Free | ||||
|  *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | ||||
|  *     MA 02110-1301 USA | ||||
|  * | ||||
|  * Alternatively, | ||||
|  * | ||||
|  *  b) Redistribution and use in source and binary forms, with or | ||||
|  *     without modification, are permitted provided that the following | ||||
|  *     conditions are met: | ||||
|  * | ||||
|  *     1. Redistributions of source code must retain the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer. | ||||
|  *     2. Redistributions in binary form must reproduce the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer in the documentation and/or other materials | ||||
|  *        provided with the distribution. | ||||
|  * | ||||
|  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | ||||
|  *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | ||||
|  *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||||
|  *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||||
|  *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|  *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|  *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||
|  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||||
|  *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||||
|  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| #include "libfdt_env.h" | ||||
|  | ||||
| #include "fdt.h" | ||||
| #include "libfdt.h" | ||||
|  | ||||
| #include "libfdt_internal.h" | ||||
|  | ||||
| int fdt_create_empty_tree(void *buf, int bufsize) | ||||
| { | ||||
|     int err; | ||||
|  | ||||
|     err = fdt_create(buf, bufsize); | ||||
|     if (err) | ||||
|         return err; | ||||
|  | ||||
|     err = fdt_finish_reservemap(buf); | ||||
|     if (err) | ||||
|         return err; | ||||
|  | ||||
|     err = fdt_begin_node(buf, ""); | ||||
|     if (err) | ||||
|         return err; | ||||
|  | ||||
|     err =  fdt_end_node(buf); | ||||
|     if (err) | ||||
|         return err; | ||||
|  | ||||
|     err = fdt_finish(buf); | ||||
|     if (err) | ||||
|         return err; | ||||
|  | ||||
|     return fdt_open_into(buf, buf, bufsize); | ||||
| } | ||||
|  | ||||
							
								
								
									
										701
									
								
								riscv/rtthread/components/drivers/fdt/libfdt/fdt_ro.c
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										701
									
								
								riscv/rtthread/components/drivers/fdt/libfdt/fdt_ro.c
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,701 @@ | ||||
| /* | ||||
|  * libfdt - Flat Device Tree manipulation | ||||
|  * Copyright (C) 2006 David Gibson, IBM Corporation. | ||||
|  * | ||||
|  * libfdt is dual licensed: you can use it either under the terms of | ||||
|  * the GPL, or the BSD license, at your option. | ||||
|  * | ||||
|  *  a) This library is free software; you can redistribute it and/or | ||||
|  *     modify it under the terms of the GNU General Public License as | ||||
|  *     published by the Free Software Foundation; either version 2 of the | ||||
|  *     License, or (at your option) any later version. | ||||
|  * | ||||
|  *     This library is distributed in the hope that it will be useful, | ||||
|  *     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *     GNU General Public License for more details. | ||||
|  * | ||||
|  *     You should have received a copy of the GNU General Public | ||||
|  *     License along with this library; if not, write to the Free | ||||
|  *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | ||||
|  *     MA 02110-1301 USA | ||||
|  * | ||||
|  * Alternatively, | ||||
|  * | ||||
|  *  b) Redistribution and use in source and binary forms, with or | ||||
|  *     without modification, are permitted provided that the following | ||||
|  *     conditions are met: | ||||
|  * | ||||
|  *     1. Redistributions of source code must retain the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer. | ||||
|  *     2. Redistributions in binary form must reproduce the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer in the documentation and/or other materials | ||||
|  *        provided with the distribution. | ||||
|  * | ||||
|  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | ||||
|  *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | ||||
|  *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||||
|  *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||||
|  *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|  *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|  *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||
|  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||||
|  *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||||
|  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| #include "libfdt_env.h" | ||||
| #include "fdt.h" | ||||
| #include "libfdt.h" | ||||
| #include "libfdt_internal.h" | ||||
|  | ||||
| static int _fdt_nodename_eq(const void *fdt, int offset, | ||||
|                 const char *s, int len) | ||||
| { | ||||
|     const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1); | ||||
|  | ||||
|     if (! p) | ||||
|         /* short match */ | ||||
|         return 0; | ||||
|  | ||||
|     if (memcmp(p, s, len) != 0) | ||||
|         return 0; | ||||
|  | ||||
|     if (p[len] == '\0') | ||||
|         return 1; | ||||
|     else if (!memchr(s, '@', len) && (p[len] == '@')) | ||||
|         return 1; | ||||
|     else | ||||
|         return 0; | ||||
| } | ||||
|  | ||||
| const char *fdt_string(const void *fdt, int stroffset) | ||||
| { | ||||
|     return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; | ||||
| } | ||||
|  | ||||
| static int _fdt_string_eq(const void *fdt, int stroffset, | ||||
|               const char *s, int len) | ||||
| { | ||||
|     const char *p = fdt_string(fdt, stroffset); | ||||
|  | ||||
|     return (strlen(p) == len) && (memcmp(p, s, len) == 0); | ||||
| } | ||||
|  | ||||
| uint32_t fdt_get_max_phandle(const void *fdt) | ||||
| { | ||||
|     uint32_t max_phandle = 0; | ||||
|     int offset; | ||||
|  | ||||
|     for (offset = fdt_next_node(fdt, -1, NULL);; | ||||
|          offset = fdt_next_node(fdt, offset, NULL)) { | ||||
|         uint32_t phandle; | ||||
|  | ||||
|         if (offset == -FDT_ERR_NOTFOUND) | ||||
|             return max_phandle; | ||||
|  | ||||
|         if (offset < 0) | ||||
|             return (uint32_t)-1; | ||||
|  | ||||
|         phandle = fdt_get_phandle(fdt, offset); | ||||
|         if (phandle == (uint32_t)-1) | ||||
|             continue; | ||||
|  | ||||
|         if (phandle > max_phandle) | ||||
|             max_phandle = phandle; | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) | ||||
| { | ||||
|     FDT_CHECK_HEADER(fdt); | ||||
|     *address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address); | ||||
|     *size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int fdt_num_mem_rsv(const void *fdt) | ||||
| { | ||||
|     int i = 0; | ||||
|  | ||||
|     while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0) | ||||
|         i++; | ||||
|     return i; | ||||
| } | ||||
|  | ||||
| static int _nextprop(const void *fdt, int offset) | ||||
| { | ||||
|     uint32_t tag; | ||||
|     int nextoffset; | ||||
|  | ||||
|     do { | ||||
|         tag = fdt_next_tag(fdt, offset, &nextoffset); | ||||
|  | ||||
|         switch (tag) { | ||||
|         case FDT_END: | ||||
|             if (nextoffset >= 0) | ||||
|                 return -FDT_ERR_BADSTRUCTURE; | ||||
|             else | ||||
|                 return nextoffset; | ||||
|  | ||||
|         case FDT_PROP: | ||||
|             return offset; | ||||
|         } | ||||
|         offset = nextoffset; | ||||
|     } while (tag == FDT_NOP); | ||||
|  | ||||
|     return -FDT_ERR_NOTFOUND; | ||||
| } | ||||
|  | ||||
| int fdt_subnode_offset_namelen(const void *fdt, int offset, | ||||
|                    const char *name, int namelen) | ||||
| { | ||||
|     int depth; | ||||
|  | ||||
|     FDT_CHECK_HEADER(fdt); | ||||
|  | ||||
|     for (depth = 0; | ||||
|          (offset >= 0) && (depth >= 0); | ||||
|          offset = fdt_next_node(fdt, offset, &depth)) | ||||
|         if ((depth == 1) | ||||
|             && _fdt_nodename_eq(fdt, offset, name, namelen)) | ||||
|             return offset; | ||||
|  | ||||
|     if (depth < 0) | ||||
|         return -FDT_ERR_NOTFOUND; | ||||
|     return offset; /* error */ | ||||
| } | ||||
|  | ||||
| int fdt_subnode_offset(const void *fdt, int parentoffset, | ||||
|                const char *name) | ||||
| { | ||||
|     return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name)); | ||||
| } | ||||
|  | ||||
| int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen) | ||||
| { | ||||
|     const char *end = path + namelen; | ||||
|     const char *p = path; | ||||
|     int offset = 0; | ||||
|  | ||||
|     FDT_CHECK_HEADER(fdt); | ||||
|  | ||||
|     /* see if we have an alias */ | ||||
|     if (*path != '/') { | ||||
|         const char *q = memchr(path, '/', end - p); | ||||
|  | ||||
|         if (!q) | ||||
|             q = end; | ||||
|  | ||||
|         p = fdt_get_alias_namelen(fdt, p, q - p); | ||||
|         if (!p) | ||||
|             return -FDT_ERR_BADPATH; | ||||
|         offset = fdt_path_offset(fdt, p); | ||||
|  | ||||
|         p = q; | ||||
|     } | ||||
|  | ||||
|     while (p < end) { | ||||
|         const char *q; | ||||
|  | ||||
|         while (*p == '/') { | ||||
|             p++; | ||||
|             if (p == end) | ||||
|                 return offset; | ||||
|         } | ||||
|         q = memchr(p, '/', end - p); | ||||
|         if (! q) | ||||
|             q = end; | ||||
|  | ||||
|         offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p); | ||||
|         if (offset < 0) | ||||
|             return offset; | ||||
|  | ||||
|         p = q; | ||||
|     } | ||||
|  | ||||
|     return offset; | ||||
| } | ||||
|  | ||||
| int fdt_path_offset(const void *fdt, const char *path) | ||||
| { | ||||
|     return fdt_path_offset_namelen(fdt, path, strlen(path)); | ||||
| } | ||||
|  | ||||
| const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) | ||||
| { | ||||
|     const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset); | ||||
|     int err; | ||||
|  | ||||
|     if (((err = fdt_check_header(fdt)) != 0) | ||||
|         || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0)) | ||||
|             goto fail; | ||||
|  | ||||
|     if (len) | ||||
|         *len = strlen(nh->name); | ||||
|  | ||||
|     return nh->name; | ||||
|  | ||||
|  fail: | ||||
|     if (len) | ||||
|         *len = err; | ||||
|     return NULL; | ||||
| } | ||||
|  | ||||
| int fdt_first_property_offset(const void *fdt, int nodeoffset) | ||||
| { | ||||
|     int offset; | ||||
|  | ||||
|     if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0) | ||||
|         return offset; | ||||
|  | ||||
|     return _nextprop(fdt, offset); | ||||
| } | ||||
|  | ||||
| int fdt_next_property_offset(const void *fdt, int offset) | ||||
| { | ||||
|     if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0) | ||||
|         return offset; | ||||
|  | ||||
|     return _nextprop(fdt, offset); | ||||
| } | ||||
|  | ||||
| const struct fdt_property *fdt_get_property_by_offset(const void *fdt, | ||||
|                               int offset, | ||||
|                               int *lenp) | ||||
| { | ||||
|     int err; | ||||
|     const struct fdt_property *prop; | ||||
|  | ||||
|     if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) { | ||||
|         if (lenp) | ||||
|             *lenp = err; | ||||
|         return NULL; | ||||
|     } | ||||
|  | ||||
|     prop = _fdt_offset_ptr(fdt, offset); | ||||
|  | ||||
|     if (lenp) | ||||
|         *lenp = fdt32_to_cpu(prop->len); | ||||
|  | ||||
|     return prop; | ||||
| } | ||||
|  | ||||
| const struct fdt_property *fdt_get_property_namelen(const void *fdt, | ||||
|                             int offset, | ||||
|                             const char *name, | ||||
|                             int namelen, int *lenp) | ||||
| { | ||||
|     for (offset = fdt_first_property_offset(fdt, offset); | ||||
|          (offset >= 0); | ||||
|          (offset = fdt_next_property_offset(fdt, offset))) { | ||||
|         const struct fdt_property *prop; | ||||
|  | ||||
|         if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) { | ||||
|             offset = -FDT_ERR_INTERNAL; | ||||
|             break; | ||||
|         } | ||||
|         if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff), | ||||
|                    name, namelen)) | ||||
|             return prop; | ||||
|     } | ||||
|  | ||||
|     if (lenp) | ||||
|         *lenp = offset; | ||||
|     return NULL; | ||||
| } | ||||
|  | ||||
| const struct fdt_property *fdt_get_property(const void *fdt, | ||||
|                         int nodeoffset, | ||||
|                         const char *name, int *lenp) | ||||
| { | ||||
|     return fdt_get_property_namelen(fdt, nodeoffset, name, | ||||
|                     strlen(name), lenp); | ||||
| } | ||||
|  | ||||
| const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, | ||||
|                 const char *name, int namelen, int *lenp) | ||||
| { | ||||
|     const struct fdt_property *prop; | ||||
|  | ||||
|     prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp); | ||||
|     if (! prop) | ||||
|         return NULL; | ||||
|  | ||||
|     return prop->data; | ||||
| } | ||||
|  | ||||
| const void *fdt_getprop_by_offset(const void *fdt, int offset, | ||||
|                   const char **namep, int *lenp) | ||||
| { | ||||
|     const struct fdt_property *prop; | ||||
|  | ||||
|     prop = fdt_get_property_by_offset(fdt, offset, lenp); | ||||
|     if (!prop) | ||||
|         return NULL; | ||||
|     if (namep) | ||||
|         *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff)); | ||||
|     return prop->data; | ||||
| } | ||||
|  | ||||
| const void *fdt_getprop(const void *fdt, int nodeoffset, | ||||
|             const char *name, int *lenp) | ||||
| { | ||||
|     return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp); | ||||
| } | ||||
|  | ||||
| uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) | ||||
| { | ||||
|     const fdt32_t *php; | ||||
|     int len; | ||||
|  | ||||
|     /* FIXME: This is a bit sub-optimal, since we potentially scan | ||||
|      * over all the properties twice. */ | ||||
|     php = fdt_getprop(fdt, nodeoffset, "phandle", &len); | ||||
|     if (!php || (len != sizeof(*php))) { | ||||
|         php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len); | ||||
|         if (!php || (len != sizeof(*php))) | ||||
|             return 0; | ||||
|     } | ||||
|  | ||||
|     return fdt32_to_cpu(*php); | ||||
| } | ||||
|  | ||||
| const char *fdt_get_alias_namelen(const void *fdt, | ||||
|                   const char *name, int namelen) | ||||
| { | ||||
|     int aliasoffset; | ||||
|  | ||||
|     aliasoffset = fdt_path_offset(fdt, "/aliases"); | ||||
|     if (aliasoffset < 0) | ||||
|         return NULL; | ||||
|  | ||||
|     return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL); | ||||
| } | ||||
|  | ||||
| const char *fdt_get_alias(const void *fdt, const char *name) | ||||
| { | ||||
|     return fdt_get_alias_namelen(fdt, name, strlen(name)); | ||||
| } | ||||
|  | ||||
| int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) | ||||
| { | ||||
|     int pdepth = 0, p = 0; | ||||
|     int offset, depth, namelen; | ||||
|     const char *name; | ||||
|  | ||||
|     FDT_CHECK_HEADER(fdt); | ||||
|  | ||||
|     if (buflen < 2) | ||||
|         return -FDT_ERR_NOSPACE; | ||||
|  | ||||
|     for (offset = 0, depth = 0; | ||||
|          (offset >= 0) && (offset <= nodeoffset); | ||||
|          offset = fdt_next_node(fdt, offset, &depth)) { | ||||
|         while (pdepth > depth) { | ||||
|             do { | ||||
|                 p--; | ||||
|             } while (buf[p-1] != '/'); | ||||
|             pdepth--; | ||||
|         } | ||||
|  | ||||
|         if (pdepth >= depth) { | ||||
|             name = fdt_get_name(fdt, offset, &namelen); | ||||
|             if (!name) | ||||
|                 return namelen; | ||||
|             if ((p + namelen + 1) <= buflen) { | ||||
|                 memcpy(buf + p, name, namelen); | ||||
|                 p += namelen; | ||||
|                 buf[p++] = '/'; | ||||
|                 pdepth++; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (offset == nodeoffset) { | ||||
|             if (pdepth < (depth + 1)) | ||||
|                 return -FDT_ERR_NOSPACE; | ||||
|  | ||||
|             if (p > 1) /* special case so that root path is "/", not "" */ | ||||
|                 p--; | ||||
|             buf[p] = '\0'; | ||||
|             return 0; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) | ||||
|         return -FDT_ERR_BADOFFSET; | ||||
|     else if (offset == -FDT_ERR_BADOFFSET) | ||||
|         return -FDT_ERR_BADSTRUCTURE; | ||||
|  | ||||
|     return offset; /* error from fdt_next_node() */ | ||||
| } | ||||
|  | ||||
| int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, | ||||
|                  int supernodedepth, int *nodedepth) | ||||
| { | ||||
|     int offset, depth; | ||||
|     int supernodeoffset = -FDT_ERR_INTERNAL; | ||||
|  | ||||
|     FDT_CHECK_HEADER(fdt); | ||||
|  | ||||
|     if (supernodedepth < 0) | ||||
|         return -FDT_ERR_NOTFOUND; | ||||
|  | ||||
|     for (offset = 0, depth = 0; | ||||
|          (offset >= 0) && (offset <= nodeoffset); | ||||
|          offset = fdt_next_node(fdt, offset, &depth)) { | ||||
|         if (depth == supernodedepth) | ||||
|             supernodeoffset = offset; | ||||
|  | ||||
|         if (offset == nodeoffset) { | ||||
|             if (nodedepth) | ||||
|                 *nodedepth = depth; | ||||
|  | ||||
|             if (supernodedepth > depth) | ||||
|                 return -FDT_ERR_NOTFOUND; | ||||
|             else | ||||
|                 return supernodeoffset; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) | ||||
|         return -FDT_ERR_BADOFFSET; | ||||
|     else if (offset == -FDT_ERR_BADOFFSET) | ||||
|         return -FDT_ERR_BADSTRUCTURE; | ||||
|  | ||||
|     return offset; /* error from fdt_next_node() */ | ||||
| } | ||||
|  | ||||
| int fdt_node_depth(const void *fdt, int nodeoffset) | ||||
| { | ||||
|     int nodedepth; | ||||
|     int err; | ||||
|  | ||||
|     err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth); | ||||
|     if (err) | ||||
|         return (err < 0) ? err : -FDT_ERR_INTERNAL; | ||||
|     return nodedepth; | ||||
| } | ||||
|  | ||||
| int fdt_parent_offset(const void *fdt, int nodeoffset) | ||||
| { | ||||
|     int nodedepth = fdt_node_depth(fdt, nodeoffset); | ||||
|  | ||||
|     if (nodedepth < 0) | ||||
|         return nodedepth; | ||||
|     return fdt_supernode_atdepth_offset(fdt, nodeoffset, | ||||
|                         nodedepth - 1, NULL); | ||||
| } | ||||
|  | ||||
| int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, | ||||
|                   const char *propname, | ||||
|                   const void *propval, int proplen) | ||||
| { | ||||
|     int offset; | ||||
|     const void *val; | ||||
|     int len; | ||||
|  | ||||
|     FDT_CHECK_HEADER(fdt); | ||||
|  | ||||
|     /* FIXME: The algorithm here is pretty horrible: we scan each | ||||
|      * property of a node in fdt_getprop(), then if that didn't | ||||
|      * find what we want, we scan over them again making our way | ||||
|      * to the next node.  Still it's the easiest to implement | ||||
|      * approach; performance can come later. */ | ||||
|     for (offset = fdt_next_node(fdt, startoffset, NULL); | ||||
|          offset >= 0; | ||||
|          offset = fdt_next_node(fdt, offset, NULL)) { | ||||
|         val = fdt_getprop(fdt, offset, propname, &len); | ||||
|         if (val && (len == proplen) | ||||
|             && (memcmp(val, propval, len) == 0)) | ||||
|             return offset; | ||||
|     } | ||||
|  | ||||
|     return offset; /* error from fdt_next_node() */ | ||||
| } | ||||
|  | ||||
| int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) | ||||
| { | ||||
|     int offset; | ||||
|  | ||||
|     if ((phandle == 0) || (phandle == -1)) | ||||
|         return -FDT_ERR_BADPHANDLE; | ||||
|  | ||||
|     FDT_CHECK_HEADER(fdt); | ||||
|  | ||||
|     /* FIXME: The algorithm here is pretty horrible: we | ||||
|      * potentially scan each property of a node in | ||||
|      * fdt_get_phandle(), then if that didn't find what | ||||
|      * we want, we scan over them again making our way to the next | ||||
|      * node.  Still it's the easiest to implement approach; | ||||
|      * performance can come later. */ | ||||
|     for (offset = fdt_next_node(fdt, -1, NULL); | ||||
|          offset >= 0; | ||||
|          offset = fdt_next_node(fdt, offset, NULL)) { | ||||
|         if (fdt_get_phandle(fdt, offset) == phandle) | ||||
|             return offset; | ||||
|     } | ||||
|  | ||||
|     return offset; /* error from fdt_next_node() */ | ||||
| } | ||||
|  | ||||
| int fdt_stringlist_contains(const char *strlist, int listlen, const char *str) | ||||
| { | ||||
|     int len = strlen(str); | ||||
|     const char *p; | ||||
|  | ||||
|     while (listlen >= len) { | ||||
|         if (memcmp(str, strlist, len+1) == 0) | ||||
|             return 1; | ||||
|         p = memchr(strlist, '\0', listlen); | ||||
|         if (!p) | ||||
|             return 0; /* malformed strlist.. */ | ||||
|         listlen -= (p-strlist) + 1; | ||||
|         strlist = p + 1; | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property) | ||||
| { | ||||
|     const char *list, *end; | ||||
|     int length, count = 0; | ||||
|  | ||||
|     list = fdt_getprop(fdt, nodeoffset, property, &length); | ||||
|     if (!list) | ||||
|         return length; | ||||
|  | ||||
|     end = list + length; | ||||
|  | ||||
|     while (list < end) { | ||||
|         length = strnlen(list, end - list) + 1; | ||||
|  | ||||
|         /* Abort if the last string isn't properly NUL-terminated. */ | ||||
|         if (list + length > end) | ||||
|             return -FDT_ERR_BADVALUE; | ||||
|  | ||||
|         list += length; | ||||
|         count++; | ||||
|     } | ||||
|  | ||||
|     return count; | ||||
| } | ||||
|  | ||||
| int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, | ||||
|               const char *string) | ||||
| { | ||||
|     int length, len, idx = 0; | ||||
|     const char *list, *end; | ||||
|  | ||||
|     list = fdt_getprop(fdt, nodeoffset, property, &length); | ||||
|     if (!list) | ||||
|         return length; | ||||
|  | ||||
|     len = strlen(string) + 1; | ||||
|     end = list + length; | ||||
|  | ||||
|     while (list < end) { | ||||
|         length = strnlen(list, end - list) + 1; | ||||
|  | ||||
|         /* Abort if the last string isn't properly NUL-terminated. */ | ||||
|         if (list + length > end) | ||||
|             return -FDT_ERR_BADVALUE; | ||||
|  | ||||
|         if (length == len && memcmp(list, string, length) == 0) | ||||
|             return idx; | ||||
|  | ||||
|         list += length; | ||||
|         idx++; | ||||
|     } | ||||
|  | ||||
|     return -FDT_ERR_NOTFOUND; | ||||
| } | ||||
|  | ||||
| const char *fdt_stringlist_get(const void *fdt, int nodeoffset, | ||||
|                    const char *property, int idx, | ||||
|                    int *lenp) | ||||
| { | ||||
|     const char *list, *end; | ||||
|     int length; | ||||
|  | ||||
|     list = fdt_getprop(fdt, nodeoffset, property, &length); | ||||
|     if (!list) { | ||||
|         if (lenp) | ||||
|             *lenp = length; | ||||
|  | ||||
|         return NULL; | ||||
|     } | ||||
|  | ||||
|     end = list + length; | ||||
|  | ||||
|     while (list < end) { | ||||
|         length = strnlen(list, end - list) + 1; | ||||
|  | ||||
|         /* Abort if the last string isn't properly NUL-terminated. */ | ||||
|         if (list + length > end) { | ||||
|             if (lenp) | ||||
|                 *lenp = -FDT_ERR_BADVALUE; | ||||
|  | ||||
|             return NULL; | ||||
|         } | ||||
|  | ||||
|         if (idx == 0) { | ||||
|             if (lenp) | ||||
|                 *lenp = length - 1; | ||||
|  | ||||
|             return list; | ||||
|         } | ||||
|  | ||||
|         list += length; | ||||
|         idx--; | ||||
|     } | ||||
|  | ||||
|     if (lenp) | ||||
|         *lenp = -FDT_ERR_NOTFOUND; | ||||
|  | ||||
|     return NULL; | ||||
| } | ||||
|  | ||||
| int fdt_node_check_compatible(const void *fdt, int nodeoffset, | ||||
|                   const char *compatible) | ||||
| { | ||||
|     const void *prop; | ||||
|     int len; | ||||
|  | ||||
|     prop = fdt_getprop(fdt, nodeoffset, "compatible", &len); | ||||
|     if (!prop) | ||||
|         return len; | ||||
|  | ||||
|     return !fdt_stringlist_contains(prop, len, compatible); | ||||
| } | ||||
|  | ||||
| int fdt_node_offset_by_compatible(const void *fdt, int startoffset, | ||||
|                   const char *compatible) | ||||
| { | ||||
|     int offset, err; | ||||
|  | ||||
|     FDT_CHECK_HEADER(fdt); | ||||
|  | ||||
|     /* FIXME: The algorithm here is pretty horrible: we scan each | ||||
|      * property of a node in fdt_node_check_compatible(), then if | ||||
|      * that didn't find what we want, we scan over them again | ||||
|      * making our way to the next node.  Still it's the easiest to | ||||
|      * implement approach; performance can come later. */ | ||||
|     for (offset = fdt_next_node(fdt, startoffset, NULL); | ||||
|          offset >= 0; | ||||
|          offset = fdt_next_node(fdt, offset, NULL)) { | ||||
|         err = fdt_node_check_compatible(fdt, offset, compatible); | ||||
|         if ((err < 0) && (err != -FDT_ERR_NOTFOUND)) | ||||
|             return err; | ||||
|         else if (err == 0) | ||||
|             return offset; | ||||
|     } | ||||
|  | ||||
|     return offset; /* error from fdt_next_node() */ | ||||
| } | ||||
							
								
								
									
										491
									
								
								riscv/rtthread/components/drivers/fdt/libfdt/fdt_rw.c
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										491
									
								
								riscv/rtthread/components/drivers/fdt/libfdt/fdt_rw.c
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,491 @@ | ||||
| /* | ||||
|  * libfdt - Flat Device Tree manipulation | ||||
|  * Copyright (C) 2006 David Gibson, IBM Corporation. | ||||
|  * | ||||
|  * libfdt is dual licensed: you can use it either under the terms of | ||||
|  * the GPL, or the BSD license, at your option. | ||||
|  * | ||||
|  *  a) This library is free software; you can redistribute it and/or | ||||
|  *     modify it under the terms of the GNU General Public License as | ||||
|  *     published by the Free Software Foundation; either version 2 of the | ||||
|  *     License, or (at your option) any later version. | ||||
|  * | ||||
|  *     This library is distributed in the hope that it will be useful, | ||||
|  *     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *     GNU General Public License for more details. | ||||
|  * | ||||
|  *     You should have received a copy of the GNU General Public | ||||
|  *     License along with this library; if not, write to the Free | ||||
|  *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | ||||
|  *     MA 02110-1301 USA | ||||
|  * | ||||
|  * Alternatively, | ||||
|  * | ||||
|  *  b) Redistribution and use in source and binary forms, with or | ||||
|  *     without modification, are permitted provided that the following | ||||
|  *     conditions are met: | ||||
|  * | ||||
|  *     1. Redistributions of source code must retain the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer. | ||||
|  *     2. Redistributions in binary form must reproduce the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer in the documentation and/or other materials | ||||
|  *        provided with the distribution. | ||||
|  * | ||||
|  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | ||||
|  *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | ||||
|  *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||||
|  *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||||
|  *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|  *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|  *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||
|  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||||
|  *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||||
|  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| #include "libfdt_env.h" | ||||
| #include "fdt.h" | ||||
| #include "libfdt.h" | ||||
| #include "libfdt_internal.h" | ||||
|  | ||||
| static int _fdt_blocks_misordered(const void *fdt, | ||||
|                   int mem_rsv_size, int struct_size) | ||||
| { | ||||
|     return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8)) | ||||
|         || (fdt_off_dt_struct(fdt) < | ||||
|             (fdt_off_mem_rsvmap(fdt) + mem_rsv_size)) | ||||
|         || (fdt_off_dt_strings(fdt) < | ||||
|             (fdt_off_dt_struct(fdt) + struct_size)) | ||||
|         || (fdt_totalsize(fdt) < | ||||
|             (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))); | ||||
| } | ||||
|  | ||||
| static int _fdt_rw_check_header(void *fdt) | ||||
| { | ||||
|     FDT_CHECK_HEADER(fdt); | ||||
|  | ||||
|     if (fdt_version(fdt) < 17) | ||||
|         return -FDT_ERR_BADVERSION; | ||||
|     if (_fdt_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry), | ||||
|                    fdt_size_dt_struct(fdt))) | ||||
|         return -FDT_ERR_BADLAYOUT; | ||||
|     if (fdt_version(fdt) > 17) | ||||
|         fdt_set_version(fdt, 17); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| #define FDT_RW_CHECK_HEADER(fdt) \ | ||||
|     { \ | ||||
|         int __err; \ | ||||
|         if ((__err = _fdt_rw_check_header(fdt)) != 0) \ | ||||
|             return __err; \ | ||||
|     } | ||||
|  | ||||
| static inline int _fdt_data_size(void *fdt) | ||||
| { | ||||
|     return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); | ||||
| } | ||||
|  | ||||
| static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen) | ||||
| { | ||||
|     char *p = splicepoint; | ||||
|     char *end = (char *)fdt + _fdt_data_size(fdt); | ||||
|      | ||||
|     if (oldlen <= 0) | ||||
|         return -FDT_ERR_BADOFFSET; | ||||
|     if (((p + oldlen) < p) || ((p + oldlen) > end)) | ||||
|         return -FDT_ERR_BADOFFSET; | ||||
|     if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt)) | ||||
|         return -FDT_ERR_BADOFFSET; | ||||
|     if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt))) | ||||
|         return -FDT_ERR_NOSPACE; | ||||
|     memmove(p + newlen, p + oldlen, end - p - oldlen); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p, | ||||
|                    int oldn, int newn) | ||||
| { | ||||
|     int delta = (newn - oldn) * sizeof(*p); | ||||
|     int err; | ||||
|     err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p)); | ||||
|     if (err) | ||||
|         return err; | ||||
|     fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta); | ||||
|     fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int _fdt_splice_struct(void *fdt, void *p, | ||||
|                   int oldlen, int newlen) | ||||
| { | ||||
|     int delta = newlen - oldlen; | ||||
|     int err; | ||||
|  | ||||
|     if ((err = _fdt_splice(fdt, p, oldlen, newlen))) | ||||
|         return err; | ||||
|  | ||||
|     fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta); | ||||
|     fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int _fdt_splice_string(void *fdt, int newlen) | ||||
| { | ||||
|     void *p = (char *)fdt | ||||
|         + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); | ||||
|     int err; | ||||
|  | ||||
|     if ((err = _fdt_splice(fdt, p, 0, newlen))) | ||||
|         return err; | ||||
|  | ||||
|     fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int _fdt_find_add_string(void *fdt, const char *s) | ||||
| { | ||||
|     char *strtab = (char *)fdt + fdt_off_dt_strings(fdt); | ||||
|     const char *p; | ||||
|     char *new; | ||||
|     int len = strlen(s) + 1; | ||||
|     int err; | ||||
|  | ||||
|     p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s); | ||||
|     if (p) | ||||
|         /* found it */ | ||||
|         return (p - strtab); | ||||
|  | ||||
|     new = strtab + fdt_size_dt_strings(fdt); | ||||
|     err = _fdt_splice_string(fdt, len); | ||||
|     if (err) | ||||
|         return err; | ||||
|  | ||||
|     memcpy(new, s, len); | ||||
|     return (new - strtab); | ||||
| } | ||||
|  | ||||
| int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size) | ||||
| { | ||||
|     struct fdt_reserve_entry *re; | ||||
|     int err; | ||||
|  | ||||
|     FDT_RW_CHECK_HEADER(fdt); | ||||
|  | ||||
|     re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt)); | ||||
|     err = _fdt_splice_mem_rsv(fdt, re, 0, 1); | ||||
|     if (err) | ||||
|         return err; | ||||
|  | ||||
|     re->address = cpu_to_fdt64(address); | ||||
|     re->size = cpu_to_fdt64(size); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int fdt_del_mem_rsv(void *fdt, int n) | ||||
| { | ||||
|     struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n); | ||||
|  | ||||
|     FDT_RW_CHECK_HEADER(fdt); | ||||
|  | ||||
|     if (n >= fdt_num_mem_rsv(fdt)) | ||||
|         return -FDT_ERR_NOTFOUND; | ||||
|  | ||||
|     return _fdt_splice_mem_rsv(fdt, re, 1, 0); | ||||
| } | ||||
|  | ||||
| static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name, | ||||
|                 int len, struct fdt_property **prop) | ||||
| { | ||||
|     int oldlen; | ||||
|     int err; | ||||
|  | ||||
|     *prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); | ||||
|     if (! (*prop)) | ||||
|         return oldlen; | ||||
|  | ||||
|     if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen), | ||||
|                       FDT_TAGALIGN(len)))) | ||||
|         return err; | ||||
|  | ||||
|     (*prop)->len = cpu_to_fdt32(len); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int _fdt_add_property(void *fdt, int nodeoffset, const char *name, | ||||
|                  int len, struct fdt_property **prop) | ||||
| { | ||||
|     int proplen; | ||||
|     int nextoffset; | ||||
|     int namestroff; | ||||
|     int err; | ||||
|  | ||||
|     if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0) | ||||
|         return nextoffset; | ||||
|  | ||||
|     namestroff = _fdt_find_add_string(fdt, name); | ||||
|     if (namestroff < 0) | ||||
|         return namestroff; | ||||
|  | ||||
|     *prop = _fdt_offset_ptr_w(fdt, nextoffset); | ||||
|     proplen = sizeof(**prop) + FDT_TAGALIGN(len); | ||||
|  | ||||
|     err = _fdt_splice_struct(fdt, *prop, 0, proplen); | ||||
|     if (err) | ||||
|         return err; | ||||
|  | ||||
|     (*prop)->tag = cpu_to_fdt32(FDT_PROP); | ||||
|     (*prop)->nameoff = cpu_to_fdt32(namestroff); | ||||
|     (*prop)->len = cpu_to_fdt32(len); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int fdt_set_name(void *fdt, int nodeoffset, const char *name) | ||||
| { | ||||
|     char *namep; | ||||
|     int oldlen, newlen; | ||||
|     int err; | ||||
|  | ||||
|     FDT_RW_CHECK_HEADER(fdt); | ||||
|  | ||||
|     namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen); | ||||
|     if (!namep) | ||||
|         return oldlen; | ||||
|  | ||||
|     newlen = strlen(name); | ||||
|  | ||||
|     err = _fdt_splice_struct(fdt, namep, FDT_TAGALIGN(oldlen+1), | ||||
|                  FDT_TAGALIGN(newlen+1)); | ||||
|     if (err) | ||||
|         return err; | ||||
|  | ||||
|     memcpy(namep, name, newlen+1); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int fdt_setprop(void *fdt, int nodeoffset, const char *name, | ||||
|         const void *val, int len) | ||||
| { | ||||
|     struct fdt_property *prop; | ||||
|     int err; | ||||
|  | ||||
|     FDT_RW_CHECK_HEADER(fdt); | ||||
|  | ||||
|     err = _fdt_resize_property(fdt, nodeoffset, name, len, &prop); | ||||
|     if (err == -FDT_ERR_NOTFOUND) | ||||
|         err = _fdt_add_property(fdt, nodeoffset, name, len, &prop); | ||||
|     if (err) | ||||
|         return err; | ||||
|  | ||||
|     if (len) | ||||
|         memcpy(prop->data, val, len); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int fdt_appendprop(void *fdt, int nodeoffset, const char *name, | ||||
|            const void *val, int len) | ||||
| { | ||||
|     struct fdt_property *prop; | ||||
|     int err, oldlen, newlen; | ||||
|  | ||||
|     FDT_RW_CHECK_HEADER(fdt); | ||||
|  | ||||
|     prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); | ||||
|     if (prop) { | ||||
|         newlen = len + oldlen; | ||||
|         err = _fdt_splice_struct(fdt, prop->data, | ||||
|                      FDT_TAGALIGN(oldlen), | ||||
|                      FDT_TAGALIGN(newlen)); | ||||
|         if (err) | ||||
|             return err; | ||||
|         prop->len = cpu_to_fdt32(newlen); | ||||
|         memcpy(prop->data + oldlen, val, len); | ||||
|     } else { | ||||
|         err = _fdt_add_property(fdt, nodeoffset, name, len, &prop); | ||||
|         if (err) | ||||
|             return err; | ||||
|         memcpy(prop->data, val, len); | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int fdt_delprop(void *fdt, int nodeoffset, const char *name) | ||||
| { | ||||
|     struct fdt_property *prop; | ||||
|     int len, proplen; | ||||
|  | ||||
|     FDT_RW_CHECK_HEADER(fdt); | ||||
|  | ||||
|     prop = fdt_get_property_w(fdt, nodeoffset, name, &len); | ||||
|     if (! prop) | ||||
|         return len; | ||||
|  | ||||
|     proplen = sizeof(*prop) + FDT_TAGALIGN(len); | ||||
|     return _fdt_splice_struct(fdt, prop, proplen, 0); | ||||
| } | ||||
|  | ||||
| int fdt_add_subnode_namelen(void *fdt, int parentoffset, | ||||
|                 const char *name, int namelen) | ||||
| { | ||||
|     struct fdt_node_header *nh; | ||||
|     int offset, nextoffset; | ||||
|     int nodelen; | ||||
|     int err; | ||||
|     uint32_t tag; | ||||
|     fdt32_t *endtag; | ||||
|  | ||||
|     FDT_RW_CHECK_HEADER(fdt); | ||||
|  | ||||
|     offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen); | ||||
|     if (offset >= 0) | ||||
|         return -FDT_ERR_EXISTS; | ||||
|     else if (offset != -FDT_ERR_NOTFOUND) | ||||
|         return offset; | ||||
|  | ||||
|     /* Try to place the new node after the parent's properties */ | ||||
|     fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */ | ||||
|     do { | ||||
|         offset = nextoffset; | ||||
|         tag = fdt_next_tag(fdt, offset, &nextoffset); | ||||
|     } while ((tag == FDT_PROP) || (tag == FDT_NOP)); | ||||
|  | ||||
|     nh = _fdt_offset_ptr_w(fdt, offset); | ||||
|     nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE; | ||||
|  | ||||
|     err = _fdt_splice_struct(fdt, nh, 0, nodelen); | ||||
|     if (err) | ||||
|         return err; | ||||
|  | ||||
|     nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); | ||||
|     memset(nh->name, 0, FDT_TAGALIGN(namelen+1)); | ||||
|     memcpy(nh->name, name, namelen); | ||||
|     endtag = (fdt32_t *)((char *)nh + nodelen - FDT_TAGSIZE); | ||||
|     *endtag = cpu_to_fdt32(FDT_END_NODE); | ||||
|  | ||||
|     return offset; | ||||
| } | ||||
|  | ||||
| int fdt_add_subnode(void *fdt, int parentoffset, const char *name) | ||||
| { | ||||
|     return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name)); | ||||
| } | ||||
|  | ||||
| int fdt_del_node(void *fdt, int nodeoffset) | ||||
| { | ||||
|     int endoffset; | ||||
|  | ||||
|     FDT_RW_CHECK_HEADER(fdt); | ||||
|  | ||||
|     endoffset = _fdt_node_end_offset(fdt, nodeoffset); | ||||
|     if (endoffset < 0) | ||||
|         return endoffset; | ||||
|  | ||||
|     return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset), | ||||
|                   endoffset - nodeoffset, 0); | ||||
| } | ||||
|  | ||||
| static void _fdt_packblocks(const char *old, char *new, | ||||
|                 int mem_rsv_size, int struct_size) | ||||
| { | ||||
|     int mem_rsv_off, struct_off, strings_off; | ||||
|  | ||||
|     mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8); | ||||
|     struct_off = mem_rsv_off + mem_rsv_size; | ||||
|     strings_off = struct_off + struct_size; | ||||
|  | ||||
|     memmove(new + mem_rsv_off, old + fdt_off_mem_rsvmap(old), mem_rsv_size); | ||||
|     fdt_set_off_mem_rsvmap(new, mem_rsv_off); | ||||
|  | ||||
|     memmove(new + struct_off, old + fdt_off_dt_struct(old), struct_size); | ||||
|     fdt_set_off_dt_struct(new, struct_off); | ||||
|     fdt_set_size_dt_struct(new, struct_size); | ||||
|  | ||||
|     memmove(new + strings_off, old + fdt_off_dt_strings(old), | ||||
|         fdt_size_dt_strings(old)); | ||||
|     fdt_set_off_dt_strings(new, strings_off); | ||||
|     fdt_set_size_dt_strings(new, fdt_size_dt_strings(old)); | ||||
| } | ||||
|  | ||||
| int fdt_open_into(const void *fdt, void *buf, int bufsize) | ||||
| { | ||||
|     int err; | ||||
|     int mem_rsv_size, struct_size; | ||||
|     int newsize; | ||||
|     const char *fdtstart = fdt; | ||||
|     const char *fdtend = fdtstart + fdt_totalsize(fdt); | ||||
|     char *tmp; | ||||
|  | ||||
|     FDT_CHECK_HEADER(fdt); | ||||
|  | ||||
|     mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) | ||||
|         * sizeof(struct fdt_reserve_entry); | ||||
|  | ||||
|     if (fdt_version(fdt) >= 17) { | ||||
|         struct_size = fdt_size_dt_struct(fdt); | ||||
|     } else { | ||||
|         struct_size = 0; | ||||
|         while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END) | ||||
|             ; | ||||
|         if (struct_size < 0) | ||||
|             return struct_size; | ||||
|     } | ||||
|  | ||||
|     if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) { | ||||
|         /* no further work necessary */ | ||||
|         err = fdt_move(fdt, buf, bufsize); | ||||
|         if (err) | ||||
|             return err; | ||||
|         fdt_set_version(buf, 17); | ||||
|         fdt_set_size_dt_struct(buf, struct_size); | ||||
|         fdt_set_totalsize(buf, bufsize); | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     /* Need to reorder */ | ||||
|     newsize = FDT_ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size | ||||
|         + struct_size + fdt_size_dt_strings(fdt); | ||||
|  | ||||
|     if (bufsize < newsize) | ||||
|         return -FDT_ERR_NOSPACE; | ||||
|  | ||||
|     /* First attempt to build converted tree at beginning of buffer */ | ||||
|     tmp = buf; | ||||
|     /* But if that overlaps with the old tree... */ | ||||
|     if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) { | ||||
|         /* Try right after the old tree instead */ | ||||
|         tmp = (char *)(uintptr_t)fdtend; | ||||
|         if ((tmp + newsize) > ((char *)buf + bufsize)) | ||||
|             return -FDT_ERR_NOSPACE; | ||||
|     } | ||||
|  | ||||
|     _fdt_packblocks(fdt, tmp, mem_rsv_size, struct_size); | ||||
|     memmove(buf, tmp, newsize); | ||||
|  | ||||
|     fdt_set_magic(buf, FDT_MAGIC); | ||||
|     fdt_set_totalsize(buf, bufsize); | ||||
|     fdt_set_version(buf, 17); | ||||
|     fdt_set_last_comp_version(buf, 16); | ||||
|     fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt)); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int fdt_pack(void *fdt) | ||||
| { | ||||
|     int mem_rsv_size; | ||||
|  | ||||
|     FDT_RW_CHECK_HEADER(fdt); | ||||
|  | ||||
|     mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) | ||||
|         * sizeof(struct fdt_reserve_entry); | ||||
|     _fdt_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt)); | ||||
|     fdt_set_totalsize(fdt, _fdt_data_size(fdt)); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										100
									
								
								riscv/rtthread/components/drivers/fdt/libfdt/fdt_strerror.c
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										100
									
								
								riscv/rtthread/components/drivers/fdt/libfdt/fdt_strerror.c
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,100 @@ | ||||
| /* | ||||
|  * libfdt - Flat Device Tree manipulation | ||||
|  * Copyright (C) 2006 David Gibson, IBM Corporation. | ||||
|  * | ||||
|  * libfdt is dual licensed: you can use it either under the terms of | ||||
|  * the GPL, or the BSD license, at your option. | ||||
|  * | ||||
|  *  a) This library is free software; you can redistribute it and/or | ||||
|  *     modify it under the terms of the GNU General Public License as | ||||
|  *     published by the Free Software Foundation; either version 2 of the | ||||
|  *     License, or (at your option) any later version. | ||||
|  * | ||||
|  *     This library is distributed in the hope that it will be useful, | ||||
|  *     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *     GNU General Public License for more details. | ||||
|  * | ||||
|  *     You should have received a copy of the GNU General Public | ||||
|  *     License along with this library; if not, write to the Free | ||||
|  *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | ||||
|  *     MA 02110-1301 USA | ||||
|  * | ||||
|  * Alternatively, | ||||
|  * | ||||
|  *  b) Redistribution and use in source and binary forms, with or | ||||
|  *     without modification, are permitted provided that the following | ||||
|  *     conditions are met: | ||||
|  * | ||||
|  *     1. Redistributions of source code must retain the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer. | ||||
|  *     2. Redistributions in binary form must reproduce the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer in the documentation and/or other materials | ||||
|  *        provided with the distribution. | ||||
|  * | ||||
|  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | ||||
|  *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | ||||
|  *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||||
|  *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||||
|  *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|  *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|  *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||
|  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||||
|  *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||||
|  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| #include "libfdt_env.h" | ||||
| #include "fdt.h" | ||||
| #include "libfdt.h" | ||||
| #include "libfdt_internal.h" | ||||
|  | ||||
| struct fdt_errtabent { | ||||
|     const char *str; | ||||
| }; | ||||
|  | ||||
| #define FDT_ERRTABENT(val) \ | ||||
|     [(val)] = { .str = #val, } | ||||
|  | ||||
| static struct fdt_errtabent fdt_errtable[] = { | ||||
|     FDT_ERRTABENT(FDT_ERR_NOTFOUND), | ||||
|     FDT_ERRTABENT(FDT_ERR_EXISTS), | ||||
|     FDT_ERRTABENT(FDT_ERR_NOSPACE), | ||||
|  | ||||
|     FDT_ERRTABENT(FDT_ERR_BADOFFSET), | ||||
|     FDT_ERRTABENT(FDT_ERR_BADPATH), | ||||
|     FDT_ERRTABENT(FDT_ERR_BADPHANDLE), | ||||
|     FDT_ERRTABENT(FDT_ERR_BADSTATE), | ||||
|  | ||||
|     FDT_ERRTABENT(FDT_ERR_TRUNCATED), | ||||
|     FDT_ERRTABENT(FDT_ERR_BADMAGIC), | ||||
|     FDT_ERRTABENT(FDT_ERR_BADVERSION), | ||||
|     FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE), | ||||
|     FDT_ERRTABENT(FDT_ERR_BADLAYOUT), | ||||
|     FDT_ERRTABENT(FDT_ERR_INTERNAL), | ||||
|     FDT_ERRTABENT(FDT_ERR_BADNCELLS), | ||||
|     FDT_ERRTABENT(FDT_ERR_BADVALUE), | ||||
|     FDT_ERRTABENT(FDT_ERR_BADOVERLAY), | ||||
|     FDT_ERRTABENT(FDT_ERR_NOPHANDLES), | ||||
| }; | ||||
| #define FDT_ERRTABSIZE  (sizeof(fdt_errtable) / sizeof(fdt_errtable[0])) | ||||
|  | ||||
| const char *fdt_strerror(int errval) | ||||
| { | ||||
|     if (errval > 0) | ||||
|         return "<valid offset/length>"; | ||||
|     else if (errval == 0) | ||||
|         return "<no error>"; | ||||
|     else if (errval > -FDT_ERRTABSIZE) { | ||||
|         const char *s = fdt_errtable[-errval].str; | ||||
|  | ||||
|         if (s) | ||||
|             return s; | ||||
|     } | ||||
|  | ||||
|     return "<unknown error>"; | ||||
| } | ||||
							
								
								
									
										286
									
								
								riscv/rtthread/components/drivers/fdt/libfdt/fdt_sw.c
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										286
									
								
								riscv/rtthread/components/drivers/fdt/libfdt/fdt_sw.c
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,286 @@ | ||||
| /* | ||||
|  * libfdt - Flat Device Tree manipulation | ||||
|  * Copyright (C) 2006 David Gibson, IBM Corporation. | ||||
|  * | ||||
|  * libfdt is dual licensed: you can use it either under the terms of | ||||
|  * the GPL, or the BSD license, at your option. | ||||
|  * | ||||
|  *  a) This library is free software; you can redistribute it and/or | ||||
|  *     modify it under the terms of the GNU General Public License as | ||||
|  *     published by the Free Software Foundation; either version 2 of the | ||||
|  *     License, or (at your option) any later version. | ||||
|  * | ||||
|  *     This library is distributed in the hope that it will be useful, | ||||
|  *     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *     GNU General Public License for more details. | ||||
|  * | ||||
|  *     You should have received a copy of the GNU General Public | ||||
|  *     License along with this library; if not, write to the Free | ||||
|  *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | ||||
|  *     MA 02110-1301 USA | ||||
|  * | ||||
|  * Alternatively, | ||||
|  * | ||||
|  *  b) Redistribution and use in source and binary forms, with or | ||||
|  *     without modification, are permitted provided that the following | ||||
|  *     conditions are met: | ||||
|  * | ||||
|  *     1. Redistributions of source code must retain the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer. | ||||
|  *     2. Redistributions in binary form must reproduce the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer in the documentation and/or other materials | ||||
|  *        provided with the distribution. | ||||
|  * | ||||
|  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | ||||
|  *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | ||||
|  *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||||
|  *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||||
|  *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|  *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|  *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||
|  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||||
|  *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||||
|  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| #include "libfdt_env.h" | ||||
| #include "fdt.h" | ||||
| #include "libfdt.h" | ||||
| #include "libfdt_internal.h" | ||||
|  | ||||
| static int _fdt_sw_check_header(void *fdt) | ||||
| { | ||||
|     if (fdt_magic(fdt) != FDT_SW_MAGIC) | ||||
|         return -FDT_ERR_BADMAGIC; | ||||
|     /* FIXME: should check more details about the header state */ | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| #define FDT_SW_CHECK_HEADER(fdt) \ | ||||
|     { \ | ||||
|         int err; \ | ||||
|         if ((err = _fdt_sw_check_header(fdt)) != 0) \ | ||||
|             return err; \ | ||||
|     } | ||||
|  | ||||
| static void *_fdt_grab_space(void *fdt, size_t len) | ||||
| { | ||||
|     int offset = fdt_size_dt_struct(fdt); | ||||
|     int spaceleft; | ||||
|  | ||||
|     spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt) | ||||
|         - fdt_size_dt_strings(fdt); | ||||
|  | ||||
|     if ((offset + len < offset) || (offset + len > spaceleft)) | ||||
|         return NULL; | ||||
|  | ||||
|     fdt_set_size_dt_struct(fdt, offset + len); | ||||
|     return _fdt_offset_ptr_w(fdt, offset); | ||||
| } | ||||
|  | ||||
| int fdt_create(void *buf, int bufsize) | ||||
| { | ||||
|     void *fdt = buf; | ||||
|  | ||||
|     if (bufsize < sizeof(struct fdt_header)) | ||||
|         return -FDT_ERR_NOSPACE; | ||||
|  | ||||
|     memset(buf, 0, bufsize); | ||||
|  | ||||
|     fdt_set_magic(fdt, FDT_SW_MAGIC); | ||||
|     fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION); | ||||
|     fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION); | ||||
|     fdt_set_totalsize(fdt,  bufsize); | ||||
|  | ||||
|     fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header), | ||||
|                           sizeof(struct fdt_reserve_entry))); | ||||
|     fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt)); | ||||
|     fdt_set_off_dt_strings(fdt, bufsize); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int fdt_resize(void *fdt, void *buf, int bufsize) | ||||
| { | ||||
|     size_t headsize, tailsize; | ||||
|     char *oldtail, *newtail; | ||||
|  | ||||
|     FDT_SW_CHECK_HEADER(fdt); | ||||
|  | ||||
|     headsize = fdt_off_dt_struct(fdt); | ||||
|     tailsize = fdt_size_dt_strings(fdt); | ||||
|  | ||||
|     if ((headsize + tailsize) > bufsize) | ||||
|         return -FDT_ERR_NOSPACE; | ||||
|  | ||||
|     oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize; | ||||
|     newtail = (char *)buf + bufsize - tailsize; | ||||
|  | ||||
|     /* Two cases to avoid clobbering data if the old and new | ||||
|      * buffers partially overlap */ | ||||
|     if (buf <= fdt) { | ||||
|         memmove(buf, fdt, headsize); | ||||
|         memmove(newtail, oldtail, tailsize); | ||||
|     } else { | ||||
|         memmove(newtail, oldtail, tailsize); | ||||
|         memmove(buf, fdt, headsize); | ||||
|     } | ||||
|  | ||||
|     fdt_set_off_dt_strings(buf, bufsize); | ||||
|     fdt_set_totalsize(buf, bufsize); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) | ||||
| { | ||||
|     struct fdt_reserve_entry *re; | ||||
|     int offset; | ||||
|  | ||||
|     FDT_SW_CHECK_HEADER(fdt); | ||||
|  | ||||
|     if (fdt_size_dt_struct(fdt)) | ||||
|         return -FDT_ERR_BADSTATE; | ||||
|  | ||||
|     offset = fdt_off_dt_struct(fdt); | ||||
|     if ((offset + sizeof(*re)) > fdt_totalsize(fdt)) | ||||
|         return -FDT_ERR_NOSPACE; | ||||
|  | ||||
|     re = (struct fdt_reserve_entry *)((char *)fdt + offset); | ||||
|     re->address = cpu_to_fdt64(addr); | ||||
|     re->size = cpu_to_fdt64(size); | ||||
|  | ||||
|     fdt_set_off_dt_struct(fdt, offset + sizeof(*re)); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int fdt_finish_reservemap(void *fdt) | ||||
| { | ||||
|     return fdt_add_reservemap_entry(fdt, 0, 0); | ||||
| } | ||||
|  | ||||
| int fdt_begin_node(void *fdt, const char *name) | ||||
| { | ||||
|     struct fdt_node_header *nh; | ||||
|     int namelen = strlen(name) + 1; | ||||
|  | ||||
|     FDT_SW_CHECK_HEADER(fdt); | ||||
|  | ||||
|     nh = _fdt_grab_space(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen)); | ||||
|     if (! nh) | ||||
|         return -FDT_ERR_NOSPACE; | ||||
|  | ||||
|     nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); | ||||
|     memcpy(nh->name, name, namelen); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int fdt_end_node(void *fdt) | ||||
| { | ||||
|     fdt32_t *en; | ||||
|  | ||||
|     FDT_SW_CHECK_HEADER(fdt); | ||||
|  | ||||
|     en = _fdt_grab_space(fdt, FDT_TAGSIZE); | ||||
|     if (! en) | ||||
|         return -FDT_ERR_NOSPACE; | ||||
|  | ||||
|     *en = cpu_to_fdt32(FDT_END_NODE); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int _fdt_find_add_string(void *fdt, const char *s) | ||||
| { | ||||
|     char *strtab = (char *)fdt + fdt_totalsize(fdt); | ||||
|     const char *p; | ||||
|     int strtabsize = fdt_size_dt_strings(fdt); | ||||
|     int len = strlen(s) + 1; | ||||
|     int struct_top, offset; | ||||
|  | ||||
|     p = _fdt_find_string(strtab - strtabsize, strtabsize, s); | ||||
|     if (p) | ||||
|         return p - strtab; | ||||
|  | ||||
|     /* Add it */ | ||||
|     offset = -strtabsize - len; | ||||
|     struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); | ||||
|     if (fdt_totalsize(fdt) + offset < struct_top) | ||||
|         return 0; /* no more room :( */ | ||||
|  | ||||
|     memcpy(strtab + offset, s, len); | ||||
|     fdt_set_size_dt_strings(fdt, strtabsize + len); | ||||
|     return offset; | ||||
| } | ||||
|  | ||||
| int fdt_property(void *fdt, const char *name, const void *val, int len) | ||||
| { | ||||
|     struct fdt_property *prop; | ||||
|     int nameoff; | ||||
|  | ||||
|     FDT_SW_CHECK_HEADER(fdt); | ||||
|  | ||||
|     nameoff = _fdt_find_add_string(fdt, name); | ||||
|     if (nameoff == 0) | ||||
|         return -FDT_ERR_NOSPACE; | ||||
|  | ||||
|     prop = _fdt_grab_space(fdt, sizeof(*prop) + FDT_TAGALIGN(len)); | ||||
|     if (! prop) | ||||
|         return -FDT_ERR_NOSPACE; | ||||
|  | ||||
|     prop->tag = cpu_to_fdt32(FDT_PROP); | ||||
|     prop->nameoff = cpu_to_fdt32(nameoff); | ||||
|     prop->len = cpu_to_fdt32(len); | ||||
|     memcpy(prop->data, val, len); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int fdt_finish(void *fdt) | ||||
| { | ||||
|     char *p = (char *)fdt; | ||||
|     fdt32_t *end; | ||||
|     int oldstroffset, newstroffset; | ||||
|     uint32_t tag; | ||||
|     int offset, nextoffset; | ||||
|  | ||||
|     FDT_SW_CHECK_HEADER(fdt); | ||||
|  | ||||
|     /* Add terminator */ | ||||
|     end = _fdt_grab_space(fdt, sizeof(*end)); | ||||
|     if (! end) | ||||
|         return -FDT_ERR_NOSPACE; | ||||
|     *end = cpu_to_fdt32(FDT_END); | ||||
|  | ||||
|     /* Relocate the string table */ | ||||
|     oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt); | ||||
|     newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); | ||||
|     memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt)); | ||||
|     fdt_set_off_dt_strings(fdt, newstroffset); | ||||
|  | ||||
|     /* Walk the structure, correcting string offsets */ | ||||
|     offset = 0; | ||||
|     while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) { | ||||
|         if (tag == FDT_PROP) { | ||||
|             struct fdt_property *prop = | ||||
|                 _fdt_offset_ptr_w(fdt, offset); | ||||
|             int nameoff; | ||||
|  | ||||
|             nameoff = fdt32_to_cpu(prop->nameoff); | ||||
|             nameoff += fdt_size_dt_strings(fdt); | ||||
|             prop->nameoff = cpu_to_fdt32(nameoff); | ||||
|         } | ||||
|         offset = nextoffset; | ||||
|     } | ||||
|     if (nextoffset < 0) | ||||
|         return nextoffset; | ||||
|  | ||||
|     /* Finally, adjust the header */ | ||||
|     fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt)); | ||||
|     fdt_set_magic(fdt, FDT_MAGIC); | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										137
									
								
								riscv/rtthread/components/drivers/fdt/libfdt/fdt_wip.c
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										137
									
								
								riscv/rtthread/components/drivers/fdt/libfdt/fdt_wip.c
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,137 @@ | ||||
| /* | ||||
|  * libfdt - Flat Device Tree manipulation | ||||
|  * Copyright (C) 2006 David Gibson, IBM Corporation. | ||||
|  * | ||||
|  * libfdt is dual licensed: you can use it either under the terms of | ||||
|  * the GPL, or the BSD license, at your option. | ||||
|  * | ||||
|  *  a) This library is free software; you can redistribute it and/or | ||||
|  *     modify it under the terms of the GNU General Public License as | ||||
|  *     published by the Free Software Foundation; either version 2 of the | ||||
|  *     License, or (at your option) any later version. | ||||
|  * | ||||
|  *     This library is distributed in the hope that it will be useful, | ||||
|  *     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *     GNU General Public License for more details. | ||||
|  * | ||||
|  *     You should have received a copy of the GNU General Public | ||||
|  *     License along with this library; if not, write to the Free | ||||
|  *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | ||||
|  *     MA 02110-1301 USA | ||||
|  * | ||||
|  * Alternatively, | ||||
|  * | ||||
|  *  b) Redistribution and use in source and binary forms, with or | ||||
|  *     without modification, are permitted provided that the following | ||||
|  *     conditions are met: | ||||
|  * | ||||
|  *     1. Redistributions of source code must retain the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer. | ||||
|  *     2. Redistributions in binary form must reproduce the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer in the documentation and/or other materials | ||||
|  *        provided with the distribution. | ||||
|  * | ||||
|  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | ||||
|  *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | ||||
|  *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||||
|  *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||||
|  *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|  *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|  *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||
|  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||||
|  *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||||
|  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| #include "libfdt_env.h" | ||||
| #include "fdt.h" | ||||
| #include "libfdt.h" | ||||
| #include "libfdt_internal.h" | ||||
|  | ||||
| int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset, | ||||
|                     const char *name, int namelen, | ||||
|                     uint32_t idx, const void *val, | ||||
|                     int len) | ||||
| { | ||||
|     void *propval; | ||||
|     int proplen; | ||||
|  | ||||
|     propval = fdt_getprop_namelen_w(fdt, nodeoffset, name, namelen, | ||||
|                     &proplen); | ||||
|     if (!propval) | ||||
|         return proplen; | ||||
|  | ||||
|     if (proplen < (len + idx)) | ||||
|         return -FDT_ERR_NOSPACE; | ||||
|  | ||||
|     memcpy((char *)propval + idx, val, len); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, | ||||
|             const void *val, int len) | ||||
| { | ||||
|     const void *propval; | ||||
|     int proplen; | ||||
|  | ||||
|     propval = fdt_getprop(fdt, nodeoffset, name, &proplen); | ||||
|     if (! propval) | ||||
|         return proplen; | ||||
|  | ||||
|     if (proplen != len) | ||||
|         return -FDT_ERR_NOSPACE; | ||||
|  | ||||
|     return fdt_setprop_inplace_namelen_partial(fdt, nodeoffset, name, | ||||
|                            strlen(name), 0, | ||||
|                            val, len); | ||||
| } | ||||
|  | ||||
| static void _fdt_nop_region(void *start, int len) | ||||
| { | ||||
|     fdt32_t *p; | ||||
|  | ||||
|     for (p = start; (char *)p < ((char *)start + len); p++) | ||||
|         *p = cpu_to_fdt32(FDT_NOP); | ||||
| } | ||||
|  | ||||
| int fdt_nop_property(void *fdt, int nodeoffset, const char *name) | ||||
| { | ||||
|     struct fdt_property *prop; | ||||
|     int len; | ||||
|  | ||||
|     prop = fdt_get_property_w(fdt, nodeoffset, name, &len); | ||||
|     if (! prop) | ||||
|         return len; | ||||
|  | ||||
|     _fdt_nop_region(prop, len + sizeof(*prop)); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int _fdt_node_end_offset(void *fdt, int offset) | ||||
| { | ||||
|     int depth = 0; | ||||
|  | ||||
|     while ((offset >= 0) && (depth >= 0)) | ||||
|         offset = fdt_next_node(fdt, offset, &depth); | ||||
|  | ||||
|     return offset; | ||||
| } | ||||
|  | ||||
| int fdt_nop_node(void *fdt, int nodeoffset) | ||||
| { | ||||
|     int endoffset; | ||||
|  | ||||
|     endoffset = _fdt_node_end_offset(fdt, nodeoffset); | ||||
|     if (endoffset < 0) | ||||
|         return endoffset; | ||||
|  | ||||
|     _fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0), | ||||
|             endoffset - nodeoffset); | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										1883
									
								
								riscv/rtthread/components/drivers/fdt/libfdt/libfdt.h
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										1883
									
								
								riscv/rtthread/components/drivers/fdt/libfdt/libfdt.h
									
									
									
									
									
										Executable file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										113
									
								
								riscv/rtthread/components/drivers/fdt/libfdt/libfdt_env.h
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										113
									
								
								riscv/rtthread/components/drivers/fdt/libfdt/libfdt_env.h
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,113 @@ | ||||
| #ifndef _LIBFDT_ENV_H | ||||
| #define _LIBFDT_ENV_H | ||||
| /* | ||||
|  * libfdt - Flat Device Tree manipulation | ||||
|  * Copyright (C) 2006 David Gibson, IBM Corporation. | ||||
|  * Copyright 2012 Kim Phillips, Freescale Semiconductor. | ||||
|  * | ||||
|  * libfdt is dual licensed: you can use it either under the terms of | ||||
|  * the GPL, or the BSD license, at your option. | ||||
|  * | ||||
|  *  a) This library is free software; you can redistribute it and/or | ||||
|  *     modify it under the terms of the GNU General Public License as | ||||
|  *     published by the Free Software Foundation; either version 2 of the | ||||
|  *     License, or (at your option) any later version. | ||||
|  * | ||||
|  *     This library is distributed in the hope that it will be useful, | ||||
|  *     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *     GNU General Public License for more details. | ||||
|  * | ||||
|  *     You should have received a copy of the GNU General Public | ||||
|  *     License along with this library; if not, write to the Free | ||||
|  *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | ||||
|  *     MA 02110-1301 USA | ||||
|  * | ||||
|  * Alternatively, | ||||
|  * | ||||
|  *  b) Redistribution and use in source and binary forms, with or | ||||
|  *     without modification, are permitted provided that the following | ||||
|  *     conditions are met: | ||||
|  * | ||||
|  *     1. Redistributions of source code must retain the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer. | ||||
|  *     2. Redistributions in binary form must reproduce the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer in the documentation and/or other materials | ||||
|  *        provided with the distribution. | ||||
|  * | ||||
|  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | ||||
|  *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | ||||
|  *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||||
|  *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||||
|  *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|  *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|  *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||
|  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||||
|  *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||||
|  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
|  | ||||
| #include <stddef.h> | ||||
| #include <stdint.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #ifdef __CHECKER__ | ||||
| #define FDT_FORCE __attribute__((force)) | ||||
| #define FDT_BITWISE __attribute__((bitwise)) | ||||
| #else | ||||
| #define FDT_FORCE | ||||
| #define FDT_BITWISE | ||||
| #endif | ||||
|  | ||||
| typedef uint16_t FDT_BITWISE fdt16_t; | ||||
| typedef uint32_t FDT_BITWISE fdt32_t; | ||||
| typedef uint64_t FDT_BITWISE fdt64_t; | ||||
| typedef uint64_t unaligned_fdt64_t __attribute__((aligned(4))); | ||||
|  | ||||
| #define EXTRACT_BYTE(x, n)  ((unsigned long long)((uint8_t *)&x)[n]) | ||||
| #define CPU_TO_FDT16(x) ((EXTRACT_BYTE(x, 0) << 8) | EXTRACT_BYTE(x, 1)) | ||||
| #define CPU_TO_FDT32(x) ((EXTRACT_BYTE(x, 0) << 24) | (EXTRACT_BYTE(x, 1) << 16) | \ | ||||
|              (EXTRACT_BYTE(x, 2) << 8) | EXTRACT_BYTE(x, 3)) | ||||
| #define CPU_TO_FDT64(x) ((EXTRACT_BYTE(x, 0) << 56) | (EXTRACT_BYTE(x, 1) << 48) | \ | ||||
|              (EXTRACT_BYTE(x, 2) << 40) | (EXTRACT_BYTE(x, 3) << 32) | \ | ||||
|              (EXTRACT_BYTE(x, 4) << 24) | (EXTRACT_BYTE(x, 5) << 16) | \ | ||||
|              (EXTRACT_BYTE(x, 6) << 8) | EXTRACT_BYTE(x, 7)) | ||||
|  | ||||
| static inline uint16_t fdt16_to_cpu(fdt16_t x) | ||||
| { | ||||
|     return (FDT_FORCE uint16_t)CPU_TO_FDT16(x); | ||||
| } | ||||
| static inline fdt16_t cpu_to_fdt16(uint16_t x) | ||||
| { | ||||
|     return (FDT_FORCE fdt16_t)CPU_TO_FDT16(x); | ||||
| } | ||||
|  | ||||
| static inline uint32_t fdt32_to_cpu(fdt32_t x) | ||||
| { | ||||
|     return (FDT_FORCE uint32_t)CPU_TO_FDT32(x); | ||||
| } | ||||
| static inline fdt32_t cpu_to_fdt32(uint32_t x) | ||||
| { | ||||
|     return (FDT_FORCE fdt32_t)CPU_TO_FDT32(x); | ||||
| } | ||||
|  | ||||
| static inline uint64_t fdt64_to_cpu(fdt64_t x) | ||||
| { | ||||
|     return (FDT_FORCE uint64_t)CPU_TO_FDT64(x); | ||||
| } | ||||
| static inline fdt64_t cpu_to_fdt64(uint64_t x) | ||||
| { | ||||
|     return (FDT_FORCE fdt64_t)CPU_TO_FDT64(x); | ||||
| } | ||||
| #undef CPU_TO_FDT64 | ||||
| #undef CPU_TO_FDT32 | ||||
| #undef CPU_TO_FDT16 | ||||
| #undef EXTRACT_BYTE | ||||
|  | ||||
| #endif /* _LIBFDT_ENV_H */ | ||||
							
								
								
									
										95
									
								
								riscv/rtthread/components/drivers/fdt/libfdt/libfdt_internal.h
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										95
									
								
								riscv/rtthread/components/drivers/fdt/libfdt/libfdt_internal.h
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,95 @@ | ||||
| #ifndef _LIBFDT_INTERNAL_H | ||||
| #define _LIBFDT_INTERNAL_H | ||||
| /* | ||||
|  * libfdt - Flat Device Tree manipulation | ||||
|  * Copyright (C) 2006 David Gibson, IBM Corporation. | ||||
|  * | ||||
|  * libfdt is dual licensed: you can use it either under the terms of | ||||
|  * the GPL, or the BSD license, at your option. | ||||
|  * | ||||
|  *  a) This library is free software; you can redistribute it and/or | ||||
|  *     modify it under the terms of the GNU General Public License as | ||||
|  *     published by the Free Software Foundation; either version 2 of the | ||||
|  *     License, or (at your option) any later version. | ||||
|  * | ||||
|  *     This library is distributed in the hope that it will be useful, | ||||
|  *     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *     GNU General Public License for more details. | ||||
|  * | ||||
|  *     You should have received a copy of the GNU General Public | ||||
|  *     License along with this library; if not, write to the Free | ||||
|  *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | ||||
|  *     MA 02110-1301 USA | ||||
|  * | ||||
|  * Alternatively, | ||||
|  * | ||||
|  *  b) Redistribution and use in source and binary forms, with or | ||||
|  *     without modification, are permitted provided that the following | ||||
|  *     conditions are met: | ||||
|  * | ||||
|  *     1. Redistributions of source code must retain the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer. | ||||
|  *     2. Redistributions in binary form must reproduce the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer in the documentation and/or other materials | ||||
|  *        provided with the distribution. | ||||
|  * | ||||
|  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | ||||
|  *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | ||||
|  *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||||
|  *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||||
|  *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|  *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|  *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||
|  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||||
|  *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||||
|  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| #include "fdt.h" | ||||
|  | ||||
| #define FDT_ALIGN(x, a)     (((x) + (a) - 1) & ~((a) - 1)) | ||||
| #define FDT_TAGALIGN(x)     (FDT_ALIGN((x), FDT_TAGSIZE)) | ||||
|  | ||||
| #define FDT_CHECK_HEADER(fdt) \ | ||||
|     { \ | ||||
|         int __err; \ | ||||
|         if ((__err = fdt_check_header(fdt)) != 0) \ | ||||
|             return __err; \ | ||||
|     } | ||||
|  | ||||
| int _fdt_check_node_offset(const void *fdt, int offset); | ||||
| int _fdt_check_prop_offset(const void *fdt, int offset); | ||||
| const char *_fdt_find_string(const char *strtab, int tabsize, const char *s); | ||||
| int _fdt_node_end_offset(void *fdt, int nodeoffset); | ||||
|  | ||||
| static inline const void *_fdt_offset_ptr(const void *fdt, int offset) | ||||
| { | ||||
|     return (const char *)fdt + fdt_off_dt_struct(fdt) + offset; | ||||
| } | ||||
|  | ||||
| static inline void *_fdt_offset_ptr_w(void *fdt, int offset) | ||||
| { | ||||
|     return (void *)(uintptr_t)_fdt_offset_ptr(fdt, offset); | ||||
| } | ||||
|  | ||||
| static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n) | ||||
| { | ||||
|     const struct fdt_reserve_entry *rsv_table = | ||||
|         (const struct fdt_reserve_entry *) | ||||
|         ((const char *)fdt + fdt_off_mem_rsvmap(fdt)); | ||||
|  | ||||
|     return rsv_table + n; | ||||
| } | ||||
| static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n) | ||||
| { | ||||
|     return (void *)(uintptr_t)_fdt_mem_rsv(fdt, n); | ||||
| } | ||||
|  | ||||
| #define FDT_SW_MAGIC        (~FDT_MAGIC) | ||||
|  | ||||
| #endif /* _LIBFDT_INTERNAL_H */ | ||||
		Reference in New Issue
	
	Block a user