]>
Commit | Line | Data |
---|---|---|
3c10dc95 SG |
1 | // SPDX-License-Identifier: Intel |
2 | /* | |
3 | * Access to binman information at runtime | |
4 | * | |
5 | * Copyright 2019 Google LLC | |
6 | * Written by Simon Glass <[email protected]> | |
7 | */ | |
8 | ||
9 | #include <common.h> | |
10 | #include <binman.h> | |
11 | #include <dm.h> | |
f7ae49fc | 12 | #include <log.h> |
336d4615 | 13 | #include <malloc.h> |
8f9877df | 14 | #include <mapmem.h> |
3c10dc95 | 15 | |
db6fb7d1 SG |
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 | */ | |
3c10dc95 SG |
24 | struct binman_info { |
25 | ofnode image; | |
db6fb7d1 | 26 | int rom_offset; |
3c10dc95 SG |
27 | }; |
28 | ||
db6fb7d1 SG |
29 | #define ROM_OFFSET_NONE (-1) |
30 | ||
3c10dc95 SG |
31 | static struct binman_info *binman; |
32 | ||
76b54d8c SG |
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 | */ | |
43 | static 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 | ||
956a9082 SG |
61 | static int binman_entry_find_internal(ofnode node, const char *name, |
62 | struct binman_entry *entry) | |
3c10dc95 | 63 | { |
3c10dc95 SG |
64 | int ret; |
65 | ||
3c10dc95 | 66 | if (!ofnode_valid(node)) |
956a9082 SG |
67 | node = binman->image; |
68 | node = ofnode_find_subnode(node, name); | |
69 | if (!ofnode_valid(node)) | |
70 | return log_msg_ret("node", -ENOENT); | |
3c10dc95 SG |
71 | |
72 | ret = ofnode_read_u32(node, "image-pos", &entry->image_pos); | |
73 | if (ret) | |
f4f41237 | 74 | return log_msg_ret("image-pos", ret); |
3c10dc95 SG |
75 | ret = ofnode_read_u32(node, "size", &entry->size); |
76 | if (ret) | |
956a9082 | 77 | return log_msg_ret("size", ret); |
3c10dc95 SG |
78 | |
79 | return 0; | |
80 | } | |
81 | ||
956a9082 SG |
82 | int binman_entry_find(const char *name, struct binman_entry *entry) |
83 | { | |
84 | return binman_entry_find_internal(binman->image, name, entry); | |
85 | } | |
86 | ||
8f9877df SG |
87 | int 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 | ||
104 | ofnode binman_section_find_node(const char *name) | |
105 | { | |
106 | return ofnode_find_subnode(binman->image, name); | |
107 | } | |
108 | ||
db6fb7d1 SG |
109 | void binman_set_rom_offset(int rom_offset) |
110 | { | |
111 | binman->rom_offset = rom_offset; | |
112 | } | |
113 | ||
f4f41237 SG |
114 | int binman_get_rom_offset(void) |
115 | { | |
116 | return binman->rom_offset; | |
117 | } | |
118 | ||
1e35a4d2 SG |
119 | int 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; | |
dc2886b0 SG |
131 | log_info("binman: Selected image subnode '%s'\n", |
132 | ofnode_get_name(binman->image)); | |
1e35a4d2 SG |
133 | |
134 | return 0; | |
135 | } | |
136 | ||
3c10dc95 SG |
137 | int binman_init(void) |
138 | { | |
76b54d8c SG |
139 | int ret; |
140 | ||
3c10dc95 SG |
141 | binman = malloc(sizeof(struct binman_info)); |
142 | if (!binman) | |
143 | return log_msg_ret("space for binman", -ENOMEM); | |
76b54d8c SG |
144 | ret = find_image_node(&binman->image); |
145 | if (ret) | |
146 | return log_msg_ret("node", -ENOENT); | |
6723b4c6 | 147 | binman_set_rom_offset(ROM_OFFSET_NONE); |
5e6c9029 SG |
148 | log_debug("binman: Selected image node '%s'\n", |
149 | ofnode_get_name(binman->image)); | |
a9e73d28 | 150 | |
3c10dc95 SG |
151 | return 0; |
152 | } |