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 17 if (ofnode_read_u32(node, "image-pos", &entry->offset)) { 18 debug("Node '%s' has bad/missing 'image-pos' property\n", 19 ofnode_get_name(node)); 20 return log_ret(-ENOENT); 21 } 22 if (ofnode_read_u32(node, "size", &entry->length)) { 23 debug("Node '%s' has bad/missing 'size' property\n", 24 ofnode_get_name(node)); 25 return log_ret(-ENOENT); 26 } 27 entry->used = ofnode_read_s32_default(node, "used", entry->length); 28 prop = ofnode_read_string(node, "compress"); 29 if (prop) { 30 if (!strcmp(prop, "lz4")) 31 entry->compress_algo = FMAP_COMPRESS_LZ4; 32 else 33 return log_msg_ret("Unknown compression algo", 34 -EINVAL); 35 } else { 36 entry->compress_algo = FMAP_COMPRESS_NONE; 37 } 38 entry->unc_length = ofnode_read_s32_default(node, "uncomp-size", 39 entry->length); 40 prop = ofnode_read_string(node, "hash"); 41 if (prop) 42 entry->hash_size = strlen(prop); 43 entry->hash_algo = prop ? FMAP_HASH_SHA256 : FMAP_HASH_NONE; 44 entry->hash = (uint8_t *)prop; 45 46 return 0; 47 } 48 49 int ofnode_decode_region(ofnode node, const char *prop_name, fdt_addr_t *basep, 50 fdt_size_t *sizep) 51 { 52 const fdt_addr_t *cell; 53 int len; 54 55 debug("%s: %s: %s\n", __func__, ofnode_get_name(node), prop_name); 56 cell = ofnode_get_property(node, prop_name, &len); 57 if (!cell || (len < sizeof(fdt_addr_t) * 2)) { 58 debug("cell=%p, len=%d\n", cell, len); 59 return -1; 60 } 61 62 *basep = fdt_addr_to_cpu(*cell); 63 *sizep = fdt_size_to_cpu(cell[1]); 64 debug("%s: base=%08lx, size=%lx\n", __func__, (ulong)*basep, 65 (ulong)*sizep); 66 67 return 0; 68 } 69 70 int ofnode_decode_memory_region(ofnode config_node, const char *mem_type, 71 const char *suffix, fdt_addr_t *basep, 72 fdt_size_t *sizep) 73 { 74 char prop_name[50]; 75 const char *mem; 76 fdt_size_t size, offset_size; 77 fdt_addr_t base, offset; 78 ofnode node; 79 80 if (!ofnode_valid(config_node)) { 81 config_node = ofnode_path("/config"); 82 if (!ofnode_valid(config_node)) { 83 debug("%s: Cannot find /config node\n", __func__); 84 return -ENOENT; 85 } 86 } 87 if (!suffix) 88 suffix = ""; 89 90 snprintf(prop_name, sizeof(prop_name), "%s-memory%s", mem_type, 91 suffix); 92 mem = ofnode_read_string(config_node, prop_name); 93 if (!mem) { 94 debug("%s: No memory type for '%s', using /memory\n", __func__, 95 prop_name); 96 mem = "/memory"; 97 } 98 99 node = ofnode_path(mem); 100 if (!ofnode_valid(node)) { 101 debug("%s: Failed to find node '%s'\n", __func__, mem); 102 return -ENOENT; 103 } 104 105 /* 106 * Not strictly correct - the memory may have multiple banks. We just 107 * use the first 108 */ 109 if (ofnode_decode_region(node, "reg", &base, &size)) { 110 debug("%s: Failed to decode memory region %s\n", __func__, 111 mem); 112 return -EINVAL; 113 } 114 115 snprintf(prop_name, sizeof(prop_name), "%s-offset%s", mem_type, 116 suffix); 117 if (ofnode_decode_region(config_node, prop_name, &offset, 118 &offset_size)) { 119 debug("%s: Failed to decode memory region '%s'\n", __func__, 120 prop_name); 121 return -EINVAL; 122 } 123 124 *basep = base + offset; 125 *sizep = offset_size; 126 127 return 0; 128 } 129