1// SPDX-License-Identifier: Intel 2/* 3 * Access to binman information at runtime 4 * 5 * Copyright 2019 Google LLC 6 * Written by Simon Glass <sjg@chromium.org> 7 */ 8 9#include <binman.h> 10#include <dm.h> 11#include <log.h> 12#include <malloc.h> 13#include <mapmem.h> 14 15/** 16 * struct binman_info - Information needed by the binman library 17 * 18 * @image: Node describing the image we are running from 19 * @rom_offset: Offset from an image_pos to the memory-mapped address, or 20 * ROM_OFFSET_NONE if the ROM is not memory-mapped. Can be positive or 21 * negative 22 */ 23struct binman_info { 24 ofnode image; 25 int rom_offset; 26}; 27 28#define ROM_OFFSET_NONE (-1) 29 30static struct binman_info *binman; 31 32/** 33 * find_image_node() - Find the top-level binman node 34 * 35 * Finds the binman node which can be used to load entries. The correct node 36 * depends on whether multiple-images is in use. 37 * 38 * @nodep: Returns the node found, on success 39 * Return: 0 if OK, , -EINVAL if there is no /binman node, -ECHILD if multiple 40 * images are being used but the first image is not available 41 */ 42static int find_image_node(ofnode *nodep) 43{ 44 ofnode node; 45 46 node = ofnode_path("/binman"); 47 if (!ofnode_valid(node)) 48 return log_msg_ret("binman node", -EINVAL); 49 if (ofnode_read_bool(node, "multiple-images")) { 50 node = ofnode_first_subnode(node); 51 52 if (!ofnode_valid(node)) 53 return log_msg_ret("first image", -ECHILD); 54 } 55 *nodep = node; 56 57 return 0; 58} 59 60static int binman_entry_find_internal(ofnode node, const char *name, 61 struct binman_entry *entry) 62{ 63 int ret; 64 65 if (!ofnode_valid(node)) 66 node = binman->image; 67 node = ofnode_find_subnode(node, name); 68 if (!ofnode_valid(node)) 69 return log_msg_ret("node", -ENOENT); 70 71 ret = ofnode_read_u32(node, "image-pos", &entry->image_pos); 72 if (ret) 73 return log_msg_ret("image-pos", ret); 74 ret = ofnode_read_u32(node, "size", &entry->size); 75 if (ret) 76 return log_msg_ret("size", ret); 77 78 return 0; 79} 80 81int binman_entry_find(const char *name, struct binman_entry *entry) 82{ 83 return binman_entry_find_internal(binman->image, name, entry); 84} 85 86int binman_entry_map(ofnode parent, const char *name, void **bufp, int *sizep) 87{ 88 struct binman_entry entry; 89 int ret; 90 91 if (binman->rom_offset == ROM_OFFSET_NONE) 92 return -EPERM; 93 ret = binman_entry_find_internal(parent, name, &entry); 94 if (ret) 95 return log_msg_ret("entry", ret); 96 if (sizep) 97 *sizep = entry.size; 98 *bufp = map_sysmem(entry.image_pos + binman->rom_offset, entry.size); 99 100 return 0; 101} 102 103ofnode binman_section_find_node(const char *name) 104{ 105 return ofnode_find_subnode(binman->image, name); 106} 107 108void binman_set_rom_offset(int rom_offset) 109{ 110 binman->rom_offset = rom_offset; 111} 112 113int binman_get_rom_offset(void) 114{ 115 return binman->rom_offset; 116} 117 118int binman_select_subnode(const char *name) 119{ 120 ofnode node; 121 int ret; 122 123 ret = find_image_node(&node); 124 if (ret) 125 return log_msg_ret("main", -ENOENT); 126 node = ofnode_find_subnode(node, name); 127 if (!ofnode_valid(node)) 128 return log_msg_ret("node", -ENOENT); 129 binman->image = node; 130 log_info("binman: Selected image subnode '%s'\n", 131 ofnode_get_name(binman->image)); 132 133 return 0; 134} 135 136int binman_init(void) 137{ 138 int ret; 139 140 binman = malloc(sizeof(struct binman_info)); 141 if (!binman) 142 return log_msg_ret("space for binman", -ENOMEM); 143 ret = find_image_node(&binman->image); 144 if (ret) 145 return log_msg_ret("node", -ENOENT); 146 binman_set_rom_offset(ROM_OFFSET_NONE); 147 log_debug("binman: Selected image node '%s'\n", 148 ofnode_get_name(binman->image)); 149 150 return 0; 151} 152