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