]>
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 | ||
3c10dc95 SG |
9 | #include <binman.h> |
10 | #include <dm.h> | |
f7ae49fc | 11 | #include <log.h> |
336d4615 | 12 | #include <malloc.h> |
8f9877df | 13 | #include <mapmem.h> |
3c10dc95 | 14 | |
db6fb7d1 SG |
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 | */ | |
3c10dc95 SG |
23 | struct binman_info { |
24 | ofnode image; | |
db6fb7d1 | 25 | int rom_offset; |
3c10dc95 SG |
26 | }; |
27 | ||
db6fb7d1 SG |
28 | #define ROM_OFFSET_NONE (-1) |
29 | ||
3c10dc95 SG |
30 | static struct binman_info *binman; |
31 | ||
76b54d8c SG |
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 | |
185f812c | 39 | * Return: 0 if OK, , -EINVAL if there is no /binman node, -ECHILD if multiple |
76b54d8c SG |
40 | * images are being used but the first image is not available |
41 | */ | |
42 | static 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 | ||
956a9082 SG |
60 | static int binman_entry_find_internal(ofnode node, const char *name, |
61 | struct binman_entry *entry) | |
3c10dc95 | 62 | { |
3c10dc95 SG |
63 | int ret; |
64 | ||
3c10dc95 | 65 | if (!ofnode_valid(node)) |
956a9082 SG |
66 | node = binman->image; |
67 | node = ofnode_find_subnode(node, name); | |
68 | if (!ofnode_valid(node)) | |
69 | return log_msg_ret("node", -ENOENT); | |
3c10dc95 SG |
70 | |
71 | ret = ofnode_read_u32(node, "image-pos", &entry->image_pos); | |
72 | if (ret) | |
f4f41237 | 73 | return log_msg_ret("image-pos", ret); |
3c10dc95 SG |
74 | ret = ofnode_read_u32(node, "size", &entry->size); |
75 | if (ret) | |
956a9082 | 76 | return log_msg_ret("size", ret); |
3c10dc95 SG |
77 | |
78 | return 0; | |
79 | } | |
80 | ||
956a9082 SG |
81 | int binman_entry_find(const char *name, struct binman_entry *entry) |
82 | { | |
83 | return binman_entry_find_internal(binman->image, name, entry); | |
84 | } | |
85 | ||
8f9877df SG |
86 | int 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 | ||
103 | ofnode binman_section_find_node(const char *name) | |
104 | { | |
105 | return ofnode_find_subnode(binman->image, name); | |
106 | } | |
107 | ||
db6fb7d1 SG |
108 | void binman_set_rom_offset(int rom_offset) |
109 | { | |
110 | binman->rom_offset = rom_offset; | |
111 | } | |
112 | ||
f4f41237 SG |
113 | int binman_get_rom_offset(void) |
114 | { | |
115 | return binman->rom_offset; | |
116 | } | |
117 | ||
1e35a4d2 SG |
118 | int 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; | |
dc2886b0 SG |
130 | log_info("binman: Selected image subnode '%s'\n", |
131 | ofnode_get_name(binman->image)); | |
1e35a4d2 SG |
132 | |
133 | return 0; | |
134 | } | |
135 | ||
3c10dc95 SG |
136 | int binman_init(void) |
137 | { | |
76b54d8c SG |
138 | int ret; |
139 | ||
3c10dc95 SG |
140 | binman = malloc(sizeof(struct binman_info)); |
141 | if (!binman) | |
142 | return log_msg_ret("space for binman", -ENOMEM); | |
76b54d8c SG |
143 | ret = find_image_node(&binman->image); |
144 | if (ret) | |
145 | return log_msg_ret("node", -ENOENT); | |
6723b4c6 | 146 | binman_set_rom_offset(ROM_OFFSET_NONE); |
5e6c9029 SG |
147 | log_debug("binman: Selected image node '%s'\n", |
148 | ofnode_get_name(binman->image)); | |
a9e73d28 | 149 | |
3c10dc95 SG |
150 | return 0; |
151 | } |