1260684Skaiw// SPDX-License-Identifier: GPL-2.0+ 2260684Skaiw/* 3276371Semaste * Copyright (C) 2016 Google, Inc 4260684Skaiw * Written by Simon Glass <sjg@chromium.org> 5260684Skaiw */ 6260684Skaiw 7260684Skaiw#include <common.h> 8260684Skaiw#include <errno.h> 9260684Skaiw#include <image.h> 10260684Skaiw#include <log.h> 11260684Skaiw#include <linux/libfdt.h> 12260684Skaiw 13260684Skaiwulong fdt_getprop_u32(const void *fdt, int node, const char *prop) 14260684Skaiw{ 15260684Skaiw const u32 *cell; 16260684Skaiw int len; 17260684Skaiw 18260684Skaiw cell = fdt_getprop(fdt, node, prop, &len); 19260684Skaiw if (!cell || len != sizeof(*cell)) 20260684Skaiw return FDT_ERROR; 21260684Skaiw 22260684Skaiw return fdt32_to_cpu(*cell); 23260684Skaiw} 24260684Skaiw 25260684Skaiw__weak int board_fit_config_name_match(const char *name) 26260684Skaiw{ 27260684Skaiw return -EINVAL; 28260684Skaiw} 29260684Skaiw 30276371Semaste/* 31260684Skaiw * Iterate over all /configurations subnodes and call a platform specific 32260684Skaiw * function to find the matching configuration. 33260684Skaiw * Returns the node offset or a negative error number. 34260684Skaiw */ 35260684Skaiwint fit_find_config_node(const void *fdt) 36276371Semaste{ 37260684Skaiw const char *name; 38260684Skaiw int conf, node, len; 39260684Skaiw const char *dflt_conf_name; 40260684Skaiw const char *dflt_conf_desc = NULL; 41260684Skaiw int dflt_conf_node = -ENOENT; 42260684Skaiw 43260684Skaiw conf = fdt_path_offset(fdt, FIT_CONFS_PATH); 44260684Skaiw if (conf < 0) { 45260684Skaiw debug("%s: Cannot find /configurations node: %d\n", __func__, 46260684Skaiw conf); 47260684Skaiw return -EINVAL; 48260854Skaiw } 49260684Skaiw 50260684Skaiw dflt_conf_name = fdt_getprop(fdt, conf, "default", &len); 51260684Skaiw 52276371Semaste for (node = fdt_first_subnode(fdt, conf); 53276371Semaste node >= 0; 54276371Semaste node = fdt_next_subnode(fdt, node)) { 55260684Skaiw name = fdt_getprop(fdt, node, "description", &len); 56260684Skaiw if (!name) { 57260684Skaiw#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 58260684Skaiw printf("%s: Missing FDT description in DTB\n", 59260684Skaiw __func__); 60260684Skaiw#endif 61260684Skaiw return -EINVAL; 62260684Skaiw } 63260684Skaiw 64260684Skaiw if (dflt_conf_name) { 65260684Skaiw const char *node_name = fdt_get_name(fdt, node, NULL); 66276371Semaste if (strcmp(dflt_conf_name, node_name) == 0) { 67276371Semaste dflt_conf_node = node; 68260684Skaiw dflt_conf_desc = name; 69260684Skaiw } 70260684Skaiw } 71276371Semaste 72260684Skaiw if (board_fit_config_name_match(name)) 73260684Skaiw continue; 74260684Skaiw 75260684Skaiw debug("Selecting config '%s'\n", name); 76260684Skaiw 77260684Skaiw return node; 78260684Skaiw } 79260684Skaiw 80276371Semaste if (dflt_conf_node != -ENOENT) { 81276371Semaste debug("Selecting default config '%s'\n", dflt_conf_desc); 82276371Semaste return dflt_conf_node; 83276371Semaste } 84260684Skaiw 85260684Skaiw return -ENOENT; 86260684Skaiw} 87260684Skaiw