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