1 /*
2  * Copyright (c) 2023 Yonatan Schachter
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_INCLUDE_ZEPHYR_BINDESC_H_
8 #define ZEPHYR_INCLUDE_ZEPHYR_BINDESC_H_
9 
10 #ifdef __cplusplus
11 extern "C" {
12 #endif /* __cplusplus */
13 
14 /*
15  * Corresponds to the definitions in scripts/west_commands/bindesc.py.
16  * Do not change without syncing the definitions in both files!
17  */
18 #define BINDESC_MAGIC 0xb9863e5a7ea46046
19 #define BINDESC_ALIGNMENT 4
20 #define BINDESC_TYPE_UINT 0x0
21 #define BINDESC_TYPE_STR 0x1
22 #define BINDESC_TYPE_BYTES 0x2
23 #define BINDESC_TYPE_DESCRIPTORS_END 0xf
24 
25 /**
26  * @brief Binary Descriptor Definition
27  * @defgroup bindesc_define Bindesc Define
28  * @{
29  */
30 
31 /*
32  * Corresponds to the definitions in scripts/west_commands/bindesc.py.
33  * Do not change without syncing the definitions in both files!
34  */
35 
36 /** The app version string such as "1.2.3" */
37 #define BINDESC_ID_APP_VERSION_STRING 0x800
38 
39 /** The app version major such as 1 */
40 #define BINDESC_ID_APP_VERSION_MAJOR 0x801
41 
42 /** The app version minor such as 2 */
43 #define BINDESC_ID_APP_VERSION_MINOR 0x802
44 
45 /** The app version patchlevel such as 3 */
46 #define BINDESC_ID_APP_VERSION_PATCHLEVEL 0x803
47 
48 /** The app version number such as 0x10203 */
49 #define BINDESC_ID_APP_VERSION_NUMBER 0x804
50 
51 /** The kernel version string such as "3.4.0" */
52 #define BINDESC_ID_KERNEL_VERSION_STRING 0x900
53 
54 /** The kernel version major such as 3 */
55 #define BINDESC_ID_KERNEL_VERSION_MAJOR 0x901
56 
57 /** The kernel version minor such as 4 */
58 #define BINDESC_ID_KERNEL_VERSION_MINOR 0x902
59 
60 /** The kernel version patchlevel such as 0 */
61 #define BINDESC_ID_KERNEL_VERSION_PATCHLEVEL 0x903
62 
63 /** The kernel version number such as 0x30400 */
64 #define BINDESC_ID_KERNEL_VERSION_NUMBER 0x904
65 
66 /** The year the image was compiled in */
67 #define BINDESC_ID_BUILD_TIME_YEAR 0xa00
68 
69 /** The month of the year the image was compiled in */
70 #define BINDESC_ID_BUILD_TIME_MONTH 0xa01
71 
72 /** The day of the month the image was compiled in */
73 #define BINDESC_ID_BUILD_TIME_DAY 0xa02
74 
75 /** The hour of the day the image was compiled in */
76 #define BINDESC_ID_BUILD_TIME_HOUR 0xa03
77 
78 /** The minute the image was compiled in */
79 #define BINDESC_ID_BUILD_TIME_MINUTE 0xa04
80 
81 /** The second the image was compiled in */
82 #define BINDESC_ID_BUILD_TIME_SECOND 0xa05
83 
84 /** The UNIX time (seconds since midnight of 1970/01/01) the image was compiled in */
85 #define BINDESC_ID_BUILD_TIME_UNIX 0xa06
86 
87 /** The date and time of compilation such as "2023/02/05 00:07:04" */
88 #define BINDESC_ID_BUILD_DATE_TIME_STRING 0xa07
89 
90 /** The date of compilation such as "2023/02/05" */
91 #define BINDESC_ID_BUILD_DATE_STRING 0xa08
92 
93 /** The time of compilation such as "00:07:04" */
94 #define BINDESC_ID_BUILD_TIME_STRING 0xa09
95 
96 /** The name of the host that compiled the image */
97 #define BINDESC_ID_HOST_NAME 0xb00
98 
99 /** The C compiler name */
100 #define BINDESC_ID_C_COMPILER_NAME 0xb01
101 
102 /** The C compiler version */
103 #define BINDESC_ID_C_COMPILER_VERSION 0xb02
104 
105 /** The C++ compiler name */
106 #define BINDESC_ID_CXX_COMPILER_NAME 0xb03
107 
108 /** The C++ compiler version */
109 #define BINDESC_ID_CXX_COMPILER_VERSION 0xb04
110 
111 #define BINDESC_TAG_DESCRIPTORS_END BINDESC_TAG(DESCRIPTORS_END, 0x0fff)
112 
113 /**
114  * @cond INTERNAL_HIDDEN
115  */
116 
117 /*
118  * Utility macro to generate a tag from a type and an ID
119  *
120  * type - Type of the descriptor, UINT, STR or BYTES
121  * id - Unique ID for the descriptor, must fit in 12 bits
122  */
123 #define BINDESC_TAG(type, id) ((BINDESC_TYPE_##type & 0xf) << 12 | (id & 0x0fff))
124 
125 /**
126  * @endcond
127  */
128 
129 #if !IS_ENABLED(_LINKER)
130 
131 #include <zephyr/sys/byteorder.h>
132 
133 /**
134  * @cond INTERNAL_HIDDEN
135  */
136 
137 /*
138  * Utility macro to get the name of a bindesc entry
139  */
140 #define BINDESC_NAME(name) bindesc_entry_##name
141 
142 /* Convenience helper for declaring a binary descriptor entry. */
143 #define __BINDESC_ENTRY_DEFINE(name)							\
144 	__aligned(BINDESC_ALIGNMENT) const struct bindesc_entry BINDESC_NAME(name)	\
145 	__in_section(_bindesc_entry, static, name) __used __noasan
146 
147 /**
148  * @endcond
149  */
150 
151 /**
152  * @brief Define a binary descriptor of type string.
153  *
154  * @details
155  * Define a string that is registered in the binary descriptor header.
156  * The defined string can be accessed using @ref BINDESC_GET_STR
157  *
158  * @note The defined string is not static, so its name must not collide with
159  * any other symbol in the executable.
160  *
161  * @param name Name of the descriptor
162  * @param id Unique ID of the descriptor
163  * @param value A string value for the descriptor
164  */
165 #define BINDESC_STR_DEFINE(name, id, value)	\
166 	__BINDESC_ENTRY_DEFINE(name) = {	\
167 		.tag = BINDESC_TAG(STR, id),	\
168 		.len = (uint16_t)sizeof(value),	\
169 		.data = value,			\
170 	}
171 
172 /**
173  * @brief Define a binary descriptor of type uint.
174  *
175  * @details
176  * Define an integer that is registered in the binary descriptor header.
177  * The defined integer can be accessed using @ref BINDESC_GET_UINT
178  *
179  * @note The defined integer is not static, so its name must not collide with
180  * any other symbol in the executable.
181  *
182  * @param name Name of the descriptor
183  * @param id Unique ID of the descriptor
184  * @param value An integer value for the descriptor
185  */
186 #define BINDESC_UINT_DEFINE(name, id, value)		\
187 	__BINDESC_ENTRY_DEFINE(name) = {		\
188 		.tag = BINDESC_TAG(UINT, id),		\
189 		.len = (uint16_t)sizeof(uint32_t),	\
190 		.data = sys_uint32_to_array(value),	\
191 	}
192 
193 /**
194  * @brief Define a binary descriptor of type bytes.
195  *
196  * @details
197  * Define a uint8_t array that is registered in the binary descriptor header.
198  * The defined array can be accessed using @ref BINDESC_GET_BYTES.
199  * The value should be given as an array literal, wrapped in parentheses, for
200  * example:
201  *
202  *     BINDESC_BYTES_DEFINE(name, id, ({1, 2, 3, 4}));
203  *
204  * @note The defined array is not static, so its name must not collide with
205  * any other symbol in the executable.
206  *
207  * @param name Name of the descriptor
208  * @param id Unique ID of the descriptor
209  * @param value A uint8_t array as data for the descriptor
210  */
211 #define BINDESC_BYTES_DEFINE(name, id, value)				\
212 	__BINDESC_ENTRY_DEFINE(name) = {				\
213 		.tag = BINDESC_TAG(BYTES, id),				\
214 		.len = (uint16_t)sizeof((uint8_t [])__DEBRACKET value),	\
215 		.data = __DEBRACKET value,				\
216 	}
217 
218 /**
219  * @brief Get the value of a string binary descriptor
220  *
221  * @details
222  * Get the value of a string binary descriptor, previously defined by
223  * BINDESC_STR_DEFINE.
224  *
225  * @param name Name of the descriptor
226  */
227 #define BINDESC_GET_STR(name) BINDESC_NAME(name).data
228 
229 /**
230  * @brief Get the value of a uint binary descriptor
231  *
232  * @details
233  * Get the value of a uint binary descriptor, previously defined by
234  * BINDESC_UINT_DEFINE.
235  *
236  * @param name Name of the descriptor
237  */
238 #define BINDESC_GET_UINT(name) *(uint32_t *)&(BINDESC_NAME(name).data)
239 
240 /**
241  * @brief Get the value of a bytes binary descriptor
242  *
243  * @details
244  * Get the value of a string binary descriptor, previously defined by
245  * BINDESC_BYTES_DEFINE. The returned value can be accessed as an array:
246  *
247  *     for (size_t i = 0; i < BINDESC_GET_SIZE(name); i++)
248  *         BINDESC_GET_BYTES(name)[i];
249  *
250  * @param name Name of the descriptor
251  */
252 #define BINDESC_GET_BYTES(name) BINDESC_NAME(name).data
253 
254 /**
255  * @brief Get the size of a binary descriptor
256  *
257  * @details
258  * Get the size of a binary descriptor. This is particularly useful for
259  * bytes binary descriptors where there's no null terminator.
260  *
261  * @param name Name of the descriptor
262  */
263 #define BINDESC_GET_SIZE(name) BINDESC_NAME(name).len
264 
265 /**
266  * @}
267  */
268 
269 /*
270  * An entry of the binary descriptor header. Each descriptor is
271  * described by one of these entries.
272  */
273 struct bindesc_entry {
274 	/** Tag of the entry */
275 	uint16_t tag;
276 	/** Length of the descriptor data */
277 	uint16_t len;
278 	/** Value of the entry. This is either an integer or a string */
279 	uint8_t data[];
280 } __packed;
281 
282 /*
283  * We're assuming that `struct bindesc_entry` has a specific layout in
284  * memory, so it's worth making sure that the layout is really what we
285  * think it is. If these assertions fail for your toolchain/platform,
286  * please open a bug report.
287  */
288 BUILD_ASSERT(offsetof(struct bindesc_entry, tag) == 0, "Incorrect memory layout");
289 BUILD_ASSERT(offsetof(struct bindesc_entry, len) == 2, "Incorrect memory layout");
290 BUILD_ASSERT(offsetof(struct bindesc_entry, data) == 4, "Incorrect memory layout");
291 
292 #if IS_ENABLED(CONFIG_BINDESC_KERNEL_VERSION_STRING)
293 extern const struct bindesc_entry BINDESC_NAME(kernel_version_string);
294 #endif /* IS_ENABLED(CONFIG_BINDESC_KERNEL_VERSION_STRING) */
295 
296 #if IS_ENABLED(CONFIG_BINDESC_KERNEL_VERSION_MAJOR)
297 extern const struct bindesc_entry BINDESC_NAME(kernel_version_major);
298 #endif /* IS_ENABLED(CONFIG_BINDESC_KERNEL_VERSION_MAJOR) */
299 
300 #if IS_ENABLED(CONFIG_BINDESC_KERNEL_VERSION_MINOR)
301 extern const struct bindesc_entry BINDESC_NAME(kernel_version_minor);
302 #endif /* IS_ENABLED(CONFIG_BINDESC_KERNEL_VERSION_MINOR) */
303 
304 #if IS_ENABLED(CONFIG_BINDESC_KERNEL_VERSION_PATCHLEVEL)
305 extern const struct bindesc_entry BINDESC_NAME(kernel_version_patchlevel);
306 #endif /* IS_ENABLED(CONFIG_BINDESC_KERNEL_VERSION_PATCHLEVEL) */
307 
308 #if IS_ENABLED(CONFIG_BINDESC_KERNEL_VERSION_NUMBER)
309 extern const struct bindesc_entry BINDESC_NAME(kernel_version_number);
310 #endif /* IS_ENABLED(CONFIG_BINDESC_KERNEL_VERSION_NUMBER) */
311 
312 #if IS_ENABLED(CONFIG_BINDESC_APP_VERSION_STRING)
313 extern const struct bindesc_entry BINDESC_NAME(app_version_string);
314 #endif /* IS_ENABLED(CONFIG_BINDESC_APP_VERSION_STRING) */
315 
316 #if IS_ENABLED(CONFIG_BINDESC_APP_VERSION_MAJOR)
317 extern const struct bindesc_entry BINDESC_NAME(app_version_major);
318 #endif /* IS_ENABLED(CONFIG_BINDESC_APP_VERSION_MAJOR) */
319 
320 #if IS_ENABLED(CONFIG_BINDESC_APP_VERSION_MINOR)
321 extern const struct bindesc_entry BINDESC_NAME(app_version_minor);
322 #endif /* IS_ENABLED(CONFIG_BINDESC_APP_VERSION_MINOR) */
323 
324 #if IS_ENABLED(CONFIG_BINDESC_APP_VERSION_PATCHLEVEL)
325 extern const struct bindesc_entry BINDESC_NAME(app_version_patchlevel);
326 #endif /* IS_ENABLED(CONFIG_BINDESC_APP_VERSION_PATCHLEVEL) */
327 
328 #if IS_ENABLED(CONFIG_BINDESC_APP_VERSION_NUMBER)
329 extern const struct bindesc_entry BINDESC_NAME(app_version_number);
330 #endif /* IS_ENABLED(CONFIG_BINDESC_APP_VERSION_NUMBER) */
331 
332 #if IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_YEAR)
333 extern const struct bindesc_entry BINDESC_NAME(build_time_year);
334 #endif /* IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_YEAR) */
335 
336 #if IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_MONTH)
337 extern const struct bindesc_entry BINDESC_NAME(build_time_month);
338 #endif /* IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_MONTH) */
339 
340 #if IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_DAY)
341 extern const struct bindesc_entry BINDESC_NAME(build_time_day);
342 #endif /* IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_DAY) */
343 
344 #if IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_HOUR)
345 extern const struct bindesc_entry BINDESC_NAME(build_time_hour);
346 #endif /* IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_HOUR) */
347 
348 #if IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_MINUTE)
349 extern const struct bindesc_entry BINDESC_NAME(build_time_minute);
350 #endif /* IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_MINUTE) */
351 
352 #if IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_SECOND)
353 extern const struct bindesc_entry BINDESC_NAME(build_time_second);
354 #endif /* IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_SECOND) */
355 
356 #if IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_UNIX)
357 extern const struct bindesc_entry BINDESC_NAME(build_time_unix);
358 #endif /* IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_UNIX) */
359 
360 #if IS_ENABLED(CONFIG_BINDESC_BUILD_DATE_TIME_STRING)
361 extern const struct bindesc_entry BINDESC_NAME(build_date_time_string);
362 #endif /* IS_ENABLED(CONFIG_BINDESC_BUILD_DATE_TIME_STRING) */
363 
364 #if IS_ENABLED(CONFIG_BINDESC_BUILD_DATE_STRING)
365 extern const struct bindesc_entry BINDESC_NAME(build_date_string);
366 #endif /* IS_ENABLED(CONFIG_BINDESC_BUILD_DATE_STRING) */
367 
368 #if IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_STRING)
369 extern const struct bindesc_entry BINDESC_NAME(build_time_string);
370 #endif /* IS_ENABLED(CONFIG_BINDESC_BUILD_TIME_STRING) */
371 
372 #if IS_ENABLED(CONFIG_BINDESC_HOST_NAME)
373 extern const struct bindesc_entry BINDESC_NAME(host_name);
374 #endif /* IS_ENABLED(CONFIG_BINDESC_HOST_NAME) */
375 
376 #if IS_ENABLED(CONFIG_BINDESC_C_COMPILER_NAME)
377 extern const struct bindesc_entry BINDESC_NAME(c_compiler_name);
378 #endif /* IS_ENABLED(CONFIG_BINDESC_C_COMPILER_NAME) */
379 
380 #if IS_ENABLED(CONFIG_BINDESC_C_COMPILER_VERSION)
381 extern const struct bindesc_entry BINDESC_NAME(c_compiler_version);
382 #endif /* IS_ENABLED(CONFIG_BINDESC_C_COMPILER_VERSION) */
383 
384 #if IS_ENABLED(CONFIG_BINDESC_CXX_COMPILER_NAME)
385 extern const struct bindesc_entry BINDESC_NAME(cxx_compiler_name);
386 #endif /* IS_ENABLED(CONFIG_BINDESC_CXX_COMPILER_NAME) */
387 
388 #if IS_ENABLED(CONFIG_BINDESC_CXX_COMPILER_VERSION)
389 extern const struct bindesc_entry BINDESC_NAME(cxx_compiler_version);
390 #endif /* IS_ENABLED(CONFIG_BINDESC_CXX_COMPILER_VERSION) */
391 
392 #endif /* !IS_ENABLED(_LINKER) */
393 
394 #ifdef __cplusplus
395 }
396 #endif
397 
398 #endif /* ZEPHYR_INCLUDE_ZEPHYR_BINDESC_H_ */
399