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