1 /*
2  * Copyright (c) 2023 Yonatan Schachter
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/bindesc.h>
9 #include <zephyr/drivers/flash.h>
10 
11 BINDESC_STR_DEFINE(my_string, 1, "Hello world!");
12 BINDESC_UINT_DEFINE(my_int, 2, 5);
13 BINDESC_BYTES_DEFINE(my_bytes, 3, ({1, 2, 3, 4}));
14 
15 const struct device *flash = DEVICE_DT_GET(DT_CHOSEN(zephyr_flash_controller));
16 
dump_bytes(const uint8_t * buffer,size_t size)17 void dump_bytes(const uint8_t *buffer, size_t size)
18 {
19 	size_t i;
20 
21 	for (i = 0; i < size; i++) {
22 		printk("%02x ", buffer[i]);
23 	}
24 	printk("\n");
25 }
26 
dump_descriptors_callback(const struct bindesc_entry * entry,void * user_data)27 int dump_descriptors_callback(const struct bindesc_entry *entry, void *user_data)
28 {
29 	ARG_UNUSED(user_data);
30 
31 	printk("tag: %hu len: %hu data: ", entry->tag, entry->len);
32 
33 	switch (BINDESC_GET_TAG_TYPE(entry->tag)) {
34 	case BINDESC_TYPE_UINT:
35 		printk("%u\n", *(const uint32_t *)entry->data);
36 		break;
37 	case BINDESC_TYPE_STR:
38 		printk("%s\n", (const char *)entry->data);
39 		break;
40 	case BINDESC_TYPE_BYTES:
41 		dump_bytes((const uint8_t *)entry->data, entry->len);
42 		break;
43 	case BINDESC_TYPE_DESCRIPTORS_END:
44 		printk("Descriptors terminator\n");
45 		break;
46 	default:
47 		printk("\n");
48 		break;
49 	}
50 
51 	return 0;
52 }
53 
main(void)54 int main(void)
55 {
56 	size_t bindesc_offset = UINT16_MAX;
57 	const uint32_t *version_number;
58 	struct bindesc_handle handle;
59 	uint8_t buffer[0x100];
60 	const uint8_t *bytes;
61 	const char *version;
62 	size_t size;
63 	int retval;
64 	size_t i;
65 
66 	/*
67 	 * In a normal application, the offset of the descriptors should be constant and known,
68 	 * usually right after the vector table. It can easily be retrieved using
69 	 * ``west bindesc get_offset path/to/zephyr.bin``.
70 	 * This sample however is intended for multiple devices, and therefore just searches for
71 	 * the descriptors in order to remain generic.
72 	 */
73 	for (i = 0; i < UINT16_MAX; i += sizeof(void *)) {
74 		if (*(uint64_t *)(CONFIG_FLASH_BASE_ADDRESS + i) == BINDESC_MAGIC) {
75 			printk("Found descriptors at 0x%x\n", i);
76 			bindesc_offset = i;
77 			break;
78 		}
79 	}
80 	if (i == UINT16_MAX) {
81 		printk("Descriptors not found\n");
82 		return 1;
83 	}
84 
85 	printk("\n##################################\n");
86 	printk("Reading using memory mapped flash:\n");
87 	printk("##################################\n");
88 
89 	bindesc_open_memory_mapped_flash(&handle, bindesc_offset);
90 	bindesc_foreach(&handle, dump_descriptors_callback, NULL);
91 
92 	bindesc_find_str(&handle, BINDESC_ID_KERNEL_VERSION_STRING, &version);
93 	printk("Zephyr version: %s\n", version);
94 
95 	bindesc_get_size(&handle, &size);
96 	printk("Bindesc size: %u\n", size);
97 
98 	printk("\n##################\n");
99 	printk("Reading using RAM:\n");
100 	printk("##################\n");
101 
102 	flash_read(flash, bindesc_offset, buffer, sizeof(buffer));
103 
104 	bindesc_open_ram(&handle, buffer, sizeof(buffer));
105 
106 	/* Search for a non-existent descriptor */
107 	retval = bindesc_find_str(&handle, 123, &version);
108 	if (retval) {
109 		printk("Descriptor not found!\n");
110 	}
111 
112 	bindesc_find_uint(&handle, BINDESC_ID_KERNEL_VERSION_MAJOR, &version_number);
113 	printk("Zephyr version number: %u\n", *version_number);
114 
115 	printk("\n####################\n");
116 	printk("Reading using flash:\n");
117 	printk("####################\n");
118 
119 	bindesc_open_flash(&handle, bindesc_offset, flash);
120 
121 	bindesc_find_bytes(&handle, 3, &bytes, &size);
122 	printk("my_bytes: ");
123 	dump_bytes(bytes, size);
124 
125 	return 0;
126 }
127