Skip to content

Commit 842a5cc

Browse files
committed
wip: successfully running more than 1 container
1 parent aa5659a commit 842a5cc

File tree

6 files changed

+185
-114
lines changed

6 files changed

+185
-114
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,5 +63,6 @@ process_wasm_binaries()
6363
if(TARGET_PLATFORM_NAME STREQUAL "Linux")
6464
include(${CMAKE_CURRENT_LIST_DIR}/src/shared/platform/posix/ocre_internal.cmake)
6565
elseif(TARGET_PLATFORM_NAME STREQUAL "Zephyr")
66+
include_directories(${CMAKE_CURRENT_BINARY_DIR})
6667
include(${CMAKE_CURRENT_LIST_DIR}/src/shared/platform/zephyr/ocre_internal.cmake)
6768
endif()

cmake/embed_wasm_binary.cmake

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -90,20 +90,21 @@ function(embed_wasm_binary)
9090

9191
message(STATUS "Detected architecture: ${ARCH_NAME}, using objcopy format: ${OBJCOPY_FORMAT}")
9292

93-
# Convert WASM to object file (use symbol name for unique files)
94-
set(WASM_OBJECT_FILE ${CMAKE_CURRENT_BINARY_DIR}/wasm_${WASM_SYMBOL_NAME}.o)
95-
96-
add_custom_command(
97-
OUTPUT ${WASM_OBJECT_FILE}
98-
COMMAND objcopy
99-
-I binary
100-
-O ${OBJCOPY_FORMAT}
101-
--rename-section .data=.rodata.wasm,alloc,load,readonly,data,contents
102-
${WASM_STAGED_FILE}
103-
${WASM_OBJECT_FILE}
104-
DEPENDS ${WASM_STAGED_FILE}
105-
COMMENT "Converting to object file (${OBJCOPY_FORMAT} for ${ARCH_NAME})"
106-
)
93+
# Convert WASM to object file (use symbol name for unique files)
94+
set(WASM_OBJECT_FILE ${CMAKE_CURRENT_BINARY_DIR}/wasm_${WASM_SYMBOL_NAME}.o)
95+
96+
add_custom_command(
97+
OUTPUT ${WASM_OBJECT_FILE}
98+
COMMAND ${CMAKE_COMMAND} -E chdir ${CMAKE_CURRENT_BINARY_DIR}
99+
objcopy
100+
-I binary
101+
-O ${OBJCOPY_FORMAT}
102+
--rename-section .data=.rodata.wasm.${WASM_SYMBOL_NAME},alloc,load,readonly,data,contents
103+
${WASM_OUTPUT_NAME}
104+
wasm_${WASM_SYMBOL_NAME}.o
105+
DEPENDS ${WASM_STAGED_FILE}
106+
COMMENT "Converting to object file (${OBJCOPY_FORMAT} for ${ARCH_NAME})"
107+
)
107108

108109
# Create a custom target
109110
add_custom_target(${WASM_TARGET_NAME} DEPENDS ${WASM_OBJECT_FILE})

src/ocre/wasm_manifest.h.in

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,23 @@
1515
typedef struct {
1616
const char *name; // Container name
1717
const uint8_t *data; // Pointer to WASM binary
18-
size_t size; // Size in bytes
1918
} wasm_binary_entry_t;
2019

2120
// Number of embedded WASM binaries
2221
#define WASM_BINARY_COUNT @COUNT@
2322

24-
// Manifest array
23+
// Manifest array (size calculated on access, not at initialization)
2524
static const wasm_binary_entry_t wasm_manifest[WASM_BINARY_COUNT] = {
2625
@MANIFEST_ENTRIES@
2726
};
2827

