1
+ #include <stdio.h>
2
+ #include <stdlib.h>
3
+
4
+ #include <math.h>
5
+ #include <string.h>
6
+
7
+ #include <libtock-sync/services/alarm.h>
8
+ #include <libtock/kernel/app_loader.h>
9
+ #include <libtock/kernel/ipc.h>
10
+
11
+ #include "loadable_binaries.h"
12
+
13
+ #define FLASH_BUFFER_SIZE 512
14
+ #define RETURNCODE_SUCCESS 0
15
+
16
+ static bool setup_done = false; // to check if setup is done
17
+ static bool write_done = false; // to check if writing to flash is done
18
+ static bool finalize_done = false; // to check if the kernel is done finalizing the process binary
19
+ static bool load_done = false; // to check if the process was loaded successfully
20
+
21
+ uint8_t app_id = 0 ;
22
+
23
+
24
+ /********************************
25
+ * Function prototypes
26
+ *********************************/
27
+ int install_binary (uint8_t id );
28
+
29
+
30
+ /******************************************************************************************************
31
+ * Callback functions
32
+ *
33
+ * 1. Callback to let us know when the capsule is done writing data to flash
34
+ * 2. Set button callback to initiate the dynamic app load process on pressing button 1 (on nrf52840dk)
35
+ *
36
+ ******************************************************************************************************/
37
+
38
+ static void app_setup_done_callback (__attribute__((unused )) int arg0 ,
39
+ __attribute__((unused )) int arg1 ,
40
+ __attribute__((unused )) int arg2 ,
41
+ __attribute__((unused )) void * ud ) {
42
+ setup_done = true;
43
+ }
44
+
45
+ static void app_write_done_callback (__attribute__((unused )) int arg0 ,
46
+ __attribute__((unused )) int arg1 ,
47
+ __attribute__((unused )) int arg2 ,
48
+ __attribute__((unused )) void * ud ) {
49
+ write_done = true;
50
+ }
51
+
52
+ static void app_finalize_done_callback (__attribute__((unused )) int arg0 ,
53
+ __attribute__((unused )) int arg1 ,
54
+ __attribute__((unused )) int arg2 ,
55
+ __attribute__((unused )) void * ud ) {
56
+ finalize_done = true;
57
+ }
58
+
59
+ static void app_load_done_callback (int arg0 ,
60
+ __attribute__((unused )) int arg1 ,
61
+ __attribute__((unused )) int arg2 ,
62
+ __attribute__((unused )) void * ud ) {
63
+
64
+ if (arg0 != RETURNCODE_SUCCESS ) {
65
+ printf ("[Error] Process creation failed: %d.\n" , arg0 );
66
+ } else {
67
+ printf ("[Success] Process created successfully.\n" );
68
+ }
69
+ load_done = true;
70
+ }
71
+
72
+ int install_binary (uint8_t id ) {
73
+ if (BINARY_COUNT == 0 ) {
74
+ printf ("[App Loader] No included apps. Unable to install!\n" );
75
+ return -1 ;
76
+ }
77
+
78
+ const char * app_name = NULL ;
79
+ unsigned char * app_data = NULL ;
80
+ size_t app_size = 0 ;
81
+ size_t binary_size = 0 ;
82
+
83
+ app_name = binary_names [id ];
84
+ app_data = (uint8_t * )(uintptr_t )binaries [id ];
85
+ app_size = binary_sizes [id ];
86
+ binary_size = actual_sizes [id ];
87
+
88
+ printf ("[AppLoader] Requested to load %s!\n" , app_name );
89
+
90
+ int ret = libtock_app_loader_setup (app_size );
91
+ if (ret != RETURNCODE_SUCCESS ) {
92
+ printf ("[Error] Setup Failed: %d.\n" , ret );
93
+ return -1 ;
94
+ }
95
+
96
+ yield_for (& setup_done );
97
+ setup_done = false;
98
+
99
+ printf ("[Success] Setup successful. Writing app to flash.\n" );
100
+ int ret1 = write_app (binary_size , app_data );
101
+ if (ret1 != RETURNCODE_SUCCESS ) {
102
+ printf ("[Error] App flash write unsuccessful: %d.\n" , ret1 );
103
+ return -1 ;
104
+ }
105
+
106
+ printf ("[Success] App flashed successfully. Creating process now.\n" );
107
+ int ret2 = libtock_app_loader_load ();
108
+ if (ret2 != RETURNCODE_SUCCESS ) {
109
+ printf ("[Error] Process creation failed: %d.\n" , ret2 );
110
+ return -1 ;
111
+ }
112
+
113
+ // wait on load done callback
114
+ yield_for (& load_done );
115
+ load_done = false;
116
+
117
+ return 0 ;
118
+ }
119
+
120
+ /******************************************************************************************************
121
+ *
122
+ * Function to write the app into the flash
123
+ *
124
+ * Takes app size and the app binary as arguments
125
+ ******************************************************************************************************/
126
+
127
+ int write_app (double size , uint8_t binary []) {
128
+
129
+ uint32_t write_count = 0 ;
130
+ uint8_t write_buffer [FLASH_BUFFER_SIZE ];
131
+ uint32_t flash_offset = 0 ;
132
+
133
+ // This value can be changed to different sizes
134
+ // to mimic different bus widths.
135
+ uint32_t write_buffer_size = FLASH_BUFFER_SIZE ;
136
+
137
+ // set the write buffer
138
+ int ret = libtock_app_loader_set_buffer (write_buffer , FLASH_BUFFER_SIZE );
139
+ if (ret != RETURNCODE_SUCCESS ) {
140
+ printf ("[Error] Failed to set the write buffer: %d.\n" , ret );
141
+ return -1 ;
142
+ }
143
+
144
+ write_count = (size + write_buffer_size - 1 ) / write_buffer_size ;
145
+
146
+ for (uint32_t offset = 0 ; offset < write_count ; offset ++ ) {
147
+
148
+ memset (write_buffer , 0 , write_buffer_size );
149
+ // copy binary to write buffer
150
+ flash_offset = (offset * write_buffer_size );
151
+ size_t bytes_left = size - flash_offset ;
152
+ size_t chunk = bytes_left < write_buffer_size ? bytes_left : write_buffer_size ;
153
+ memcpy (write_buffer , & binary [write_buffer_size * offset ], chunk );
154
+ int ret1 = libtock_app_loader_write (flash_offset , write_buffer_size );
155
+ if (ret1 != 0 ) {
156
+ printf ("[Error] Failed writing data to flash at address: 0x%lx\n" , flash_offset );
157
+ printf ("[Error] Error nature: %d\n" , ret1 );
158
+ return -1 ;
159
+ }
160
+ // wait on write done callback
161
+ yield_for (& write_done );
162
+ write_done = false;
163
+ }
164
+
165
+ // Now that we are done writing the binary, we ask the kernel to finalize it.
166
+ printf ("Done writing app, finalizing.\n" );
167
+ int ret2 = libtock_app_loader_finalize ();
168
+ if (ret2 != 0 ) {
169
+ printf ("[Error] Failed to finalize new process binary.\n" );
170
+ return -1 ;
171
+ }
172
+ yield_for (& finalize_done );
173
+ finalize_done = false;
174
+
175
+ return 0 ;
176
+ }
177
+
178
+ static void ipc_callback (int pid , int len , int buf , __attribute__ ((unused )) void * ud ) {
179
+ uint8_t * buffer = (uint8_t * ) (uintptr_t ) buf ;
180
+ const char * name_buffer = (const char * ) (uintptr_t ) buf ;
181
+
182
+ int offset = 0 ;
183
+ int num_binaries = sizeof (binary_sizes ) / sizeof (binary_sizes [0 ]);
184
+
185
+ if (len < 1 ) {
186
+ // Need at least one byte for the command.
187
+ return ;
188
+ }
189
+
190
+ uint8_t command = buffer [0 ];
191
+
192
+ switch (command ) {
193
+ case 0 :
194
+ // Return the number of binaries available
195
+ buffer [0 ] = num_binaries ;
196
+ ipc_notify_client (pid );
197
+ break ;
198
+
199
+ case 1 :
200
+ // Return the list of binaries to display on the menu
201
+ if (len < num_binaries + 1 ) {
202
+ printf ("[AppLoader] Returning on Command 0x01\n" );
203
+ return ;
204
+ }
205
+
206
+ for (int i = 0 ; i < num_binaries ; i ++ ) {
207
+ size_t name_len = strlen (binary_names [i ]);
208
+
209
+ if ((size_t )(offset + name_len + 1 ) > (size_t )len ) {
210
+ printf ("[AppLoader] Buffer overflow risk.\n" );
211
+ return ;
212
+ }
213
+
214
+ // Copy the binary name to the buffer
215
+ memcpy ((void * ) & name_buffer [offset ], binary_names [i ], name_len + 1 );
216
+ offset += name_len + 1 ;
217
+ }
218
+
219
+ ipc_notify_client (pid );
220
+ break ;
221
+
222
+ case 2 :
223
+ // install certain app
224
+ if (len < 2 ) {
225
+ // app id missing
226
+ printf ("[AppLoader] Returning on Command 0x02\n" );
227
+ return ;
228
+ }
229
+
230
+ app_id = buffer [1 ];
231
+ int ret = install_binary (app_id );
232
+ buffer [0 ] = ret ;
233
+ ipc_notify_client (pid );
234
+ break ;
235
+ }
236
+ }
237
+
238
+
239
+ int main (void ) {
240
+
241
+ if (!libtock_app_loader_exists ()) {
242
+ printf ("[Error] Failed to detect App Loader Driver!\n" );
243
+ return -1 ;
244
+ }
245
+
246
+ // set up the setup done callback
247
+ int err1 = libtock_app_loader_subscribe_setup (app_setup_done_callback , NULL );
248
+ if (err1 != 0 ) {
249
+ printf ("[Error] Failed to set setup done callback: %d\n" , err1 );
250
+ return err1 ;
251
+ }
252
+
253
+ // set up the write done callback
254
+ int err2 = libtock_app_loader_subscribe_write (app_write_done_callback , NULL );
255
+ if (err2 != 0 ) {
256
+ printf ("[Error] Failed to set flash write done callback: %d\n" , err2 );
257
+ return err2 ;
258
+ }
259
+
260
+ // set up the finalize done callback
261
+ int err3 = libtock_app_loader_subscribe_finalize (app_finalize_done_callback , NULL );
262
+ if (err3 != 0 ) {
263
+ printf ("[Error] Failed to set finalize done callback: %d\n" , err3 );
264
+ return err3 ;
265
+ }
266
+
267
+ // set up the load done callback
268
+ int err4 = libtock_app_loader_subscribe_load (app_load_done_callback , NULL );
269
+ if (err4 != 0 ) {
270
+ printf ("[Error] Failed to set load done callback: %d\n" , err4 );
271
+ return err4 ;
272
+ }
273
+
274
+ ipc_register_service_callback ("app_loader" , ipc_callback ,
275
+ NULL );
276
+
277
+ while (1 ) {
278
+ yield ();
279
+ }
280
+ }
0 commit comments