1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (c) 2017 Google, Inc 4 * Written by Simon Glass <sjg@chromium.org> 5 */ 6 7 #include <common.h> 8 #include <linux/libfdt.h> 9 #include <dm/of_access.h> 10 #include <dm/of_extra.h> 11 #include <dm/ofnode.h> 12 13 int ofnode_read_fmap_entry(ofnode node, struct fmap_entry *entry) 14 { 15 const char *prop; 16 u32 reg[2]; 17 18 if (ofnode_read_u32_array(node, "reg", reg, 2)) { 19 debug("Node '%s' has bad/missing 'reg' property\n", 20 ofnode_get_name(node)); 21 return -log_ret(ENOENT); 22 } 23 entry->offset = reg[0]; 24 entry->length = reg[1]; 25 entry->used = ofnode_read_s32_default(node, "used", entry->length); 26 prop = ofnode_read_string(node, "compress"); 27 entry->compress_algo = prop && !strcmp(prop, "lzo") ? 28 FMAP_COMPRESS_LZO : FMAP_COMPRESS_NONE; 29 prop = ofnode_read_string(node, "hash"); 30 if (prop) 31 entry->hash_size = strlen(prop); 32 entry->hash_algo = prop ? FMAP_HASH_SHA256 : FMAP_HASH_NONE; 33 entry->hash = (uint8_t *)prop; 34 35 return 0; 36 } 37 38 int ofnode_decode_region(ofnode node, const char *prop_name, fdt_addr_t *basep, 39 fdt_size_t *sizep) 40 { 41 const fdt_addr_t *cell; 42 int len; 43 44 debug("%s: %s: %s\n", __func__, ofnode_get_name(node), prop_name); 45 cell = ofnode_get_property(node, prop_name, &len); 46 if (!cell || (len < sizeof(fdt_addr_t) * 2)) { 47 debug("cell=%p, len=%d\n", cell, len); 48 return -1; 49 } 50 51 *basep = fdt_addr_to_cpu(*cell); 52 *sizep = fdt_size_to_cpu(cell[1]); 53 debug("%s: base=%08lx, size=%lx\n", __func__, (ulong)*basep, 54 (ulong)*sizep); 55 56 return 0; 57 } 58 59 int ofnode_decode_memory_region(ofnode config_node, const char *mem_type, 60 const char *suffix, fdt_addr_t *basep, 61 fdt_size_t *sizep) 62 { 63 char prop_name[50]; 64 const char *mem; 65 fdt_size_t size, offset_size; 66 fdt_addr_t base, offset; 67 ofnode node; 68 69 if (!ofnode_valid(config_node)) { 70 config_node = ofnode_path("/config"); 71 if (!ofnode_valid(config_node)) { 72 debug("%s: Cannot find /config node\n", __func__); 73 return -ENOENT; 74 } 75 } 76 if (!suffix) 77 suffix = ""; 78 79 snprintf(prop_name, sizeof(prop_name), "%s-memory%s", mem_type, 80 suffix); 81 mem = ofnode_read_string(config_node, prop_name); 82 if (!mem) { 83 debug("%s: No memory type for '%s', using /memory\n", __func__, 84 prop_name); 85 mem = "/memory"; 86 } 87 88 node = ofnode_path(mem); 89 if (!ofnode_valid(node)) { 90 debug("%s: Failed to find node '%s'\n", __func__, mem); 91 return -ENOENT; 92 } 93 94 /* 95 * Not strictly correct - the memory may have multiple banks. We just 96 * use the first 97 */ 98 if (ofnode_decode_region(node, "reg", &base, &size)) { 99 debug("%s: Failed to decode memory region %s\n", __func__, 100 mem); 101 return -EINVAL; 102 } 103 104 snprintf(prop_name, sizeof(prop_name), "%s-offset%s", mem_type, 105 suffix); 106 if (ofnode_decode_region(config_node, prop_name, &offset, 107 &offset_size)) { 108 debug("%s: Failed to decode memory region '%s'\n", __func__, 109 prop_name); 110 return -EINVAL; 111 } 112 113 *basep = base + offset; 114 *sizep = offset_size; 115 116 return 0; 117 } 118