diff options
-rw-r--r-- | lib/device_tree/include/lib/device_tree/libfdt_helpers.h | 41 | ||||
-rw-r--r-- | lib/device_tree/libfdt_helpers.c | 121 | ||||
-rw-r--r-- | lib/device_tree/rules.mk | 37 |
3 files changed, 199 insertions, 0 deletions
diff --git a/lib/device_tree/include/lib/device_tree/libfdt_helpers.h b/lib/device_tree/include/lib/device_tree/libfdt_helpers.h new file mode 100644 index 00000000..22acce77 --- /dev/null +++ b/lib/device_tree/include/lib/device_tree/libfdt_helpers.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024 LK Trusty Authors. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#pragma once + +#include <libfdt.h> +#include <lk/types.h> + +status_t fdt_helper_read_cells32(const fdt32_t* fdt_prop, + int fdt_prop_len, + int row_index, + int before_cells, + int cells, + int after_cells, + uint64_t* valp); + +status_t fdt_helper_get_reg(const void* fdt, + int nodeoffset, + int reg_index, + paddr_t* addrp, + size_t* sizep); diff --git a/lib/device_tree/libfdt_helpers.c b/lib/device_tree/libfdt_helpers.c new file mode 100644 index 00000000..dc6eb17f --- /dev/null +++ b/lib/device_tree/libfdt_helpers.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2024 LK Trusty Authors. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include <lib/device_tree/libfdt_helpers.h> +#include "err.h" +#include "lk/types.h" + +/** + * fdt_helper_read_cells32 - Read and convert cells. + * @fdt_prop: Pointer to property to read from. + * @fdt_prop_len: Length of @fdt_prop in bytes (not count of 32 bit values). + * @row_index: Row to read from. + * @before_cells: Number of cells to ignore in each row before the cells we + * read and convert. + * @cells: Number of cells to read and convert to cpu endian. + * @after_cells: Number of cells to ignore in each row after the cell we read + * and convert. + * @valp: Pointer to store converted value in. + * + * Return: + * * %0: Success. + * * %ERR_OUT_OF_RANGE: @fdt_prop_len is too small for the requested read. + * * %ERR_TOO_BIG: value does not fit in uint64_t (only possible if + * cells > 2). + */ +status_t fdt_helper_read_cells32(const fdt32_t* fdt_prop, + int fdt_prop_len, + int row_index, + int before_cells, + int cells, + int after_cells, + uint64_t* valp) { + uint64_t ret = 0; + int cell_index = + row_index * (before_cells + cells + after_cells) + before_cells; + if (cell_index + cells > (fdt_prop_len / (int)sizeof(fdt32_t))) { + return ERR_OUT_OF_RANGE; + } + while (cells-- > 0) { + if (ret > UINT32_MAX) { + return ERR_TOO_BIG; + } + ret = ret << 32 | fdt32_to_cpu(fdt_prop[cell_index++]); + } + *valp = ret; + return 0; +} + +/** + * fdt_helper_get_reg - Get address and size from reg property of a node. + * @fdt: Pointer to device tree. + * @nodeoffset: Node to use. + * @reg_index: Row to read from. + * + * Return: + * * %0: Success. + * * %ERR_NOT_FOUND: Node does not have a reg property. + * * %ERR_OUT_OF_RANGE: reg property is too small for the requested read. + * * %ERR_TOO_BIG: reg value does not fit in paddr_t or size_t. + */ +status_t fdt_helper_get_reg(const void* fdt, + int nodeoffset, + int reg_index, + paddr_t* addrp, + size_t* sizep) { + status_t ret = 0; + int parent_offset = fdt_parent_offset(fdt, nodeoffset); + int address_cells = fdt_address_cells(fdt, parent_offset); + int size_cells = fdt_size_cells(fdt, parent_offset); + int reg_prop_len; + const fdt32_t* reg_prop = + fdt_getprop(fdt, nodeoffset, "reg", ®_prop_len); + if (!reg_prop) { + return ERR_NOT_FOUND; + } + if (addrp) { + uint64_t addr64; + ret = fdt_helper_read_cells32(reg_prop, reg_prop_len, reg_index, 0, + address_cells, size_cells, &addr64); + if (ret) { + return ret; + } + if (addr64 > PADDR_MAX) { + return ERR_TOO_BIG; + } + *addrp = addr64; + } + if (sizep) { + uint64_t size64; + ret = fdt_helper_read_cells32(reg_prop, reg_prop_len, reg_index, + address_cells, size_cells, 0, &size64); + if (ret) { + return ret; + } + if (size64 > SIZE_MAX) { + return ERR_TOO_BIG; + } + *sizep = size64; + } + return 0; +} diff --git a/lib/device_tree/rules.mk b/lib/device_tree/rules.mk new file mode 100644 index 00000000..903de373 --- /dev/null +++ b/lib/device_tree/rules.mk @@ -0,0 +1,37 @@ +# +# Copyright (c) 2024 LK Trusty Authors. All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +LOCAL_DIR := $(GET_LOCAL_DIR) + +MODULE := $(LOCAL_DIR) + +MODULE_LIBRARY_DEPS += \ + external/dtc/libfdt \ + +MODULE_EXPORT_INCLUDES += \ + $(LOCAL_DIR)/include \ + +MODULE_SRCS += \ + $(LOCAL_DIR)/libfdt_helpers.c \ + +include make/library.mk |