1 /*
2  * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef _PICO_BINARY_INFO_CODE_H
8 #define _PICO_BINARY_INFO_CODE_H
9 
10 // pico.h is not available when PICO_NO_BINARY_INFO=1 is used for builds outside of the SDK (e.g. picotool)
11 // and only needed anyway (because of macro definitions) in PICO_NO_BINARY_INFO=0 builds
12 #if !PICO_NO_BINARY_INFO
13 #include "pico.h"
14 #endif
15 
16 #include "pico/binary_info/structure.h"
17 
18 #if !PICO_NO_BINARY_INFO
19 #define __bi_decl(name, bi, section_prefix, attr) static const attr __attribute__((section(section_prefix __STRING(name)))) struct _binary_info_core *const name = bi
20 #define __bi_lineno_var_name __CONCAT(__bi_, __LINE__)
21 #define __bi_ptr_lineno_var_name __CONCAT(__bi_ptr, __LINE__)
22 #define __bi_enclosure_check_lineno_var_name __CONCAT(_error_bi_is_missing_enclosing_decl_,__LINE__)
23 #define __bi_mark_enclosure static const __unused int __bi_enclosure_check_lineno_var_name=0;
24 #if __cplusplus || __GNUC__ >= 8
25 #define __bi_enclosure_check(x) (x + __bi_enclosure_check_lineno_var_name)
26 #else
27 // skip the version check on older GCC non C++, as it doesn't compile.. this is only here to catch the
28 // user accidentally forgetting to enclose the binary item with bi_decl
29 #define __bi_enclosure_check(x) (x)
30 #endif
31 /**
32  * \brief Declare some binary information that will be included if the contain source file/line is compiled into the binary
33  * \ingroup pico_binary_info
34  */
35 #define bi_decl(_decl) __bi_mark_enclosure _decl; __bi_decl(__bi_ptr_lineno_var_name, &__bi_lineno_var_name.core, ".binary_info.keep.", __used);
36 /**
37  * \brief Declare some binary information that will be included if the function containing the decl is linked into the binary.
38  * The SDK uses --gc-sections, so functions that are never called will be removed by the linker, and any associated
39  * binary information declared this way will also be stripped
40  * \ingroup pico_binary_info
41  */
42 #define bi_decl_if_func_used(_decl) ({__bi_mark_enclosure _decl; __bi_decl(__bi_ptr_lineno_var_name, &__bi_lineno_var_name.core, ".binary_info.", ); *(const volatile uint8_t *)&__bi_ptr_lineno_var_name;});
43 
44 #define bi_decl_with_attr(_decl, _attr) __bi_mark_enclosure _attr _decl; __bi_decl(__bi_ptr_lineno_var_name, &__bi_lineno_var_name.core, ".binary_info.keep.", __used);
45 #define bi_decl_if_func_used_with_attr(_decl, _attr) ({__bi_mark_enclosure _attr _decl; __bi_decl(__bi_ptr_lineno_var_name, &__bi_lineno_var_name.core, ".binary_info.", ); *(const volatile uint8_t *)&__bi_ptr_lineno_var_name;});
46 #else
47 #define __bi_decl(bi, name, attr)
48 #define bi_decl_with_attr(_decl, _attr)
49 #define bi_decl(_decl)
50 #define bi_decl_if_func_used_with_attr(_decl, _attr) ((void)0);
51 #define bi_decl_if_func_used(_decl) ((void)0);
52 #endif
53 
54 #define bi_int(_tag, _id, _value) \
55      static const struct _binary_info_id_and_int __bi_lineno_var_name = { \
56         .core = { \
57             .type = __bi_enclosure_check(BINARY_INFO_TYPE_ID_AND_INT), \
58             .tag = _tag, \
59         },\
60         .id = _id, \
61         .value = _value \
62     };
63 
64 #define bi_string(_tag, _id, _value) \
65     static const struct _binary_info_id_and_string __bi_lineno_var_name = { \
66         .core = { \
67             .type = __bi_enclosure_check(BINARY_INFO_TYPE_ID_AND_STRING), \
68             .tag = _tag, \
69         },\
70         .id = _id, \
71         .value = _value, \
72     }
73 
74 #define __bi_ptr_int32_with_name(_tag, _id, _label, _value) \
75     static const struct _binary_info_ptr_int32_with_name __bi_lineno_var_name = { \
76         .core = { \
77             .type = __bi_enclosure_check(BINARY_INFO_TYPE_PTR_INT32_WITH_NAME), \
78             .tag = _tag, \
79         },\
80         .id = _id, \
81         .value = &_value, \
82         .label = _label, \
83     }
84 
85 #define bi_ptr_int32(_tag, _id, _var, _default) __attribute__((section(".data"))) static int _var = _default; __bi_ptr_int32_with_name(_tag, _id, __STRING(_var), _var)
86 
87 #define __bi_ptr_string_with_name(_tag, _id, _label, _value, _len) \
88     static const struct _binary_info_ptr_string_with_name __bi_lineno_var_name = { \
89         .core = { \
90             .type = __bi_enclosure_check(BINARY_INFO_TYPE_PTR_STRING_WITH_NAME), \
91             .tag = _tag, \
92         },\
93         .id = _id, \
94         .value = _value, \
95         .label = _label, \
96         .len = _len, \
97     }
98 
99 #define bi_ptr_string(_tag, _id, _var, _default, _max_len) static char _var[_max_len] = _default; __bi_ptr_string_with_name(_tag, _id, __STRING(_var), _var, _max_len)
100 
101 #define bi_block_device(_tag, _name, _address, _size, _extra, _flags) \
102     static const struct _binary_info_block_device __bi_lineno_var_name = { \
103         .core = { \
104             .type = __bi_enclosure_check(BINARY_INFO_TYPE_BLOCK_DEVICE), \
105             .tag = _tag, \
106         },\
107         .name = _name, \
108         .address = _address, \
109         .size = _size, \
110         .extra = _extra, \
111         .flags = _flags, \
112     }
113 
114 #define __bi_encoded_pins_with_func(_encoding) \
115     static const struct _binary_info_pins_with_func __bi_lineno_var_name = { \
116         .core = { \
117             .type = __bi_enclosure_check(BINARY_INFO_TYPE_PINS_WITH_FUNC), \
118             .tag = BINARY_INFO_TAG_RASPBERRY_PI, \
119         },\
120         .pin_encoding = _encoding \
121     }
122 
123 #define __bi_encoded_pins_64_with_func(_encoding) \
124     static const struct _binary_info_pins64_with_func __bi_lineno_var_name = { \
125         .core = { \
126             .type = __bi_enclosure_check(BINARY_INFO_TYPE_PINS64_WITH_FUNC), \
127             .tag = BINARY_INFO_TAG_RASPBERRY_PI, \
128         },\
129         .pin_encoding = _encoding \
130     }
131 
132 #define __bi_pins_with_name(_mask, _label) \
133     static const struct _binary_info_pins_with_name __bi_lineno_var_name = { \
134         .core = { \
135             .type = __bi_enclosure_check(BINARY_INFO_TYPE_PINS_WITH_NAME), \
136             .tag = BINARY_INFO_TAG_RASPBERRY_PI, \
137         },\
138         .pin_mask = _mask, \
139         .label = _label \
140     }
141 
142 #define __bi_pins_64_with_name(_mask, _label) \
143     static const struct _binary_info_pins64_with_name __bi_lineno_var_name = { \
144         .core = { \
145             .type = __bi_enclosure_check(BINARY_INFO_TYPE_PINS64_WITH_NAME), \
146             .tag = BINARY_INFO_TAG_RASPBERRY_PI, \
147         },\
148         .pin_mask = _mask, \
149         .label = _label \
150     }
151 
152 #define __bi_named_group(_parent_tag, _parent_id, _group_tag, _group_id, _label, _flags) \
153 static const struct _binary_info_named_group __bi_lineno_var_name = { \
154         .core = { \
155             .type = __bi_enclosure_check(BINARY_INFO_TYPE_NAMED_GROUP), \
156             .tag = _parent_tag, \
157         },\
158         .parent_id = _parent_id, \
159         .group_tag = _group_tag, \
160         .flags = _flags, \
161         .group_id = _group_id, \
162         .label = _label \
163     }
164 
165 #define bi_binary_end(end) bi_int(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_BINARY_END, end)
166 #define bi_program_name(name) bi_string(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_PROGRAM_NAME, name)
167 #define bi_program_description(description) bi_string(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_PROGRAM_DESCRIPTION, description)
168 #define bi_program_version_string(version_string) bi_string(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_PROGRAM_VERSION_STRING, version_string)
169 #define bi_program_build_date_string(date_string) bi_string(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_PROGRAM_BUILD_DATE_STRING, date_string)
170 #define bi_program_url(url) bi_string(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_PROGRAM_URL, url)
171 // multiple of these may be added
172 #define bi_program_feature(feature) bi_string(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_PROGRAM_FEATURE, feature)
173 #define bi_program_build_attribute(attr) bi_string(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_PROGRAM_BUILD_ATTRIBUTE, attr)
174 #define bi_program_feature_group(tag, id, name) __bi_named_group(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_PROGRAM_FEATURE, tag, id, name, 0)
175 #define bi_program_feature_group_with_flags(tag, id, name, flags) __bi_named_group(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_PROGRAM_FEATURE, tag, id, name, flags)
176 
177 
178 #ifndef PICO_BINARY_INFO_USE_PINS_64
179 #define PICO_BINARY_INFO_USE_PINS_64 (NUM_BANK0_GPIOS > 32)
180 #endif
181 
182 #if !PICO_BINARY_INFO_USE_PINS_64
183 #define bi_1pin_with_func(p0, func)                  __bi_encoded_pins_with_func(BI_PINS_ENCODING_MULTI | ((func << 3)) | ((p0) << 7) | ((p0) << 12))
184 #define bi_2pins_with_func(p0, p1, func)             __bi_encoded_pins_with_func(BI_PINS_ENCODING_MULTI | ((func << 3)) | ((p0) << 7) | ((p1) << 12) | ((p1) << 17))
185 #define bi_3pins_with_func(p0, p1, p2, func)         __bi_encoded_pins_with_func(BI_PINS_ENCODING_MULTI | ((func << 3)) | ((p0) << 7) | ((p1) << 12) | ((p2) << 17) | ((p2) << 22))
186 #define bi_4pins_with_func(p0, p1, p2, p3, func)     __bi_encoded_pins_with_func(BI_PINS_ENCODING_MULTI | ((func << 3)) | ((p0) << 7) | ((p1) << 12) | ((p2) << 17) | ((p3) << 22) | ((p3) << 27))
187 #define bi_5pins_with_func(p0, p1, p2, p3, p4, func) __bi_encoded_pins_with_func(BI_PINS_ENCODING_MULTI | ((func << 3)) | ((p0) << 7) | ((p1) << 12) | ((p2) << 17) | ((p3) << 22) | ((p4) << 27))
188 #define bi_pin_range_with_func(plo, phi, func)       __bi_encoded_pins_with_func(BI_PINS_ENCODING_RANGE | ((func << 3)) | ((plo) << 7) | ((phi) << 12))
189 
190 #define bi_pin_mask_with_name(pmask, label)          __bi_pins_with_name((pmask), (label))
191 // names are separated by | ... i.e. "name1|name2|name3"
192 #define bi_pin_mask_with_names(pmask, label)          __bi_pins_with_name((pmask), (label))
193 #else
194 #define bi_1pin_with_func(p0, func)                         __bi_encoded_pins_64_with_func(BI_PINS_ENCODING_MULTI | ((func << 3)) | ((p0) << 8) | ((p0) << 16))
195 #define bi_2pins_with_func(p0, p1, func)                    __bi_encoded_pins_64_with_func(BI_PINS_ENCODING_MULTI | ((func << 3)) | ((p0) << 8) | ((p1) << 16) | ((p1) << 24))
196 #define bi_3pins_with_func(p0, p1, p2, func)                __bi_encoded_pins_64_with_func(BI_PINS_ENCODING_MULTI | ((func << 3)) | ((p0) << 8) | ((p1) << 16) | ((p2) << 24) | ((uint64_t)(p2) << 32))
197 #define bi_4pins_with_func(p0, p1, p2, p3, func)            __bi_encoded_pins_64_with_func(BI_PINS_ENCODING_MULTI | ((func << 3)) | ((p0) << 8) | ((p1) << 16) | ((p2) << 24) | ((uint64_t)(p3) << 32) | ((uint64_t)(p3) << 40))
198 #define bi_5pins_with_func(p0, p1, p2, p3, p4, func)        __bi_encoded_pins_64_with_func(BI_PINS_ENCODING_MULTI | ((func << 3)) | ((p0) << 8) | ((p1) << 16) | ((p2) << 24) | ((uint64_t)(p3) << 32) | ((uint64_t)(p4) << 40) | ((uint64_t)(p4) << 48))
199 #define bi_pin_range_with_func(plo, phi, func)              __bi_encoded_pins_64_with_func(BI_PINS_ENCODING_RANGE | ((func << 3)) | ((plo) << 8) | ((phi) << 16))
200 
201 #define bi_pin_mask_with_name(pmask, label)          __bi_pins_64_with_name((uint64_t)(pmask), (label))
202 // names are separated by | ... i.e. "name1|name2|name3"
203 #define bi_pin_mask_with_names(pmask, label)          __bi_pins_64_with_name((uint64_t)(pmask), (label))
204 #endif
205 
206 // 6 and 7 pins require pins_64
207 #define bi_6pins_with_func(p0, p1, p2, p3, p4, p5, func)    __bi_encoded_pins_64_with_func(BI_PINS_ENCODING_MULTI | ((func << 3)) | ((p0) << 8) | ((p1) << 16) | ((p2) << 24) | ((uint64_t)(p3) << 32) | ((uint64_t)(p4) << 40) | ((uint64_t)(p5) << 48) | ((uint64_t)(p5) << 56))
208 #define bi_7pins_with_func(p0, p1, p2, p3, p4, p5, p6,func) __bi_encoded_pins_64_with_func(BI_PINS_ENCODING_MULTI | ((func << 3)) | ((p0) << 8) | ((p1) << 16) | ((p2) << 24) | ((uint64_t)(p3) << 32) | ((uint64_t)(p4) << 40) | ((uint64_t)(p5) << 48) | ((uint64_t)(p6) << 56))
209 
210 #define bi_1pin_with_name(p0, name)                   bi_pin_mask_with_name(1ull << (p0), name)
211 #define bi_2pins_with_names(p0, name0, p1, name1)     bi_pin_mask_with_names((1ull << (p0)) | (1ull << (p1)), p0 < p1 ? name0 "|" name1 : name1 "|" name0)
212 #define bi_3pins_with_names(p0, name0, p1, name1, p2, name2)  bi_pin_mask_with_names((1ull << (p0)) | (1ull << (p1)) | (1ull << (p2)),\
213     p0 < p1 ?\
214         (p1 < p2 ?\
215             name0 "|" name1 "|" name2:\
216             (p0 < p2 ? name0 "|" name2 "|" name1 : name2 "|" name0 "|" name1)):\
217         (p1 < p2 ?\
218             (p0 < p2 ? name1 "|" name0 "|" name2 : name1 "|" name2 "|" name0) :\
219             name2 "|" name1 "|" name0))
220 #define bi_4pins_with_names(p0, name0, p1, name1, p2, name2, p3, name3)  bi_pin_mask_with_names((1ull << (p0)) | (1ull << (p1)) | (1ull << (p2)) | (1ull << (p3)),\
221     p0 < p1 ?\
222         (p1 < p2 ?\
223             (p2 < p3 ?\
224                 name0 "|" name1 "|" name2 "|" name3:\
225                 (p0 < p3 ?\
226                     (p1 < p3 ?\
227                         name0 "|" name1 "|" name3 "|" name2:\
228                         name0 "|" name3 "|" name1 "|" name2):\
229                     name3 "|" name0 "|" name1 "|" name2)):\
230             (p2 < p3 ?\
231                 (p0 < p2 ?\
232                     (p1 < p3 ?\
233                         name0 "|" name2 "|" name1 "|" name3:\
234                         name0 "|" name2 "|" name3 "|" name1):\
235                     (p0 < p3 ?\
236                         (p1 < p3 ?\
237                             name2 "|" name0 "|" name1 "|" name3:\
238                             name2 "|" name0 "|" name3 "|" name1):\
239                         name2 "|" name3 "|" name0 "|" name1)):\
240                 (p0 < p2 ?\
241                     (p0 < p3 ?\
242                         name0 "|" name3 "|" name2 "|" name1:\
243                         name3 "|" name0 "|" name2 "|" name1):\
244                     name3 "|" name2 "|" name0 "|" name1))):\
245         (p1 < p2 ?\
246             (p2 < p3 ?\
247                 (p0 < p2 ?\
248                     name1 "|" name0 "|" name2 "|" name3:\
249                     (p0 < p3 ?\
250                         name1 "|" name2 "|" name0 "|" name3:\
251                         name1 "|" name2 "|" name3 "|" name0)):\
252                 (p0 < p2 ?\
253                     (p0 < p3 ?\
254                         name1 "|" name0 "|" name3 "|" name2:\
255                         (p1 < p3 ?\
256                             name1 "|" name3 "|" name0 "|" name2:\
257                             name3 "|" name1 "|" name0 "|" name2)):\
258                     (p1 < p3 ?\
259                         name1 "|" name3 "|" name2 "|" name0:\
260                         name3 "|" name1 "|" name2 "|" name0))):\
261             (p2 < p3 ?\
262                 (p0 < p3 ?\
263                     name2 "|" name1 "|" name0 "|" name3:\
264                     (p1 < p3 ?\
265                         name2 "|" name1 "|" name3 "|" name0:\
266                         name2 "|" name3 "|" name1 "|" name0)):\
267                 name3 "|" name2 "|" name1 "|" name0)))
268 
269 #endif
270