28+
// Helper function to get size (calculated at runtime)
29+
static inline size_t wasm_get_size(int index) {
30+
if (index < 0 || index >= WASM_BINARY_COUNT) return 0;
31+
@SIZE_CALCULATIONS@
32+
return 0;
33+
}
34+
2935
// Helper function to find a WASM binary by name
3036
static inline const wasm_binary_entry_t* wasm_find(const char *name) {
3137
if (!name) return NULL;
@@ -37,9 +43,10 @@ static inline const wasm_binary_entry_t* wasm_find(const char *name) {
3743
return NULL;
3844
}
3945

40-
// Helper function to get WASM binary by index
46+
// Helper function to get WASM binary by index (with runtime size calculation)
4147
static inline const wasm_binary_entry_t* wasm_get(int index) {
4248
if (index < 0 || index >= WASM_BINARY_COUNT) return NULL;
49+
// Note: size field is 0 in static array, use wasm_get_size() to get actual size
4350
return &wasm_manifest[index];
4451
}
4552

src/samples-mini/zephyr/main.c

Lines changed: 130 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -5,106 +5,146 @@
55
* SPDX-License-Identifier: Apache-2.0
66
*/
77

8-
#include <zephyr/kernel.h>
9-
#include <zephyr/fs/fs.h>
10-
#include "ocre_core_external.h"
11-
#include <zephyr/net/net_if.h>
12-
#include <zephyr/net/dhcpv4.h>
13-
14-
#include <ocre/ocre.h>
15-
#include <ocre/ocre_container_runtime/ocre_container_runtime.h>
16-
17-
#ifdef HAS_GENERATED_INPUT
18-
#include <ocre/ocre_input_file.g>
19-
#else
20-
#include <ocre/ocre_input_file.h>
21-
#endif
22-
23-
void create_sample_container();
24-
int ocre_network_init();
25-
26-
int main(int argc, char *argv[]) {
27-
ocre_cs_ctx ctx;
28-
ocre_container_init_arguments_t args;
29-
char *container_filename = "hello";
30-
31-
#ifdef CONFIG_OCRE_NETWORKING
32-
int net_status = ocre_network_init();
33-
if (net_status < 0) {
34-
printf("Unable to connect to network\n");
35-
} else {
36-
printf("Network is UP\n");
37-
}
38-
#endif
39-
40-
ocre_app_storage_init();
41-
42-
// Step 1: Initialize the Ocre runtime
43-
ocre_container_runtime_status_t ret = ocre_container_runtime_init(&ctx, &args);
44-
45-
if (ret == RUNTIME_STATUS_INITIALIZED) {
46-
printf("\n\nOcre runtime started\n");
47-
48-
create_sample_container(container_filename);
49-
50-
// Step 2: Create the container, this allocates and loads the container binary
51-
ocre_container_data_t ocre_container_data;
52-
int container_ID;
53-
54-
ocre_container_data.heap_size = 0;
55-
snprintf(ocre_container_data.name, sizeof(ocre_container_data.name), "Hello World");
56-
snprintf(ocre_container_data.sha256, sizeof(ocre_container_data.sha256), "%s", container_filename);
57-
ocre_container_data.timers = 0;
58-
ocre_container_runtime_create_container(&ctx, &ocre_container_data, &container_ID, NULL);
59-
60-
// Step 3: Execute the container
61-
ocre_container_runtime_run_container(container_ID, NULL);
62-
// Loop forever, without this the application will exit and stop all execution
63-
while (true) {
64-
core_sleep_ms(1000);
8+
#include <zephyr/kernel.h>
9+
#include <zephyr/fs/fs.h>
10+
#include "ocre_core_external.h"
11+
#include <zephyr/net/net_if.h>
12+
#include <zephyr/net/dhcpv4.h>
13+
14+
#include <ocre/ocre.h>
15+
#include <ocre/ocre_container_runtime/ocre_container_runtime.h>
16+
17+
#ifdef HAS_WASM_MANIFEST
18+
#include "wasm_manifest.h"
19+
#endif
20+
21+
void create_containers_from_manifest(ocre_cs_ctx *ctx);
22+
int ocre_network_init();
23+
24+
int main(int argc, char *argv[]) {
25+
ocre_cs_ctx ctx;
26+
ocre_container_init_arguments_t args;
27+
28+
#ifdef CONFIG_OCRE_NETWORKING
29+
int net_status = ocre_network_init();
30+
if (net_status < 0) {
31+
printf("Unable to connect to network\n");
32+
} else {
33+
printf("Network is UP\n");
34+
}
35+
#endif
36+
37+
ocre_app_storage_init();
38+
39+
// Step 1: Initialize the Ocre runtime
40+
ocre_container_runtime_status_t ret = ocre_container_runtime_init(&ctx, &args);
41+
42+
if (ret == RUNTIME_STATUS_INITIALIZED) {
43+
printf("\n\nOcre runtime started\n");
44+
45+
#ifdef HAS_WASM_MANIFEST
46+
// Create and run all containers from manifest
47+
printf("Found %d WASM binaries to load\n", WASM_BINARY_COUNT);
48+
create_containers_from_manifest(&ctx);
49+
#else
50+
printf("ERROR: No WASM binaries provided. Build with -f option.\n");
51+
#endif
52+
53+
// Loop forever, without this the application will exit and stop all execution
54+
while (true) {
55+
core_sleep_ms(1000);
56+
}
57+
58+
} else {
59+
printf("\n\nOcre runtime failed to start.\n");
60+
}
61+
}
62+
63+
#ifdef HAS_WASM_MANIFEST
64+
/**
65+
* Create and run all containers from the embedded WASM manifest
66+
*/
67+
void create_containers_from_manifest(ocre_cs_ctx *ctx) {
68+
int container_IDs[WASM_BINARY_COUNT];
69+
70+
// Step 1: Write all WASM binaries to filesystem
71+
for (int i = 0; i < WASM_BINARY_COUNT; i++) {
72+
const wasm_binary_entry_t *entry = wasm_get(i);
73+
size_t actual_size = wasm_get_size(i); // ← Use the helper function!
74+
75+
printf("Loading WASM: %s (%zu bytes) from flash\n", entry->name, actual_size);
76+
77+
// Write to filesystem
78+
char file_path[64];
79+
struct fs_file_t f;
80+
snprintf(file_path, sizeof(file_path), "/lfs/ocre/images/%s.bin", entry->name);
81+
82+
fs_file_t_init(&f);
83+
int res = fs_open(&f, file_path, FS_O_CREATE | FS_O_RDWR);
84+
if (res < 0) {
85+
printf(" ERROR: Failed to create file: %d\n", res);
86+
continue;
6587
}
6688

67-
} else {
68-
printf("\n\nOcre runtime failed to start.\n");
89+
fs_write(&f, entry->data, actual_size); // ← Use actual_size
90+
fs_close(&f);
91+
printf(" Written to: %s\n", file_path);
6992
}
70-
}
7193

72-
/**
73-
* Creates a container image file using the sample "hello-word" WASM module
74-
* This is for demostration purposes only and does not perform any error checking.
75-
*
76-
* @param file_name a string containing the name of the file to create
77-
*/
94+
// Step 2: Create all containers
95+
for (int i = 0; i < WASM_BINARY_COUNT; i++) {
96+
const wasm_binary_entry_t *entry = wasm_get(i);
97+
98+
ocre_container_data_t container_data;
99+
container_data.heap_size = 0;
100+
snprintf(container_data.name, sizeof(container_data.name), "%s", entry->name);
101+
snprintf(container_data.sha256, sizeof(container_data.sha256), "%s", entry->name);
102+
container_data.timers = 0;
103+
104+
ocre_container_status_t status = ocre_container_runtime_create_container(ctx, &container_data,
105+
&container_IDs[i], NULL);
106+
// Check for CREATED status, not 0!
107+
if (status == CONTAINER_STATUS_CREATED) {
108+
printf("Container requested: %s (ID: %d)\n", entry->name, container_IDs[i]);
109+
core_sleep_ms(100);
110+
} else {
111+
printf("ERROR: Failed to request container %s: %d\n", entry->name, status);
112+
container_IDs[i] = -1;
113+
}
114+
}
78115

79-
void create_sample_container(char *file_name) {
80-
static char file_path[64];
81-
struct fs_file_t f;
82-
snprintf((char *)&file_path, 64, "/lfs/ocre/images/%s.bin", file_name);
83-
int res;
116+
// Give containers time to actually be created asynchronously
117+
printf("Waiting for containers to be created...\n");
118+
core_sleep_ms(500); // Wait for async creation to complete
84119

85-
fs_file_t_init(&f);
86-
res = fs_open(&f, file_path, FS_O_CREATE | FS_O_RDWR);
120+
// Run all containers
121+
for (int i = 0; i < WASM_BINARY_COUNT; i++) {
122+
if (container_IDs[i] >= 0) {
123+
const wasm_binary_entry_t *entry = wasm_get(i);
124+
printf("Starting container: %s\n", entry->name);
125+
ocre_container_runtime_run_container(container_IDs[i], NULL);
126+
}
127+
}
87128

88-
fs_write(&f, &wasm_binary, wasm_binary_len);
89-
fs_close(&f);
129+
printf("All containers started!\n");
90130
}
131+
#endif
91132

92-
int ocre_network_init() {
133+
int ocre_network_init() {
134+
struct net_if *iface = net_if_get_default();
135+
net_dhcpv4_start(iface);
93136

94-
struct net_if *iface = net_if_get_default();
95-
net_dhcpv4_start(iface);
137+
printf("Waiting for network to be ready...\n");
96138

97-
printf("Waiting for network to be ready...\n");
139+
int sleep_cnt = 0;
140+
while (!net_if_is_up(iface) && (sleep_cnt < 10)) {
141+
k_sleep(K_MSEC(200));
142+
sleep_cnt++;
143+
}
98144

99-
int sleep_cnt = 0;
100-
while (!net_if_is_up(iface) && (sleep_cnt < 10)) {
101-
k_sleep(K_MSEC(200));
102-
sleep_cnt++;
103-
}
145+
if (!net_if_is_up(iface)) {
146+
return -ENOTCONN;
147+
}
104148

105-
if (!net_if_is_up(iface)) {
106-
return -ENOTCONN;
107-
}
108-
109-
return 0;
110-
}
149+
return 0;
150+
}

src/shared/platform/zephyr/ocre_internal.cmake

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,21 @@ target_sources(app PRIVATE
119119

120120
add_dependencies(app generate_messages)
121121

122-
if(NOT "${OCRE_INPUT_FILE}" STREQUAL "")
123-
add_dependencies(app generate_ocre_file)
124-
# Add the WASM object file to the app sources
125-
target_sources(app PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/wasm_binary.o)
122+
message(STATUS "DEBUG: WASM_MANIFEST_ENTRIES = '${WASM_MANIFEST_ENTRIES}'")
123+
message(STATUS "DEBUG: CMAKE_CURRENT_BINARY_DIR = '${CMAKE_CURRENT_BINARY_DIR}'")
124+
125+
# Link WASM object files if manifest was generated
126+
if(DEFINED WASM_MANIFEST_ENTRIES AND WASM_MANIFEST_ENTRIES)
127+
message(STATUS "Linking WASM object files: ${WASM_MANIFEST_ENTRIES}")
128+
129+
foreach(WASM_NAME ${WASM_MANIFEST_ENTRIES})
130+
set(WASM_OBJ ${CMAKE_CURRENT_BINARY_DIR}/wasm_${WASM_NAME}.o)
131+
132+
# Don't check if EXISTS - files are generated at build time!
133+
target_sources(app PRIVATE ${WASM_OBJ})
134+
add_dependencies(app generate_${WASM_NAME}_wasm)
135+
message(STATUS " → Will link: ${WASM_OBJ}")
136+
endforeach()
137+
else()
138+
message(WARNING "No WASM_MANIFEST_ENTRIES defined!")
126139
endif()

tools/generate_wasm_manifest.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,25 @@ def generate_extern_declarations(wasm_names):
2121
return "\n".join(declarations)
2222

2323
def generate_manifest_entries(wasm_names):
24-
"""Generate manifest array entries"""
24+
"""Generate manifest array entries WITHOUT size field"""
2525
entries = []
2626
for name in wasm_names:
2727
safe_name = sanitize_name(name)
2828
entry = f""" {{
2929
.name = "{name}",
30-
.data = _binary_{safe_name}_wasm_start,
31-
.size = (size_t)(_binary_{safe_name}_wasm_end - _binary_{safe_name}_wasm_start)
30+
.data = _binary_{safe_name}_wasm_start
3231
}}"""
3332
entries.append(entry)
3433
return ",\n".join(entries)
3534

35+
def generate_size_calculations(wasm_names):
36+
"""Generate size calculation switch statement"""
37+
cases = []
38+
for i, name in enumerate(wasm_names):
39+
safe_name = sanitize_name(name)
40+
cases.append(f" if (index == {i}) return (size_t)(_binary_{safe_name}_wasm_end - _binary_{safe_name}_wasm_start);")
41+
return "\n".join(cases)
42+
3643
def main():
3744
parser = argparse.ArgumentParser(description='Generate WASM manifest header from template')
3845
parser.add_argument('names', nargs='+', help='WASM container names')
@@ -52,11 +59,13 @@ def main():
5259
# Generate content pieces
5360
extern_decls = generate_extern_declarations(args.names)
5461
manifest_entries = generate_manifest_entries(args.names)
62+
size_calculations = generate_size_calculations(args.names)
5563

5664
# Replace placeholders
5765
content = template.replace('@EXTERN_DECLARATIONS@', extern_decls)
5866
content = content.replace('@COUNT@', str(len(args.names)))
5967
content = content.replace('@MANIFEST_ENTRIES@', manifest_entries)
68+
content = content.replace('@SIZE_CALCULATIONS@', size_calculations)
6069

6170
# Write output
6271
output_path = Path(args.output)

0 commit comments

Comments
 (0)