^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * libfdt - Flat Device Tree manipulation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2014 David Gibson <david@gibson.dropbear.id.au>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2018 embedded brains GmbH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include "libfdt_env.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <fdt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <libfdt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "libfdt_internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) static int fdt_cells(const void *fdt, int nodeoffset, const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) const fdt32_t *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) uint32_t val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) c = fdt_getprop(fdt, nodeoffset, name, &len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) if (!c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) if (len != sizeof(*c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) return -FDT_ERR_BADNCELLS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) val = fdt32_to_cpu(*c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) if (val > FDT_MAX_NCELLS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) return -FDT_ERR_BADNCELLS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) return (int)val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) int fdt_address_cells(const void *fdt, int nodeoffset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) val = fdt_cells(fdt, nodeoffset, "#address-cells");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) if (val == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) return -FDT_ERR_BADNCELLS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) if (val == -FDT_ERR_NOTFOUND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) return 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) int fdt_size_cells(const void *fdt, int nodeoffset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) val = fdt_cells(fdt, nodeoffset, "#size-cells");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (val == -FDT_ERR_NOTFOUND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /* This function assumes that [address|size]_cells is 1 or 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) const char *name, uint64_t addr, uint64_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) int addr_cells, size_cells, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) uint8_t data[sizeof(fdt64_t) * 2], *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) ret = fdt_address_cells(fdt, parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) addr_cells = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) ret = fdt_size_cells(fdt, parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) size_cells = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /* check validity of address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) prop = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (addr_cells == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if ((addr > UINT32_MAX) || ((UINT32_MAX + 1 - addr) < size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return -FDT_ERR_BADVALUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) fdt32_st(prop, (uint32_t)addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) } else if (addr_cells == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) fdt64_st(prop, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return -FDT_ERR_BADNCELLS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* check validity of size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) prop += addr_cells * sizeof(fdt32_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (size_cells == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (size > UINT32_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return -FDT_ERR_BADVALUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) fdt32_st(prop, (uint32_t)size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) } else if (size_cells == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) fdt64_st(prop, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return -FDT_ERR_BADNCELLS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return fdt_appendprop(fdt, nodeoffset, name, data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) (addr_cells + size_cells) * sizeof(fdt32_t));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }