Skip to content

Commit 7a8b876

Browse files
committed
tests: app_loader: add uninstall test app + matching syscalls and wrappers
1 parent de87deb commit 7a8b876

File tree

7 files changed

+191
-28
lines changed

7 files changed

+191
-28
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Makefile for user application
2+
3+
# Specify this directory relative to the current application.
4+
TOCK_USERLAND_BASE_DIR = ../../../..
5+
6+
# Which files to compile.
7+
C_SRCS := $(wildcard *.c)
8+
9+
# Include app loading support rules. Rules to generate app binary images.
10+
include $(TOCK_USERLAND_BASE_DIR)/AppMakefile.mk
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Dynamic App Loader (Helper App)
2+
=================================
3+
4+
This app waits upon the user to press one of two buttons on the device (if supported).
5+
6+
When Button 1 (Default user button on boards) is pressed, the app tried to load in the
7+
`blink` app.
8+
9+
When Button 2 is pressed, the app tries to load in the `adc` app.
10+
11+
There are three stages to this:
12+
13+
1. Setup Phase
14+
2. Flash Phase
15+
3. Load Phase
16+
17+
#### Setup Phase
18+
During the setup phase, the application passes the size of the new app `(blink)/(adc)`'s
19+
binary to the app_loader capsule.
20+
21+
The capsule returns with either a success or failure.
22+
23+
On success, the app requests the app_loader capsule to flash the `blink/adc` app.
24+
25+
On Failure, the app exits logs the reason for failure and exits.
26+
27+
#### Flash Phase
28+
The app sends the binary of the `blink/adc` app 512 bytes (this is the size of the shared
29+
buffer between the app and the capsule) at a time along with the offset.
30+
31+
The capsule checks that these values do not violate the bounds dictated by the kernel
32+
and then requests the kernel to flash the app.
33+
34+
The kernel performs more stringent checking on the request to ensure that memory access
35+
violations do not take place, and flashes the app.
36+
37+
The capsule then returns with either a success or failure.
38+
39+
On success, the app requests the app_loader capsule to load the `blink/adc` app.
40+
41+
On Failure, the app exits logs the reason for failure and exits.
42+
43+
#### Load Phase
44+
The app requests the capsule to load the new app. There are only two outcomes:
45+
46+
1. The `blink/adc` app is loaded successfully and functions without requiring a restart.
47+
2. The load process failed somewhere, and the app is erased.
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#include <math.h>
2+
#include <stdio.h>
3+
#include <string.h>
4+
5+
#include <libtock-sync/services/alarm.h>
6+
#include <libtock/interface/button.h>
7+
#include <libtock/kernel/app_loader.h>
8+
#include <libtock/tock.h>
9+
10+
#include <inttypes.h>
11+
12+
/******************************************************************************************************
13+
* Short ID and version of app that has to be uninstalled (Blink in this case)
14+
******************************************************************************************************/
15+
const uint32_t short_id = 4246331976;
16+
const uint32_t version = 0;
17+
18+
/******************************************************************************************************
19+
* Callback Tracking Flags
20+
******************************************************************************************************/
21+
static bool uninstall_done = false; // to check if setup is done
22+
static bool app_uninstall = false; // to track if app has to be uninstalled
23+
24+
/******************************************************************************************************
25+
* Callback functions
26+
*
27+
* Set button callback to initiate the uninstall on pressing buttons
28+
******************************************************************************************************/
29+
30+
static void app_uninstall_done_callback(__attribute__((unused)) int arg0,
31+
__attribute__((unused)) int arg1,
32+
__attribute__((unused)) int arg2,
33+
__attribute__((unused)) void* ud) {
34+
35+
if (arg0 != RETURNCODE_SUCCESS) {
36+
printf("[Error] Uninstall failed: %d.\n", arg0);
37+
} else {
38+
printf("[Success] Uninstalled app successfully.\n");
39+
}
40+
uninstall_done = true;
41+
}
42+
43+
// Callback for button presses.
44+
static void button_callback(__attribute__ ((unused)) returncode_t retval, int btn_num, __attribute__ (
45+
(unused)) bool pressed) {
46+
// Callback for button presses.
47+
if (btn_num == 0) {
48+
app_uninstall = true;
49+
} else {
50+
printf("[App Uninstaller] Invalid button selected. Unable to uninstall!\n");
51+
}
52+
}
53+
54+
55+
/******************************************************************************************************
56+
* Main
57+
******************************************************************************************************/
58+
59+
int main(void) {
60+
printf("[Log] Simple test app to uninstall an app during runtime.\n");
61+
62+
// check if app loader driver exists
63+
if (!libtock_app_loader_exists()) {
64+
printf("No App Loader driver!\n");
65+
return -1;
66+
}
67+
68+
int count;
69+
int err = libtock_button_count(&count);
70+
// Ensure there is a button to use.
71+
if (err < 0) return err;
72+
printf("[Log] There are %d buttons on this board.\n", count);
73+
74+
// Enable interrupts on each button.
75+
for (int i = 0; i < count; i++) {
76+
libtock_button_notify_on_press(i, button_callback);
77+
}
78+
79+
printf("[Log] Waiting for a button press.\n");
80+
81+
while (1) {
82+
if (app_uninstall) {
83+
printf("Uninstalling app with Short ID: %" PRIu32 " and version %" PRIu32 "\n", short_id, version);
84+
int ret = libtock_app_loader_uninstall(short_id, version, app_uninstall_done_callback);
85+
if (ret != RETURNCODE_SUCCESS) {
86+
printf("[Error] Uninstall Failed: %d.\n", ret);
87+
tock_exit(ret);
88+
}
89+
yield_for(&uninstall_done);
90+
uninstall_done = false;
91+
app_uninstall = false;
92+
}
93+
yield();
94+
}
95+
}

libtock/kernel/app_loader.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,3 +143,20 @@ returncode_t libtock_app_loader_abort(subscribe_upcall cb) {
143143

144144
return libtock_app_loader_command_abort();
145145
}
146+
147+
/******************************************************************************************************
148+
* Function to uninstall an existing application
149+
*
150+
* Takes the short id and version of the app and the callback function as arguments
151+
******************************************************************************************************/
152+
153+
returncode_t libtock_app_loader_uninstall(uint32_t app_short_id, uint32_t app_version, subscribe_upcall cb) {
154+
// set up the uninstall done callback
155+
int err = libtock_app_loader_set_uninstall_upcall(cb, NULL);
156+
if (err != 0) {
157+
printf("[Error] Failed to set setup done callback: %d\n", err);
158+
return err;
159+
}
160+
161+
return libtock_app_loader_command_uninstall(app_short_id, app_version);
162+
}

libtock/kernel/app_loader.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ returncode_t libtock_app_loader_load(subscribe_upcall cb);
1818

1919
returncode_t libtock_app_loader_abort(subscribe_upcall cb);
2020

21+
returncode_t libtock_app_loader_uninstall(uint32_t app_short_id, uint32_t app_version, subscribe_upcall cb);
22+
2123

2224
#ifdef __cplusplus
2325
}

libtock/kernel/syscalls/app_loader_syscalls.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ returncode_t libtock_app_loader_set_abort_upcall(subscribe_upcall cb, void* user
2929
return tock_subscribe_return_to_returncode(sval);
3030
}
3131

32+
returncode_t libtock_app_loader_set_uninstall_upcall(subscribe_upcall cb, void* userdata) {
33+
subscribe_return_t sval = subscribe(DRIVER_NUM_APP_LOADER, 5, cb, userdata);
34+
return tock_subscribe_return_to_returncode(sval);
35+
}
36+
3237
returncode_t libtock_app_loader_write_buffer(uint8_t* buffer, uint32_t len) {
3338
allow_ro_return_t aval = allow_readonly(DRIVER_NUM_APP_LOADER, 0, (void*) buffer, len);
3439
return tock_allow_ro_return_to_returncode(aval);
@@ -57,4 +62,9 @@ returncode_t libtock_app_loader_command_load(void) {
5762
returncode_t libtock_app_loader_command_abort(void) {
5863
syscall_return_t res = command(DRIVER_NUM_APP_LOADER, 5, 0, 0);
5964
return tock_command_return_novalue_to_returncode(res);
65+
}
66+
67+
returncode_t libtock_app_loader_command_uninstall(uint32_t app_short_id, uint32_t app_version) {
68+
syscall_return_t res = command(DRIVER_NUM_APP_LOADER, 6, app_short_id, app_version);
69+
return tock_command_return_novalue_to_returncode(res);
6070
}

libtock/kernel/syscalls/app_loader_syscalls.h

Lines changed: 10 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,26 +15,12 @@ extern "C"
1515
*/
1616
bool libtock_app_loader_exists(void);
1717

18-
/*
19-
* Function to setup the callback from capsule.
20-
* This function takes in the function that will be executed
21-
* when the callback is triggered.
22-
*/
23-
returncode_t libtock_app_loader_set_setup_upcall(subscribe_upcall cb, void* userdata);
24-
2518
/*
2619
* Command to request the kernel to set up for a new app.
2720
* This functions takes the size of the new app as the argument.
2821
*/
2922
returncode_t libtock_app_loader_command_setup(uint32_t app_length);
3023

31-
/*
32-
* Function to setup the callback from capsule.
33-
* This function takes in the function that will be executed
34-
* when the callback is triggered.
35-
*/
36-
returncode_t libtock_app_loader_set_write_upcall(subscribe_upcall cb, void* userdata);
37-
3824
/*
3925
* Function to set up a shared buffer with the capsule.
4026
* This buffer is used to write data to the flash.
@@ -51,13 +37,6 @@ returncode_t libtock_app_loader_write_buffer(uint8_t* buffer, uint32_t len);
5137
*/
5238
returncode_t libtock_app_loader_command_write(uint32_t flash_offset, uint32_t write_length);
5339

54-
/*
55-
* Function to setup the callback from capsule.
56-
* This function takes in the function that will be executed
57-
* when the callback is triggered.
58-
*/
59-
returncode_t libtock_app_loader_set_finalize_upcall(subscribe_upcall cb, void* userdata);
60-
6140
/*
6241
* Signal to kernel we are done writing a new process binary.
6342
*/
@@ -69,23 +48,26 @@ returncode_t libtock_app_loader_command_finalize(void);
6948
returncode_t libtock_app_loader_command_load(void);
7049

7150
/*
72-
* Function to setup the callback from capsule.
73-
* This function takes in the function that will be executed
74-
* when the callback is triggered.
51+
* Command to request the kernel to abort setup/writing process.
7552
*/
76-
returncode_t libtock_app_loader_set_load_upcall(subscribe_upcall cb, void* userdata);
53+
returncode_t libtock_app_loader_command_abort(void);
7754

7855
/*
79-
* Command to request the kernel to abort setup/writing process.
56+
* Command to request the kernel to uninstall an application.
8057
*/
81-
returncode_t libtock_app_loader_command_abort(void);
58+
returncode_t libtock_app_loader_command_uninstall(uint32_t app_short_id, uint32_t app_version);
8259

8360
/*
84-
* Function to setup the callback from capsule.
61+
* Functions to setup the callback from capsule.
8562
* This function takes in the function that will be executed
8663
* when the callback is triggered.
8764
*/
65+
returncode_t libtock_app_loader_set_setup_upcall(subscribe_upcall cb, void* userdata);
66+
returncode_t libtock_app_loader_set_write_upcall(subscribe_upcall cb, void* userdata);
67+
returncode_t libtock_app_loader_set_finalize_upcall(subscribe_upcall cb, void* userdata);
68+
returncode_t libtock_app_loader_set_load_upcall(subscribe_upcall cb, void* userdata);
8869
returncode_t libtock_app_loader_set_abort_upcall(subscribe_upcall cb, void* userdata);
70+
returncode_t libtock_app_loader_set_uninstall_upcall(subscribe_upcall cb, void* userdata);
8971

9072

9173

0 commit comments

Comments
 (0)