183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+ 2b7e0d73bSSimon Glass /* 3b7e0d73bSSimon Glass * Copyright (c) 2017 Google, Inc 4b7e0d73bSSimon Glass * Written by Simon Glass <sjg@chromium.org> 5b7e0d73bSSimon Glass */ 6b7e0d73bSSimon Glass 7b7e0d73bSSimon Glass #include <common.h> 8b08c8c48SMasahiro Yamada #include <linux/libfdt.h> 9b7e0d73bSSimon Glass #include <dm/of_access.h> 10b7e0d73bSSimon Glass #include <dm/of_extra.h> 11b7e0d73bSSimon Glass #include <dm/ofnode.h> 12b7e0d73bSSimon Glass 135e0a7341SSimon Glass int ofnode_read_fmap_entry(ofnode node, struct fmap_entry *entry) 14b7e0d73bSSimon Glass { 15b7e0d73bSSimon Glass const char *prop; 16b7e0d73bSSimon Glass 17*e6c5c94aSSimon Glass if (ofnode_read_u32(node, "image-pos", &entry->offset)) { 18*e6c5c94aSSimon Glass debug("Node '%s' has bad/missing 'image-pos' property\n", 195e0a7341SSimon Glass ofnode_get_name(node)); 20*e6c5c94aSSimon Glass return log_ret(-ENOENT); 21b7e0d73bSSimon Glass } 22*e6c5c94aSSimon Glass if (ofnode_read_u32(node, "size", &entry->length)) { 23*e6c5c94aSSimon Glass debug("Node '%s' has bad/missing 'size' property\n", 24*e6c5c94aSSimon Glass ofnode_get_name(node)); 25*e6c5c94aSSimon Glass return log_ret(-ENOENT); 26*e6c5c94aSSimon Glass } 27b7e0d73bSSimon Glass entry->used = ofnode_read_s32_default(node, "used", entry->length); 28b7e0d73bSSimon Glass prop = ofnode_read_string(node, "compress"); 29*e6c5c94aSSimon Glass if (prop) { 30*e6c5c94aSSimon Glass if (!strcmp(prop, "lz4")) 31*e6c5c94aSSimon Glass entry->compress_algo = FMAP_COMPRESS_LZ4; 32*e6c5c94aSSimon Glass else 33*e6c5c94aSSimon Glass return log_msg_ret("Unknown compression algo", 34*e6c5c94aSSimon Glass -EINVAL); 35*e6c5c94aSSimon Glass } else { 36*e6c5c94aSSimon Glass entry->compress_algo = FMAP_COMPRESS_NONE; 37*e6c5c94aSSimon Glass } 38*e6c5c94aSSimon Glass entry->unc_length = ofnode_read_s32_default(node, "uncomp-size", 39*e6c5c94aSSimon Glass entry->length); 40b7e0d73bSSimon Glass prop = ofnode_read_string(node, "hash"); 41b7e0d73bSSimon Glass if (prop) 42b7e0d73bSSimon Glass entry->hash_size = strlen(prop); 43b7e0d73bSSimon Glass entry->hash_algo = prop ? FMAP_HASH_SHA256 : FMAP_HASH_NONE; 44b7e0d73bSSimon Glass entry->hash = (uint8_t *)prop; 45b7e0d73bSSimon Glass 46b7e0d73bSSimon Glass return 0; 47b7e0d73bSSimon Glass } 48964cadc4SSimon Glass 49964cadc4SSimon Glass int ofnode_decode_region(ofnode node, const char *prop_name, fdt_addr_t *basep, 50964cadc4SSimon Glass fdt_size_t *sizep) 51964cadc4SSimon Glass { 52964cadc4SSimon Glass const fdt_addr_t *cell; 53964cadc4SSimon Glass int len; 54964cadc4SSimon Glass 55964cadc4SSimon Glass debug("%s: %s: %s\n", __func__, ofnode_get_name(node), prop_name); 56964cadc4SSimon Glass cell = ofnode_get_property(node, prop_name, &len); 57964cadc4SSimon Glass if (!cell || (len < sizeof(fdt_addr_t) * 2)) { 58964cadc4SSimon Glass debug("cell=%p, len=%d\n", cell, len); 59964cadc4SSimon Glass return -1; 60964cadc4SSimon Glass } 61964cadc4SSimon Glass 62964cadc4SSimon Glass *basep = fdt_addr_to_cpu(*cell); 63964cadc4SSimon Glass *sizep = fdt_size_to_cpu(cell[1]); 64964cadc4SSimon Glass debug("%s: base=%08lx, size=%lx\n", __func__, (ulong)*basep, 65964cadc4SSimon Glass (ulong)*sizep); 66964cadc4SSimon Glass 67964cadc4SSimon Glass return 0; 68964cadc4SSimon Glass } 69964cadc4SSimon Glass 70964cadc4SSimon Glass int ofnode_decode_memory_region(ofnode config_node, const char *mem_type, 71964cadc4SSimon Glass const char *suffix, fdt_addr_t *basep, 72964cadc4SSimon Glass fdt_size_t *sizep) 73964cadc4SSimon Glass { 74964cadc4SSimon Glass char prop_name[50]; 75964cadc4SSimon Glass const char *mem; 76964cadc4SSimon Glass fdt_size_t size, offset_size; 77964cadc4SSimon Glass fdt_addr_t base, offset; 78964cadc4SSimon Glass ofnode node; 79964cadc4SSimon Glass 80964cadc4SSimon Glass if (!ofnode_valid(config_node)) { 81964cadc4SSimon Glass config_node = ofnode_path("/config"); 82964cadc4SSimon Glass if (!ofnode_valid(config_node)) { 83964cadc4SSimon Glass debug("%s: Cannot find /config node\n", __func__); 84964cadc4SSimon Glass return -ENOENT; 85964cadc4SSimon Glass } 86964cadc4SSimon Glass } 87964cadc4SSimon Glass if (!suffix) 88964cadc4SSimon Glass suffix = ""; 89964cadc4SSimon Glass 90964cadc4SSimon Glass snprintf(prop_name, sizeof(prop_name), "%s-memory%s", mem_type, 91964cadc4SSimon Glass suffix); 92964cadc4SSimon Glass mem = ofnode_read_string(config_node, prop_name); 93964cadc4SSimon Glass if (!mem) { 94964cadc4SSimon Glass debug("%s: No memory type for '%s', using /memory\n", __func__, 95964cadc4SSimon Glass prop_name); 96964cadc4SSimon Glass mem = "/memory"; 97964cadc4SSimon Glass } 98964cadc4SSimon Glass 99964cadc4SSimon Glass node = ofnode_path(mem); 100964cadc4SSimon Glass if (!ofnode_valid(node)) { 101964cadc4SSimon Glass debug("%s: Failed to find node '%s'\n", __func__, mem); 102964cadc4SSimon Glass return -ENOENT; 103964cadc4SSimon Glass } 104964cadc4SSimon Glass 105964cadc4SSimon Glass /* 106964cadc4SSimon Glass * Not strictly correct - the memory may have multiple banks. We just 107964cadc4SSimon Glass * use the first 108964cadc4SSimon Glass */ 109964cadc4SSimon Glass if (ofnode_decode_region(node, "reg", &base, &size)) { 110964cadc4SSimon Glass debug("%s: Failed to decode memory region %s\n", __func__, 111964cadc4SSimon Glass mem); 112964cadc4SSimon Glass return -EINVAL; 113964cadc4SSimon Glass } 114964cadc4SSimon Glass 115964cadc4SSimon Glass snprintf(prop_name, sizeof(prop_name), "%s-offset%s", mem_type, 116964cadc4SSimon Glass suffix); 117964cadc4SSimon Glass if (ofnode_decode_region(config_node, prop_name, &offset, 118964cadc4SSimon Glass &offset_size)) { 119964cadc4SSimon Glass debug("%s: Failed to decode memory region '%s'\n", __func__, 120964cadc4SSimon Glass prop_name); 121964cadc4SSimon Glass return -EINVAL; 122964cadc4SSimon Glass } 123964cadc4SSimon Glass 124964cadc4SSimon Glass *basep = base + offset; 125964cadc4SSimon Glass *sizep = offset_size; 126964cadc4SSimon Glass 127964cadc4SSimon Glass return 0; 128964cadc4SSimon Glass } 129