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