diff --git a/CMakeLists.txt b/CMakeLists.txt index 269a731..b0d3702 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ endif() if(TARGET_PLATFORM_NAME STREQUAL "Linux") project(ocre LANGUAGES C ASM) elseif(TARGET_PLATFORM_NAME STREQUAL "Zephyr") - find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(ocre VERSION ${APP_VERSION_MAJOR}.${APP_VERSION_MINOR}.${APP_PATCHLEVEL}.${APP_VERSION_TWEAK} LANGUAGES C ASM) else() message(FATAL_ERROR "Unsupported TARGET_PLATFORM_NAME: ${TARGET_PLATFORM_NAME}") @@ -55,22 +55,14 @@ add_custom_command( ) add_custom_target(generate_messages DEPENDS ${MSG_GENERATED_FILE}) -if(NOT "${OCRE_INPUT_FILE}" STREQUAL "") - message("Using input file: ${OCRE_INPUT_FILE}") - add_custom_command( - OUTPUT ${CMAKE_CURRENT_LIST_DIR}/src/ocre/ocre_input_file.g - COMMAND xxd -n wasm_binary -i ${OCRE_INPUT_FILE} > ${CMAKE_CURRENT_LIST_DIR}/src/ocre/ocre_input_file.g - DEPENDS ${OCRE_INPUT_FILE} - COMMENT "Generating C header from ${OCRE_INPUT_FILE}" - ) - - add_definitions(-DHAS_GENERATED_INPUT) - - add_custom_target(generate_ocre_file DEPENDS ${CMAKE_CURRENT_LIST_DIR}/src/ocre/ocre_input_file.g) -endif() +# Include and process WASM binaries +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) +include(embed_wasm_binary) +process_wasm_binaries() if(TARGET_PLATFORM_NAME STREQUAL "Linux") include(${CMAKE_CURRENT_LIST_DIR}/src/shared/platform/posix/ocre_internal.cmake) elseif(TARGET_PLATFORM_NAME STREQUAL "Zephyr") + include_directories(${CMAKE_CURRENT_BINARY_DIR}) include(${CMAKE_CURRENT_LIST_DIR}/src/shared/platform/zephyr/ocre_internal.cmake) endif() diff --git a/boards/native_sim.overlay b/boards/native_sim.overlay index 8bf90af..7b860b9 100644 --- a/boards/native_sim.overlay +++ b/boards/native_sim.overlay @@ -35,5 +35,10 @@ label = "storage"; reg = <0x100000 0x00004000>; }; + + wasm_binary_partition: partition@f0000 { + label = "wasm-binary"; + reg = <0x000f0000 DT_SIZE_K(64)>; + }; }; }; diff --git a/build.sh b/build.sh index ac1da7b..143787e 100755 --- a/build.sh +++ b/build.sh @@ -4,12 +4,14 @@ show_help() { echo "Usage: $0 -t [-r] [-f [file2 ...]]" echo " -t (Required) Specify the target. z for Zephyr and l for Linux" - echo " -r (Optional) Specify whether run after the build" - echo " -f (Optional) Specify one or more input files" + echo " -r (Optional) Run after build" + echo " -f (Optional) Specify WASM file(s) to embed" + echo " Example: -f app.wasm" + echo " Example: -f blinky.wasm sensor.wasm control.wasm" echo " -b (Optional, Zephyr only) Select board:" echo " uw -> b_u585i_iot02a + W5500" echo " ue -> b_u585i_iot02a + ENC28J60" - echo " note: when no board is selected, native_sim is the default target for Zephyr" + echo " (default: native_sim)" echo " -h Display help" exit 0 } @@ -99,14 +101,27 @@ if [[ "$TARGET" == "z" ]]; then esac if [[ ${#INPUT_FILES[@]} -gt 0 ]]; then - echo "Input files provided: ${INPUT_FILES[*]}" - rm flash.bin + echo "Input WASM files provided: ${INPUT_FILES[*]}" + + WASM_LIST=$(IFS=';'; echo "${INPUT_FILES[*]}") + + for WASM_FILE in "${INPUT_FILES[@]}"; do + WASM_NAME=$(basename "$WASM_FILE" .wasm) + echo " → Will embed: ${WASM_NAME} <- ${WASM_FILE}" + done + + rm -f flash.bin west build -p -b $ZEPHYR_BOARD ./application -d build -- \ - -DMODULE_EXT_ROOT=`pwd`/application -DOCRE_INPUT_FILE="${INPUT_FILES[0]}" -DTARGET_PLATFORM_NAME=Zephyr $CONF_EXTRA || exit 1 + -DMODULE_EXT_ROOT=`pwd`/application \ + -DOCRE_WASM_FILES="$WASM_LIST" \ + -DTARGET_PLATFORM_NAME=Zephyr \ + $CONF_EXTRA || exit 1 else - rm flash.bin + rm -f flash.bin west build -p -b $ZEPHYR_BOARD ./application -d build -- \ - -DMODULE_EXT_ROOT=`pwd`/application -DTARGET_PLATFORM_NAME=Zephyr $CONF_EXTRA || exit 1 + -DMODULE_EXT_ROOT=`pwd`/application \ + -DTARGET_PLATFORM_NAME=Zephyr \ + $CONF_EXTRA || exit 1 fi elif [[ "$TARGET" == "l" ]]; then echo "Target is: Linux" diff --git a/cmake/embed_wasm_binary.cmake b/cmake/embed_wasm_binary.cmake new file mode 100644 index 0000000..27f1e2e --- /dev/null +++ b/cmake/embed_wasm_binary.cmake @@ -0,0 +1,198 @@ +# embed_wasm_binary.cmake +# Embeds a WASM binary file into the application as a linkable object + +# Helper function to detect the correct objcopy format based on architecture +function(detect_objcopy_format OUT_FORMAT OUT_ARCH_NAME) + set(FORMAT "") + set(ARCH "unknown") + + if(CONFIG_ARM64 OR CONFIG_AARCH64) + set(FORMAT "elf64-littleaarch64") + set(ARCH "ARM64") + elseif(CONFIG_ARM) + set(FORMAT "elf32-littlearm") + set(ARCH "ARM") + elseif(CONFIG_RISCV) + if(CONFIG_64BIT) + set(FORMAT "elf64-littleriscv") + set(ARCH "RISC-V 64") + else() + set(FORMAT "elf32-littleriscv") + set(ARCH "RISC-V 32") + endif() + elseif(CONFIG_X86_64) + set(FORMAT "elf64-x86-64") + set(ARCH "x86-64") + elseif(CONFIG_X86 OR CONFIG_ARCH_POSIX) + # POSIX/native boards are typically x86 32-bit + # Check if 64-bit is explicitly set + if(CONFIG_64BIT OR CMAKE_SIZEOF_VOID_P EQUAL 8) + set(FORMAT "elf64-x86-64") + set(ARCH "x86-64") + else() + set(FORMAT "elf32-i386") + set(ARCH "x86") + endif() + elseif(CONFIG_XTENSA) + set(FORMAT "elf32-xtensa-le") + set(ARCH "Xtensa") + elseif(CONFIG_ARC) + set(FORMAT "elf32-littlearc") + set(ARCH "ARC") + elseif(CONFIG_NIOS2) + set(FORMAT "elf32-littlenios2") + set(ARCH "NIOS2") + else() + # Fallback: try to use default + set(FORMAT "default") + set(ARCH "unknown") + message(WARNING "Could not detect architecture for objcopy, using 'default' format") + endif() + + # Return values to caller + set(${OUT_FORMAT} ${FORMAT} PARENT_SCOPE) + set(${OUT_ARCH_NAME} ${ARCH} PARENT_SCOPE) +endfunction() + +# Main function to embed WASM binary +function(embed_wasm_binary) + set(options "") + set(oneValueArgs INPUT_FILE OUTPUT_NAME TARGET_NAME SYMBOL_NAME) + set(multiValueArgs "") + cmake_parse_arguments(WASM "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT WASM_INPUT_FILE) + message(FATAL_ERROR "embed_wasm_binary: INPUT_FILE is required") + endif() + + if(NOT WASM_OUTPUT_NAME) + set(WASM_OUTPUT_NAME "app.wasm") + endif() + + if(NOT WASM_SYMBOL_NAME) + get_filename_component(WASM_SYMBOL_NAME "${WASM_OUTPUT_NAME}" NAME_WE) + endif() + + message(STATUS "Embedding WASM binary: ${WASM_INPUT_FILE}") + + # Stage the WASM file with a fixed name for consistent symbol names + set(WASM_STAGED_FILE ${CMAKE_CURRENT_BINARY_DIR}/${WASM_OUTPUT_NAME}) + + add_custom_command( + OUTPUT ${WASM_STAGED_FILE} + COMMAND ${CMAKE_COMMAND} -E copy ${WASM_INPUT_FILE} ${WASM_STAGED_FILE} + DEPENDS ${WASM_INPUT_FILE} + COMMENT "Staging WASM file: ${WASM_INPUT_FILE}" + ) + + # Detect the correct objcopy format for the target architecture + detect_objcopy_format(OBJCOPY_FORMAT ARCH_NAME) + + message(STATUS "Detected architecture: ${ARCH_NAME}, using objcopy format: ${OBJCOPY_FORMAT}") + + # Convert WASM to object file (use symbol name for unique files) + set(WASM_OBJECT_FILE ${CMAKE_CURRENT_BINARY_DIR}/wasm_${WASM_SYMBOL_NAME}.o) + + add_custom_command( + OUTPUT ${WASM_OBJECT_FILE} + COMMAND ${CMAKE_COMMAND} -E chdir ${CMAKE_CURRENT_BINARY_DIR} + objcopy + -I binary + -O ${OBJCOPY_FORMAT} + --rename-section .data=.rodata.wasm.${WASM_SYMBOL_NAME},alloc,load,readonly,data,contents + ${WASM_OUTPUT_NAME} + wasm_${WASM_SYMBOL_NAME}.o + DEPENDS ${WASM_STAGED_FILE} + COMMENT "Converting to object file (${OBJCOPY_FORMAT} for ${ARCH_NAME})" + ) + + # Create a custom target + add_custom_target(${WASM_TARGET_NAME} DEPENDS ${WASM_OBJECT_FILE}) + + # Export the object file path to parent scope with symbol name + set(WASM_BINARY_OBJECT_${WASM_SYMBOL_NAME} ${WASM_OBJECT_FILE} PARENT_SCOPE) + + message(STATUS "WASM binary will be embedded as: ${WASM_OBJECT_FILE}") +endfunction() + +# Generate a manifest header file using template and Python script +function(generate_wasm_manifest WASM_NAMES_LIST) + if(NOT WASM_NAMES_LIST) + message(WARNING "No WASM names provided for manifest generation") + return() + endif() + + set(TEMPLATE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/src/ocre/wasm_manifest.h.in) + set(MANIFEST_FILE ${CMAKE_CURRENT_BINARY_DIR}/wasm_manifest.h) + + # Find Python executable (reuse from earlier in CMakeLists) + if(NOT DEFINED PYTHON_EXECUTABLE) + find_package(Python3 QUIET REQUIRED Interpreter) + set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE}) + endif() + + # Generate manifest using Python script with template + execute_process( + COMMAND ${PYTHON_EXECUTABLE} + ${CMAKE_CURRENT_SOURCE_DIR}/tools/generate_wasm_manifest.py + ${WASM_NAMES_LIST} + -t ${TEMPLATE_FILE} + -o ${MANIFEST_FILE} + RESULT_VARIABLE RESULT + OUTPUT_VARIABLE OUTPUT + ERROR_VARIABLE ERROR + ) + + if(NOT RESULT EQUAL 0) + message(FATAL_ERROR "Failed to generate WASM manifest: ${ERROR}") + endif() + + message(STATUS "${OUTPUT}") +endfunction() + +# High-level function to process WASM files from build script +function(process_wasm_binaries) + if(NOT DEFINED OCRE_WASM_FILES OR "${OCRE_WASM_FILES}" STREQUAL "") + message(STATUS "No WASM files specified") + return() + endif() + + message(STATUS "Processing WASM files: ${OCRE_WASM_FILES}") + + set(WASM_NAMES "") + + foreach(WASM_PATH ${OCRE_WASM_FILES}) + if(EXISTS "${WASM_PATH}") + get_filename_component(WASM_NAME "${WASM_PATH}" NAME_WE) + message(STATUS " → Embedding: ${WASM_NAME} from ${WASM_PATH}") + + embed_wasm_binary( + INPUT_FILE "${WASM_PATH}" + OUTPUT_NAME "${WASM_NAME}.wasm" + TARGET_NAME "generate_${WASM_NAME}_wasm" + SYMBOL_NAME "${WASM_NAME}" + ) + + list(APPEND WASM_NAMES ${WASM_NAME}) + else() + message(WARNING "WASM file not found: ${WASM_PATH}") + endif() + endforeach() + + if(WASM_NAMES) + # Export to parent scope and cache for use in other cmake files + set(WASM_MANIFEST_ENTRIES ${WASM_NAMES} PARENT_SCOPE) + set(WASM_MANIFEST_ENTRIES ${WASM_NAMES} CACHE INTERNAL "List of embedded WASM names") + + list(LENGTH WASM_NAMES WASM_COUNT) + message(STATUS "Successfully configured ${WASM_COUNT} WASM file(s): ${WASM_NAMES}") + + # Generate the manifest header + generate_wasm_manifest("${WASM_NAMES}") + + add_definitions(-DHAS_GENERATED_INPUT) + add_definitions(-DHAS_WASM_MANIFEST) + else() + message(WARNING "No valid WASM files were processed") + endif() +endfunction() diff --git a/src/ocre/ocre_gpio/ocre_gpio.c b/src/ocre/ocre_gpio/ocre_gpio.c index 6300404..915234f 100644 --- a/src/ocre/ocre_gpio/ocre_gpio.c +++ b/src/ocre/ocre_gpio/ocre_gpio.c @@ -104,6 +104,10 @@ int ocre_gpio_init(void) { #elif defined(CONFIG_BOARD_W5500_EVB_PICO2) INIT_GPIO_PORT_NAMED(0, DT_NODELABEL(gpio0), "GPIO0"); +#elif defined(CONFIG_BOARD_NRF5340DK_NRF5340_CPUAPP) + INIT_GPIO_PORT_NAMED(0, DT_NODELABEL(gpio0), "GPIO0"); + INIT_GPIO_PORT_NAMED(1, DT_NODELABEL(gpio1), "GPIO1"); + #else // Generic fallback #if DT_NODE_EXISTS(DT_NODELABEL(gpio0)) @@ -384,7 +388,7 @@ static void gpio_callback_handler(const struct device *port, struct gpio_callbac } //======================================================================================================================================================================================================================================================================================================== -// By Name +// By Name //======================================================================================================================================================================================================================================================================================================== static int find_port_index(const struct device *port) { if (!port) { @@ -662,12 +666,12 @@ int ocre_gpio_wasm_register_callback_by_name(wasm_exec_env_t exec_env, const cha int global_pin = port_idx * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; LOG_INF("Registering callback by name: %s, global_pin=%d", name, global_pin); - + if (global_pin >= CONFIG_OCRE_GPIO_MAX_PINS) { LOG_ERR("Global pin %d exceeds max %d", global_pin, CONFIG_OCRE_GPIO_MAX_PINS); return -EINVAL; } - + return ocre_gpio_register_callback(global_pin); } @@ -686,6 +690,6 @@ int ocre_gpio_wasm_unregister_callback_by_name(wasm_exec_env_t exec_env, const c int global_pin = port_idx * CONFIG_OCRE_GPIO_PINS_PER_PORT + pin; LOG_INF("Unregistering callback by name: %s, global_pin=%d", name, global_pin); - + return ocre_gpio_unregister_callback(global_pin); } diff --git a/src/ocre/ocre_input_file.h b/src/ocre/ocre_input_file.h index 74a3905..60fc854 100644 --- a/src/ocre/ocre_input_file.h +++ b/src/ocre/ocre_input_file.h @@ -1,337 +1,15 @@ -/** - * @copyright Copyright © contributors to Project Ocre, - * which has been established as Project Ocre a Series of LF Projects, LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - #ifndef OCRE_INPUT_FILE_H #define OCRE_INPUT_FILE_H -// Sample WASM binary data -static unsigned char wasm_binary[] = { - 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x35, 0x09, 0x60, - 0x03, 0x7f, 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x03, 0x7f, 0x7e, 0x7f, 0x01, - 0x7e, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f, - 0x60, 0x04, 0x7f, 0x7e, 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x04, 0x7f, 0x7f, - 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x01, 0x7f, 0x00, 0x60, 0x00, 0x00, 0x60, - 0x00, 0x01, 0x7f, 0x02, 0xb0, 0x01, 0x05, 0x16, 0x77, 0x61, 0x73, 0x69, - 0x5f, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x70, 0x72, - 0x65, 0x76, 0x69, 0x65, 0x77, 0x31, 0x08, 0x66, 0x64, 0x5f, 0x63, 0x6c, - 0x6f, 0x73, 0x65, 0x00, 0x02, 0x16, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x73, - 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x76, - 0x69, 0x65, 0x77, 0x31, 0x0d, 0x66, 0x64, 0x5f, 0x66, 0x64, 0x73, 0x74, - 0x61, 0x74, 0x5f, 0x67, 0x65, 0x74, 0x00, 0x03, 0x16, 0x77, 0x61, 0x73, - 0x69, 0x5f, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x70, - 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x31, 0x07, 0x66, 0x64, 0x5f, 0x73, - 0x65, 0x65, 0x6b, 0x00, 0x04, 0x16, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x73, - 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x76, - 0x69, 0x65, 0x77, 0x31, 0x08, 0x66, 0x64, 0x5f, 0x77, 0x72, 0x69, 0x74, - 0x65, 0x00, 0x05, 0x16, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x73, 0x6e, 0x61, - 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x76, 0x69, 0x65, - 0x77, 0x31, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x5f, 0x65, 0x78, 0x69, 0x74, - 0x00, 0x06, 0x03, 0x1d, 0x1c, 0x07, 0x07, 0x08, 0x02, 0x03, 0x04, 0x05, - 0x06, 0x07, 0x07, 0x08, 0x07, 0x02, 0x05, 0x03, 0x03, 0x02, 0x07, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x01, 0x01, 0x00, 0x02, 0x04, 0x05, 0x01, - 0x70, 0x01, 0x05, 0x05, 0x05, 0x03, 0x01, 0x00, 0x02, 0x06, 0x0d, 0x02, - 0x7f, 0x01, 0x41, 0xc0, 0x91, 0x04, 0x0b, 0x7f, 0x00, 0x41, 0x00, 0x0b, - 0x07, 0x1a, 0x03, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00, - 0x06, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x00, 0x06, 0x04, 0x6d, 0x61, - 0x69, 0x6e, 0x00, 0x07, 0x09, 0x0a, 0x01, 0x00, 0x41, 0x01, 0x0b, 0x04, - 0x1a, 0x18, 0x1c, 0x1e, 0x0a, 0x93, 0x1a, 0x1c, 0x02, 0x00, 0x0b, 0x51, - 0x01, 0x01, 0x7f, 0x02, 0x40, 0x02, 0x40, 0x23, 0x81, 0x80, 0x80, 0x80, - 0x00, 0x41, 0xa0, 0x89, 0x80, 0x80, 0x00, 0x6a, 0x28, 0x02, 0x00, 0x0d, - 0x00, 0x23, 0x81, 0x80, 0x80, 0x80, 0x00, 0x41, 0xa0, 0x89, 0x80, 0x80, - 0x00, 0x6a, 0x41, 0x01, 0x36, 0x02, 0x00, 0x10, 0x85, 0x80, 0x80, 0x80, - 0x00, 0x10, 0x87, 0x80, 0x80, 0x80, 0x00, 0x21, 0x00, 0x10, 0x8e, 0x80, - 0x80, 0x80, 0x00, 0x20, 0x00, 0x0d, 0x01, 0x0f, 0x0b, 0x00, 0x0b, 0x20, - 0x00, 0x10, 0x8c, 0x80, 0x80, 0x80, 0x00, 0x00, 0x0b, 0x11, 0x00, 0x41, - 0x80, 0x88, 0x80, 0x80, 0x00, 0x10, 0x95, 0x80, 0x80, 0x80, 0x00, 0x1a, - 0x41, 0x00, 0x0b, 0x0f, 0x00, 0x20, 0x00, 0x10, 0x80, 0x80, 0x80, 0x80, - 0x00, 0x41, 0xff, 0xff, 0x03, 0x71, 0x0b, 0x11, 0x00, 0x20, 0x00, 0x20, - 0x01, 0x10, 0x81, 0x80, 0x80, 0x80, 0x00, 0x41, 0xff, 0xff, 0x03, 0x71, - 0x0b, 0x15, 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x20, 0x03, 0x10, - 0x82, 0x80, 0x80, 0x80, 0x00, 0x41, 0xff, 0xff, 0x03, 0x71, 0x0b, 0x15, - 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x20, 0x03, 0x10, 0x83, 0x80, - 0x80, 0x80, 0x00, 0x41, 0xff, 0xff, 0x03, 0x71, 0x0b, 0x0b, 0x00, 0x20, - 0x00, 0x10, 0x84, 0x80, 0x80, 0x80, 0x00, 0x00, 0x0b, 0x02, 0x00, 0x0b, - 0x0e, 0x00, 0x10, 0x8d, 0x80, 0x80, 0x80, 0x00, 0x10, 0x90, 0x80, 0x80, - 0x80, 0x00, 0x0b, 0x08, 0x00, 0x41, 0xa4, 0x89, 0x80, 0x80, 0x00, 0x0b, - 0xa3, 0x03, 0x01, 0x03, 0x7f, 0x02, 0x40, 0x10, 0x8f, 0x80, 0x80, 0x80, - 0x00, 0x28, 0x02, 0x00, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x03, 0x40, 0x02, - 0x40, 0x20, 0x00, 0x28, 0x02, 0x14, 0x20, 0x00, 0x28, 0x02, 0x18, 0x46, - 0x0d, 0x00, 0x20, 0x00, 0x41, 0x00, 0x41, 0x00, 0x20, 0x00, 0x28, 0x02, - 0x20, 0x11, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, - 0x1a, 0x0b, 0x02, 0x40, 0x20, 0x00, 0x28, 0x02, 0x04, 0x22, 0x01, 0x20, - 0x00, 0x28, 0x02, 0x08, 0x22, 0x02, 0x46, 0x0d, 0x00, 0x20, 0x00, 0x20, - 0x01, 0x20, 0x02, 0x6b, 0xac, 0x41, 0x01, 0x20, 0x00, 0x28, 0x02, 0x24, - 0x11, 0x81, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x1a, - 0x0b, 0x20, 0x00, 0x28, 0x02, 0x34, 0x22, 0x00, 0x0d, 0x00, 0x0b, 0x0b, - 0x02, 0x40, 0x41, 0x00, 0x28, 0x02, 0xa8, 0x89, 0x80, 0x80, 0x00, 0x22, - 0x00, 0x45, 0x0d, 0x00, 0x02, 0x40, 0x20, 0x00, 0x28, 0x02, 0x14, 0x20, - 0x00, 0x28, 0x02, 0x18, 0x46, 0x0d, 0x00, 0x20, 0x00, 0x41, 0x00, 0x41, - 0x00, 0x20, 0x00, 0x28, 0x02, 0x20, 0x11, 0x80, 0x80, 0x80, 0x80, 0x00, - 0x80, 0x80, 0x80, 0x80, 0x00, 0x1a, 0x0b, 0x20, 0x00, 0x28, 0x02, 0x04, - 0x22, 0x01, 0x20, 0x00, 0x28, 0x02, 0x08, 0x22, 0x02, 0x46, 0x0d, 0x00, - 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x6b, 0xac, 0x41, 0x01, 0x20, 0x00, - 0x28, 0x02, 0x24, 0x11, 0x81, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, - 0x80, 0x00, 0x1a, 0x0b, 0x02, 0x40, 0x41, 0x00, 0x28, 0x02, 0x90, 0x89, - 0x80, 0x80, 0x00, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x02, 0x40, 0x20, 0x00, - 0x28, 0x02, 0x14, 0x20, 0x00, 0x28, 0x02, 0x18, 0x46, 0x0d, 0x00, 0x20, - 0x00, 0x41, 0x00, 0x41, 0x00, 0x20, 0x00, 0x28, 0x02, 0x20, 0x11, 0x80, - 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x1a, 0x0b, 0x20, - 0x00, 0x28, 0x02, 0x04, 0x22, 0x01, 0x20, 0x00, 0x28, 0x02, 0x08, 0x22, - 0x02, 0x46, 0x0d, 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x6b, 0xac, - 0x41, 0x01, 0x20, 0x00, 0x28, 0x02, 0x24, 0x11, 0x81, 0x80, 0x80, 0x80, - 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x1a, 0x0b, 0x02, 0x40, 0x41, 0x00, - 0x28, 0x02, 0xa8, 0x89, 0x80, 0x80, 0x00, 0x22, 0x00, 0x45, 0x0d, 0x00, - 0x02, 0x40, 0x20, 0x00, 0x28, 0x02, 0x14, 0x20, 0x00, 0x28, 0x02, 0x18, - 0x46, 0x0d, 0x00, 0x20, 0x00, 0x41, 0x00, 0x41, 0x00, 0x20, 0x00, 0x28, - 0x02, 0x20, 0x11, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, - 0x00, 0x1a, 0x0b, 0x20, 0x00, 0x28, 0x02, 0x04, 0x22, 0x01, 0x20, 0x00, - 0x28, 0x02, 0x08, 0x22, 0x02, 0x46, 0x0d, 0x00, 0x20, 0x00, 0x20, 0x01, - 0x20, 0x02, 0x6b, 0xac, 0x41, 0x01, 0x20, 0x00, 0x28, 0x02, 0x24, 0x11, - 0x81, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x1a, 0x0b, - 0x0b, 0x5c, 0x01, 0x01, 0x7f, 0x20, 0x00, 0x20, 0x00, 0x28, 0x02, 0x3c, - 0x22, 0x01, 0x41, 0x7f, 0x6a, 0x20, 0x01, 0x72, 0x36, 0x02, 0x3c, 0x02, - 0x40, 0x20, 0x00, 0x28, 0x02, 0x00, 0x22, 0x01, 0x41, 0x08, 0x71, 0x45, - 0x0d, 0x00, 0x20, 0x00, 0x20, 0x01, 0x41, 0x20, 0x72, 0x36, 0x02, 0x00, - 0x41, 0x7f, 0x0f, 0x0b, 0x20, 0x00, 0x42, 0x00, 0x37, 0x02, 0x04, 0x20, - 0x00, 0x20, 0x00, 0x28, 0x02, 0x28, 0x22, 0x01, 0x36, 0x02, 0x18, 0x20, - 0x00, 0x20, 0x01, 0x36, 0x02, 0x14, 0x20, 0x00, 0x20, 0x01, 0x20, 0x00, - 0x28, 0x02, 0x2c, 0x6a, 0x36, 0x02, 0x10, 0x41, 0x00, 0x0b, 0xa8, 0x02, - 0x01, 0x05, 0x7f, 0x20, 0x02, 0x20, 0x01, 0x6c, 0x21, 0x04, 0x02, 0x40, - 0x02, 0x40, 0x20, 0x03, 0x28, 0x02, 0x10, 0x22, 0x05, 0x0d, 0x00, 0x41, - 0x00, 0x21, 0x06, 0x20, 0x03, 0x10, 0x91, 0x80, 0x80, 0x80, 0x00, 0x0d, - 0x01, 0x20, 0x03, 0x28, 0x02, 0x10, 0x21, 0x05, 0x0b, 0x02, 0x40, 0x20, - 0x05, 0x20, 0x03, 0x28, 0x02, 0x14, 0x22, 0x07, 0x6b, 0x20, 0x04, 0x4f, - 0x0d, 0x00, 0x20, 0x03, 0x20, 0x00, 0x20, 0x04, 0x20, 0x03, 0x28, 0x02, - 0x20, 0x11, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, - 0x21, 0x06, 0x0c, 0x01, 0x0b, 0x41, 0x00, 0x21, 0x08, 0x02, 0x40, 0x02, - 0x40, 0x20, 0x04, 0x0d, 0x00, 0x20, 0x04, 0x21, 0x05, 0x0c, 0x01, 0x0b, - 0x41, 0x00, 0x21, 0x05, 0x02, 0x40, 0x20, 0x03, 0x28, 0x02, 0x40, 0x41, - 0x00, 0x4e, 0x0d, 0x00, 0x20, 0x04, 0x21, 0x05, 0x0c, 0x01, 0x0b, 0x20, - 0x00, 0x20, 0x04, 0x6a, 0x21, 0x06, 0x02, 0x40, 0x03, 0x40, 0x20, 0x06, - 0x20, 0x05, 0x6a, 0x41, 0x7f, 0x6a, 0x2d, 0x00, 0x00, 0x41, 0x0a, 0x46, - 0x0d, 0x01, 0x20, 0x04, 0x20, 0x05, 0x41, 0x7f, 0x6a, 0x22, 0x05, 0x6a, - 0x0d, 0x00, 0x0b, 0x41, 0x00, 0x21, 0x08, 0x20, 0x04, 0x21, 0x05, 0x0c, - 0x01, 0x0b, 0x20, 0x03, 0x20, 0x00, 0x20, 0x04, 0x20, 0x05, 0x6a, 0x22, - 0x08, 0x20, 0x03, 0x28, 0x02, 0x20, 0x11, 0x80, 0x80, 0x80, 0x80, 0x00, - 0x80, 0x80, 0x80, 0x80, 0x00, 0x22, 0x06, 0x20, 0x08, 0x49, 0x0d, 0x01, - 0x20, 0x08, 0x20, 0x00, 0x6a, 0x21, 0x00, 0x41, 0x00, 0x20, 0x05, 0x6b, - 0x21, 0x05, 0x20, 0x03, 0x28, 0x02, 0x14, 0x21, 0x07, 0x0b, 0x20, 0x07, - 0x20, 0x00, 0x20, 0x05, 0x10, 0x9f, 0x80, 0x80, 0x80, 0x00, 0x1a, 0x20, - 0x03, 0x20, 0x03, 0x28, 0x02, 0x14, 0x20, 0x05, 0x6a, 0x36, 0x02, 0x14, - 0x20, 0x08, 0x20, 0x05, 0x6a, 0x21, 0x06, 0x0b, 0x02, 0x40, 0x20, 0x06, - 0x20, 0x04, 0x47, 0x0d, 0x00, 0x20, 0x02, 0x41, 0x00, 0x20, 0x01, 0x1b, - 0x0f, 0x0b, 0x20, 0x06, 0x20, 0x01, 0x6e, 0x0b, 0x24, 0x01, 0x01, 0x7f, - 0x20, 0x00, 0x10, 0xa0, 0x80, 0x80, 0x80, 0x00, 0x21, 0x02, 0x41, 0x7f, - 0x41, 0x00, 0x20, 0x02, 0x20, 0x00, 0x41, 0x01, 0x20, 0x02, 0x20, 0x01, - 0x10, 0x92, 0x80, 0x80, 0x80, 0x00, 0x47, 0x1b, 0x0b, 0xb3, 0x01, 0x01, - 0x03, 0x7f, 0x23, 0x80, 0x80, 0x80, 0x80, 0x00, 0x41, 0x10, 0x6b, 0x22, - 0x02, 0x24, 0x80, 0x80, 0x80, 0x80, 0x00, 0x20, 0x02, 0x20, 0x01, 0x3a, - 0x00, 0x0f, 0x02, 0x40, 0x02, 0x40, 0x20, 0x00, 0x28, 0x02, 0x10, 0x22, - 0x03, 0x0d, 0x00, 0x02, 0x40, 0x20, 0x00, 0x10, 0x91, 0x80, 0x80, 0x80, - 0x00, 0x45, 0x0d, 0x00, 0x41, 0x7f, 0x21, 0x03, 0x0c, 0x02, 0x0b, 0x20, - 0x00, 0x28, 0x02, 0x10, 0x21, 0x03, 0x0b, 0x02, 0x40, 0x20, 0x00, 0x28, - 0x02, 0x14, 0x22, 0x04, 0x20, 0x03, 0x46, 0x0d, 0x00, 0x20, 0x00, 0x28, - 0x02, 0x40, 0x20, 0x01, 0x41, 0xff, 0x01, 0x71, 0x22, 0x03, 0x46, 0x0d, - 0x00, 0x20, 0x00, 0x20, 0x04, 0x41, 0x01, 0x6a, 0x36, 0x02, 0x14, 0x20, - 0x04, 0x20, 0x01, 0x3a, 0x00, 0x00, 0x0c, 0x01, 0x0b, 0x02, 0x40, 0x20, - 0x00, 0x20, 0x02, 0x41, 0x0f, 0x6a, 0x41, 0x01, 0x20, 0x00, 0x28, 0x02, - 0x20, 0x11, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, - 0x41, 0x01, 0x46, 0x0d, 0x00, 0x41, 0x7f, 0x21, 0x03, 0x0c, 0x01, 0x0b, - 0x20, 0x02, 0x2d, 0x00, 0x0f, 0x21, 0x03, 0x0b, 0x20, 0x02, 0x41, 0x10, - 0x6a, 0x24, 0x80, 0x80, 0x80, 0x80, 0x00, 0x20, 0x03, 0x0b, 0x6c, 0x00, - 0x02, 0x40, 0x20, 0x00, 0x41, 0xa0, 0x88, 0x80, 0x80, 0x00, 0x10, 0x93, - 0x80, 0x80, 0x80, 0x00, 0x41, 0x00, 0x4e, 0x0d, 0x00, 0x41, 0x7f, 0x0f, - 0x0b, 0x02, 0x40, 0x41, 0x00, 0x28, 0x02, 0xe0, 0x88, 0x80, 0x80, 0x00, - 0x41, 0x0a, 0x46, 0x0d, 0x00, 0x41, 0x00, 0x28, 0x02, 0xb4, 0x88, 0x80, - 0x80, 0x00, 0x22, 0x00, 0x41, 0x00, 0x28, 0x02, 0xb0, 0x88, 0x80, 0x80, - 0x00, 0x46, 0x0d, 0x00, 0x41, 0x00, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x36, - 0x02, 0xb4, 0x88, 0x80, 0x80, 0x00, 0x20, 0x00, 0x41, 0x0a, 0x3a, 0x00, - 0x00, 0x41, 0x00, 0x0f, 0x0b, 0x41, 0xa0, 0x88, 0x80, 0x80, 0x00, 0x41, - 0x0a, 0x10, 0x94, 0x80, 0x80, 0x80, 0x00, 0x41, 0x1f, 0x75, 0x0b, 0x02, - 0x00, 0x0b, 0x27, 0x00, 0x10, 0x96, 0x80, 0x80, 0x80, 0x00, 0x02, 0x40, - 0x20, 0x00, 0x10, 0x88, 0x80, 0x80, 0x80, 0x00, 0x22, 0x00, 0x0d, 0x00, - 0x41, 0x00, 0x0f, 0x0b, 0x41, 0x00, 0x20, 0x00, 0x36, 0x02, 0xac, 0x89, - 0x80, 0x80, 0x00, 0x41, 0x7f, 0x0b, 0x0d, 0x00, 0x20, 0x00, 0x28, 0x02, - 0x38, 0x10, 0x97, 0x80, 0x80, 0x80, 0x00, 0x0b, 0x71, 0x01, 0x02, 0x7f, - 0x23, 0x80, 0x80, 0x80, 0x80, 0x00, 0x41, 0x10, 0x6b, 0x22, 0x03, 0x24, - 0x80, 0x80, 0x80, 0x80, 0x00, 0x41, 0x7f, 0x21, 0x04, 0x02, 0x40, 0x02, - 0x40, 0x20, 0x02, 0x41, 0x7f, 0x4a, 0x0d, 0x00, 0x41, 0x00, 0x41, 0x1c, - 0x36, 0x02, 0xac, 0x89, 0x80, 0x80, 0x00, 0x0c, 0x01, 0x0b, 0x02, 0x40, - 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x20, 0x03, 0x41, 0x0c, 0x6a, 0x10, - 0x8b, 0x80, 0x80, 0x80, 0x00, 0x22, 0x02, 0x45, 0x0d, 0x00, 0x41, 0x00, - 0x20, 0x02, 0x36, 0x02, 0xac, 0x89, 0x80, 0x80, 0x00, 0x41, 0x7f, 0x21, - 0x04, 0x0c, 0x01, 0x0b, 0x20, 0x03, 0x28, 0x02, 0x0c, 0x21, 0x04, 0x0b, - 0x20, 0x03, 0x41, 0x10, 0x6a, 0x24, 0x80, 0x80, 0x80, 0x80, 0x00, 0x20, - 0x04, 0x0b, 0xbb, 0x02, 0x01, 0x07, 0x7f, 0x23, 0x80, 0x80, 0x80, 0x80, - 0x00, 0x41, 0x10, 0x6b, 0x22, 0x03, 0x24, 0x80, 0x80, 0x80, 0x80, 0x00, - 0x20, 0x03, 0x20, 0x02, 0x36, 0x02, 0x0c, 0x20, 0x03, 0x20, 0x01, 0x36, - 0x02, 0x08, 0x20, 0x03, 0x20, 0x00, 0x28, 0x02, 0x18, 0x22, 0x01, 0x36, - 0x02, 0x00, 0x20, 0x03, 0x20, 0x00, 0x28, 0x02, 0x14, 0x20, 0x01, 0x6b, - 0x22, 0x04, 0x36, 0x02, 0x04, 0x41, 0x02, 0x21, 0x05, 0x02, 0x40, 0x02, - 0x40, 0x20, 0x00, 0x28, 0x02, 0x38, 0x20, 0x03, 0x41, 0x02, 0x10, 0x99, - 0x80, 0x80, 0x80, 0x00, 0x22, 0x01, 0x20, 0x04, 0x20, 0x02, 0x6a, 0x22, - 0x06, 0x46, 0x0d, 0x00, 0x20, 0x03, 0x21, 0x04, 0x03, 0x40, 0x02, 0x40, - 0x20, 0x01, 0x41, 0x7f, 0x4a, 0x0d, 0x00, 0x41, 0x00, 0x21, 0x01, 0x20, - 0x00, 0x41, 0x00, 0x36, 0x02, 0x18, 0x20, 0x00, 0x42, 0x00, 0x37, 0x03, - 0x10, 0x20, 0x00, 0x20, 0x00, 0x28, 0x02, 0x00, 0x41, 0x20, 0x72, 0x36, - 0x02, 0x00, 0x20, 0x05, 0x41, 0x02, 0x46, 0x0d, 0x03, 0x20, 0x02, 0x20, - 0x04, 0x28, 0x02, 0x04, 0x6b, 0x21, 0x01, 0x0c, 0x03, 0x0b, 0x20, 0x04, - 0x20, 0x01, 0x20, 0x04, 0x28, 0x02, 0x04, 0x22, 0x07, 0x4b, 0x22, 0x08, - 0x41, 0x03, 0x74, 0x6a, 0x22, 0x09, 0x20, 0x09, 0x28, 0x02, 0x00, 0x20, - 0x01, 0x20, 0x07, 0x41, 0x00, 0x20, 0x08, 0x1b, 0x6b, 0x22, 0x07, 0x6a, - 0x36, 0x02, 0x00, 0x20, 0x04, 0x41, 0x0c, 0x41, 0x04, 0x20, 0x08, 0x1b, - 0x6a, 0x22, 0x04, 0x20, 0x04, 0x28, 0x02, 0x00, 0x20, 0x07, 0x6b, 0x36, - 0x02, 0x00, 0x20, 0x09, 0x21, 0x04, 0x20, 0x06, 0x20, 0x01, 0x6b, 0x22, - 0x06, 0x20, 0x00, 0x28, 0x02, 0x38, 0x20, 0x09, 0x20, 0x05, 0x20, 0x08, - 0x6b, 0x22, 0x05, 0x10, 0x99, 0x80, 0x80, 0x80, 0x00, 0x22, 0x01, 0x47, - 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x00, 0x20, 0x00, 0x28, 0x02, 0x28, 0x22, - 0x01, 0x36, 0x02, 0x18, 0x20, 0x00, 0x20, 0x01, 0x36, 0x02, 0x14, 0x20, - 0x00, 0x20, 0x01, 0x20, 0x00, 0x28, 0x02, 0x2c, 0x6a, 0x36, 0x02, 0x10, - 0x20, 0x02, 0x21, 0x01, 0x0b, 0x20, 0x03, 0x41, 0x10, 0x6a, 0x24, 0x80, - 0x80, 0x80, 0x80, 0x00, 0x20, 0x01, 0x0b, 0x66, 0x01, 0x02, 0x7f, 0x23, - 0x80, 0x80, 0x80, 0x80, 0x00, 0x41, 0x20, 0x6b, 0x22, 0x01, 0x24, 0x80, - 0x80, 0x80, 0x80, 0x00, 0x02, 0x40, 0x02, 0x40, 0x20, 0x00, 0x20, 0x01, - 0x41, 0x08, 0x6a, 0x10, 0x89, 0x80, 0x80, 0x80, 0x00, 0x22, 0x00, 0x0d, - 0x00, 0x41, 0x3b, 0x21, 0x00, 0x20, 0x01, 0x2d, 0x00, 0x08, 0x41, 0x02, - 0x47, 0x0d, 0x00, 0x20, 0x01, 0x2d, 0x00, 0x10, 0x41, 0x24, 0x71, 0x0d, - 0x00, 0x41, 0x01, 0x21, 0x02, 0x0c, 0x01, 0x0b, 0x41, 0x00, 0x21, 0x02, - 0x41, 0x00, 0x20, 0x00, 0x36, 0x02, 0xac, 0x89, 0x80, 0x80, 0x00, 0x0b, - 0x20, 0x01, 0x41, 0x20, 0x6a, 0x24, 0x80, 0x80, 0x80, 0x80, 0x00, 0x20, - 0x02, 0x0b, 0x3b, 0x00, 0x20, 0x00, 0x41, 0x81, 0x80, 0x80, 0x80, 0x00, - 0x36, 0x02, 0x20, 0x02, 0x40, 0x20, 0x00, 0x2d, 0x00, 0x00, 0x41, 0xc0, - 0x00, 0x71, 0x0d, 0x00, 0x20, 0x00, 0x28, 0x02, 0x38, 0x10, 0x9b, 0x80, - 0x80, 0x80, 0x00, 0x0d, 0x00, 0x20, 0x00, 0x41, 0x7f, 0x36, 0x02, 0x40, - 0x0b, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x10, 0x9a, 0x80, 0x80, 0x80, - 0x00, 0x0b, 0x64, 0x01, 0x01, 0x7f, 0x23, 0x80, 0x80, 0x80, 0x80, 0x00, - 0x41, 0x10, 0x6b, 0x22, 0x03, 0x24, 0x80, 0x80, 0x80, 0x80, 0x00, 0x02, - 0x40, 0x02, 0x40, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x41, 0xff, 0x01, - 0x71, 0x20, 0x03, 0x41, 0x08, 0x6a, 0x10, 0x8a, 0x80, 0x80, 0x80, 0x00, - 0x22, 0x02, 0x45, 0x0d, 0x00, 0x41, 0x00, 0x41, 0xc6, 0x00, 0x20, 0x02, - 0x20, 0x02, 0x41, 0xcc, 0x00, 0x46, 0x1b, 0x36, 0x02, 0xac, 0x89, 0x80, - 0x80, 0x00, 0x42, 0x7f, 0x21, 0x01, 0x0c, 0x01, 0x0b, 0x20, 0x03, 0x29, - 0x03, 0x08, 0x21, 0x01, 0x0b, 0x20, 0x03, 0x41, 0x10, 0x6a, 0x24, 0x80, - 0x80, 0x80, 0x80, 0x00, 0x20, 0x01, 0x0b, 0x11, 0x00, 0x20, 0x00, 0x28, - 0x02, 0x38, 0x20, 0x01, 0x20, 0x02, 0x10, 0x9d, 0x80, 0x80, 0x80, 0x00, - 0x0b, 0xee, 0x07, 0x01, 0x04, 0x7f, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, - 0x20, 0x02, 0x41, 0x20, 0x4b, 0x0d, 0x00, 0x20, 0x01, 0x41, 0x03, 0x71, - 0x45, 0x0d, 0x01, 0x20, 0x02, 0x45, 0x0d, 0x01, 0x20, 0x00, 0x20, 0x01, - 0x2d, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x20, 0x02, 0x41, 0x7f, 0x6a, 0x21, - 0x03, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x21, 0x04, 0x20, 0x01, 0x41, 0x01, - 0x6a, 0x22, 0x05, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x02, 0x20, 0x03, 0x45, - 0x0d, 0x02, 0x20, 0x00, 0x20, 0x01, 0x2d, 0x00, 0x01, 0x3a, 0x00, 0x01, - 0x20, 0x02, 0x41, 0x7e, 0x6a, 0x21, 0x03, 0x20, 0x00, 0x41, 0x02, 0x6a, - 0x21, 0x04, 0x20, 0x01, 0x41, 0x02, 0x6a, 0x22, 0x05, 0x41, 0x03, 0x71, - 0x45, 0x0d, 0x02, 0x20, 0x03, 0x45, 0x0d, 0x02, 0x20, 0x00, 0x20, 0x01, - 0x2d, 0x00, 0x02, 0x3a, 0x00, 0x02, 0x20, 0x02, 0x41, 0x7d, 0x6a, 0x21, - 0x03, 0x20, 0x00, 0x41, 0x03, 0x6a, 0x21, 0x04, 0x20, 0x01, 0x41, 0x03, - 0x6a, 0x22, 0x05, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x02, 0x20, 0x03, 0x45, - 0x0d, 0x02, 0x20, 0x00, 0x20, 0x01, 0x2d, 0x00, 0x03, 0x3a, 0x00, 0x03, - 0x20, 0x02, 0x41, 0x7c, 0x6a, 0x21, 0x03, 0x20, 0x00, 0x41, 0x04, 0x6a, - 0x21, 0x04, 0x20, 0x01, 0x41, 0x04, 0x6a, 0x21, 0x05, 0x0c, 0x02, 0x0b, - 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0xfc, 0x0a, 0x00, 0x00, 0x20, 0x00, - 0x0f, 0x0b, 0x20, 0x02, 0x21, 0x03, 0x20, 0x00, 0x21, 0x04, 0x20, 0x01, - 0x21, 0x05, 0x0b, 0x02, 0x40, 0x02, 0x40, 0x20, 0x04, 0x41, 0x03, 0x71, - 0x22, 0x02, 0x0d, 0x00, 0x02, 0x40, 0x02, 0x40, 0x20, 0x03, 0x41, 0x10, - 0x4f, 0x0d, 0x00, 0x20, 0x03, 0x21, 0x02, 0x0c, 0x01, 0x0b, 0x02, 0x40, - 0x20, 0x03, 0x41, 0x70, 0x6a, 0x22, 0x02, 0x41, 0x10, 0x71, 0x0d, 0x00, - 0x20, 0x04, 0x20, 0x05, 0x29, 0x02, 0x00, 0x37, 0x02, 0x00, 0x20, 0x04, - 0x20, 0x05, 0x29, 0x02, 0x08, 0x37, 0x02, 0x08, 0x20, 0x04, 0x41, 0x10, - 0x6a, 0x21, 0x04, 0x20, 0x05, 0x41, 0x10, 0x6a, 0x21, 0x05, 0x20, 0x02, - 0x21, 0x03, 0x0b, 0x20, 0x02, 0x41, 0x10, 0x49, 0x0d, 0x00, 0x20, 0x03, - 0x21, 0x02, 0x03, 0x40, 0x20, 0x04, 0x20, 0x05, 0x29, 0x02, 0x00, 0x37, - 0x02, 0x00, 0x20, 0x04, 0x20, 0x05, 0x29, 0x02, 0x08, 0x37, 0x02, 0x08, - 0x20, 0x04, 0x20, 0x05, 0x29, 0x02, 0x10, 0x37, 0x02, 0x10, 0x20, 0x04, - 0x20, 0x05, 0x29, 0x02, 0x18, 0x37, 0x02, 0x18, 0x20, 0x04, 0x41, 0x20, - 0x6a, 0x21, 0x04, 0x20, 0x05, 0x41, 0x20, 0x6a, 0x21, 0x05, 0x20, 0x02, - 0x41, 0x60, 0x6a, 0x22, 0x02, 0x41, 0x0f, 0x4b, 0x0d, 0x00, 0x0b, 0x0b, - 0x02, 0x40, 0x20, 0x02, 0x41, 0x08, 0x49, 0x0d, 0x00, 0x20, 0x04, 0x20, - 0x05, 0x29, 0x02, 0x00, 0x37, 0x02, 0x00, 0x20, 0x05, 0x41, 0x08, 0x6a, - 0x21, 0x05, 0x20, 0x04, 0x41, 0x08, 0x6a, 0x21, 0x04, 0x0b, 0x02, 0x40, - 0x20, 0x02, 0x41, 0x04, 0x71, 0x45, 0x0d, 0x00, 0x20, 0x04, 0x20, 0x05, - 0x28, 0x02, 0x00, 0x36, 0x02, 0x00, 0x20, 0x05, 0x41, 0x04, 0x6a, 0x21, - 0x05, 0x20, 0x04, 0x41, 0x04, 0x6a, 0x21, 0x04, 0x0b, 0x02, 0x40, 0x20, - 0x02, 0x41, 0x02, 0x71, 0x45, 0x0d, 0x00, 0x20, 0x04, 0x20, 0x05, 0x2f, - 0x00, 0x00, 0x3b, 0x00, 0x00, 0x20, 0x04, 0x41, 0x02, 0x6a, 0x21, 0x04, - 0x20, 0x05, 0x41, 0x02, 0x6a, 0x21, 0x05, 0x0b, 0x20, 0x02, 0x41, 0x01, - 0x71, 0x45, 0x0d, 0x01, 0x20, 0x04, 0x20, 0x05, 0x2d, 0x00, 0x00, 0x3a, - 0x00, 0x00, 0x20, 0x00, 0x0f, 0x0b, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, - 0x02, 0x40, 0x02, 0x40, 0x20, 0x03, 0x41, 0x20, 0x49, 0x0d, 0x00, 0x20, - 0x04, 0x20, 0x05, 0x28, 0x02, 0x00, 0x22, 0x03, 0x3a, 0x00, 0x00, 0x02, - 0x40, 0x02, 0x40, 0x20, 0x02, 0x41, 0x7f, 0x6a, 0x0e, 0x03, 0x03, 0x00, - 0x01, 0x03, 0x0b, 0x20, 0x04, 0x20, 0x03, 0x41, 0x08, 0x76, 0x3a, 0x00, - 0x01, 0x20, 0x04, 0x20, 0x05, 0x41, 0x06, 0x6a, 0x29, 0x01, 0x00, 0x37, - 0x02, 0x06, 0x20, 0x04, 0x20, 0x05, 0x28, 0x02, 0x04, 0x41, 0x10, 0x74, - 0x20, 0x03, 0x41, 0x10, 0x76, 0x72, 0x36, 0x02, 0x02, 0x20, 0x04, 0x41, - 0x12, 0x6a, 0x21, 0x02, 0x20, 0x05, 0x41, 0x12, 0x6a, 0x21, 0x01, 0x41, - 0x0e, 0x21, 0x06, 0x20, 0x05, 0x41, 0x0e, 0x6a, 0x28, 0x01, 0x00, 0x21, - 0x05, 0x41, 0x0e, 0x21, 0x03, 0x0c, 0x03, 0x0b, 0x20, 0x04, 0x20, 0x05, - 0x41, 0x05, 0x6a, 0x29, 0x00, 0x00, 0x37, 0x02, 0x05, 0x20, 0x04, 0x20, - 0x05, 0x28, 0x02, 0x04, 0x41, 0x18, 0x74, 0x20, 0x03, 0x41, 0x08, 0x76, - 0x72, 0x36, 0x02, 0x01, 0x20, 0x04, 0x41, 0x11, 0x6a, 0x21, 0x02, 0x20, - 0x05, 0x41, 0x11, 0x6a, 0x21, 0x01, 0x41, 0x0d, 0x21, 0x06, 0x20, 0x05, - 0x41, 0x0d, 0x6a, 0x28, 0x00, 0x00, 0x21, 0x05, 0x41, 0x0f, 0x21, 0x03, - 0x0c, 0x02, 0x0b, 0x02, 0x40, 0x02, 0x40, 0x20, 0x03, 0x41, 0x10, 0x4f, - 0x0d, 0x00, 0x20, 0x04, 0x21, 0x02, 0x20, 0x05, 0x21, 0x01, 0x0c, 0x01, - 0x0b, 0x20, 0x04, 0x20, 0x05, 0x2d, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x20, - 0x04, 0x20, 0x05, 0x28, 0x00, 0x01, 0x36, 0x00, 0x01, 0x20, 0x04, 0x20, - 0x05, 0x29, 0x00, 0x05, 0x37, 0x00, 0x05, 0x20, 0x04, 0x20, 0x05, 0x2f, - 0x00, 0x0d, 0x3b, 0x00, 0x0d, 0x20, 0x04, 0x20, 0x05, 0x2d, 0x00, 0x0f, - 0x3a, 0x00, 0x0f, 0x20, 0x04, 0x41, 0x10, 0x6a, 0x21, 0x02, 0x20, 0x05, - 0x41, 0x10, 0x6a, 0x21, 0x01, 0x0b, 0x20, 0x03, 0x41, 0x08, 0x71, 0x0d, - 0x02, 0x0c, 0x03, 0x0b, 0x20, 0x04, 0x20, 0x03, 0x41, 0x10, 0x76, 0x3a, - 0x00, 0x02, 0x20, 0x04, 0x20, 0x03, 0x41, 0x08, 0x76, 0x3a, 0x00, 0x01, - 0x20, 0x04, 0x20, 0x05, 0x41, 0x07, 0x6a, 0x29, 0x00, 0x00, 0x37, 0x02, - 0x07, 0x20, 0x04, 0x20, 0x05, 0x28, 0x02, 0x04, 0x41, 0x08, 0x74, 0x20, - 0x03, 0x41, 0x18, 0x76, 0x72, 0x36, 0x02, 0x03, 0x20, 0x04, 0x41, 0x13, - 0x6a, 0x21, 0x02, 0x20, 0x05, 0x41, 0x13, 0x6a, 0x21, 0x01, 0x41, 0x0f, - 0x21, 0x06, 0x20, 0x05, 0x41, 0x0f, 0x6a, 0x28, 0x00, 0x00, 0x21, 0x05, - 0x41, 0x0d, 0x21, 0x03, 0x0b, 0x20, 0x04, 0x20, 0x06, 0x6a, 0x20, 0x05, - 0x36, 0x02, 0x00, 0x0b, 0x20, 0x02, 0x20, 0x01, 0x29, 0x00, 0x00, 0x37, - 0x00, 0x00, 0x20, 0x02, 0x41, 0x08, 0x6a, 0x21, 0x02, 0x20, 0x01, 0x41, - 0x08, 0x6a, 0x21, 0x01, 0x0b, 0x02, 0x40, 0x20, 0x03, 0x41, 0x04, 0x71, - 0x45, 0x0d, 0x00, 0x20, 0x02, 0x20, 0x01, 0x28, 0x00, 0x00, 0x36, 0x00, - 0x00, 0x20, 0x02, 0x41, 0x04, 0x6a, 0x21, 0x02, 0x20, 0x01, 0x41, 0x04, - 0x6a, 0x21, 0x01, 0x0b, 0x02, 0x40, 0x20, 0x03, 0x41, 0x02, 0x71, 0x45, - 0x0d, 0x00, 0x20, 0x02, 0x20, 0x01, 0x2f, 0x00, 0x00, 0x3b, 0x00, 0x00, - 0x20, 0x02, 0x41, 0x02, 0x6a, 0x21, 0x02, 0x20, 0x01, 0x41, 0x02, 0x6a, - 0x21, 0x01, 0x0b, 0x20, 0x03, 0x41, 0x01, 0x71, 0x45, 0x0d, 0x00, 0x20, - 0x02, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x0b, 0x20, 0x00, - 0x0b, 0xcf, 0x01, 0x01, 0x03, 0x7f, 0x20, 0x00, 0x21, 0x01, 0x02, 0x40, - 0x02, 0x40, 0x20, 0x00, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x00, 0x02, 0x40, - 0x20, 0x00, 0x2d, 0x00, 0x00, 0x0d, 0x00, 0x20, 0x00, 0x20, 0x00, 0x6b, - 0x0f, 0x0b, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x22, 0x01, 0x41, 0x03, 0x71, - 0x45, 0x0d, 0x00, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x45, 0x0d, 0x01, 0x20, - 0x00, 0x41, 0x02, 0x6a, 0x22, 0x01, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x00, - 0x20, 0x01, 0x2d, 0x00, 0x00, 0x45, 0x0d, 0x01, 0x20, 0x00, 0x41, 0x03, - 0x6a, 0x22, 0x01, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x00, 0x20, 0x01, 0x2d, - 0x00, 0x00, 0x45, 0x0d, 0x01, 0x20, 0x00, 0x41, 0x04, 0x6a, 0x22, 0x01, - 0x41, 0x03, 0x71, 0x0d, 0x01, 0x0b, 0x20, 0x01, 0x41, 0x7c, 0x6a, 0x21, - 0x02, 0x20, 0x01, 0x41, 0x7b, 0x6a, 0x21, 0x01, 0x03, 0x40, 0x20, 0x01, - 0x41, 0x04, 0x6a, 0x21, 0x01, 0x41, 0x80, 0x82, 0x84, 0x08, 0x20, 0x02, - 0x41, 0x04, 0x6a, 0x22, 0x02, 0x28, 0x02, 0x00, 0x22, 0x03, 0x6b, 0x20, - 0x03, 0x72, 0x41, 0x80, 0x81, 0x82, 0x84, 0x78, 0x71, 0x41, 0x80, 0x81, - 0x82, 0x84, 0x78, 0x46, 0x0d, 0x00, 0x0b, 0x03, 0x40, 0x20, 0x01, 0x41, - 0x01, 0x6a, 0x21, 0x01, 0x20, 0x02, 0x2d, 0x00, 0x00, 0x21, 0x03, 0x20, - 0x02, 0x41, 0x01, 0x6a, 0x21, 0x02, 0x20, 0x03, 0x0d, 0x00, 0x0b, 0x0b, - 0x20, 0x01, 0x20, 0x00, 0x6b, 0x0b, 0x0b, 0x9d, 0x01, 0x02, 0x00, 0x41, - 0x80, 0x08, 0x0b, 0x1c, 0x0a, 0x0a, 0x09, 0x48, 0x65, 0x6c, 0x6c, 0x6f, - 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, - 0x4f, 0x63, 0x72, 0x65, 0x21, 0x0a, 0x0a, 0x00, 0x00, 0x41, 0xa0, 0x08, - 0x0b, 0x74, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xb8, 0x04, 0x00, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00 - }; -static unsigned int wasm_binary_len = 3850; +#include +#include + +// Symbols created by objcopy from app.wasm +extern const uint8_t _binary_app_wasm_start[]; +extern const uint8_t _binary_app_wasm_end[]; + +// Macros for compatibility with existing code +#define wasm_binary _binary_app_wasm_start +#define wasm_binary_len ((size_t)(_binary_app_wasm_end - _binary_app_wasm_start)) -#endif // OCRE_INPUT_FILE_H +#endif diff --git a/src/ocre/wasm_manifest.h.in b/src/ocre/wasm_manifest.h.in new file mode 100644 index 0000000..a567053 --- /dev/null +++ b/src/ocre/wasm_manifest.h.in @@ -0,0 +1,53 @@ +// Auto-generated WASM manifest +// DO NOT EDIT - Generated at build time from wasm_manifest.h.in + +#ifndef OCRE_WASM_MANIFEST_H +#define OCRE_WASM_MANIFEST_H + +#include +#include +#include + +// External symbols from objcopy +@EXTERN_DECLARATIONS@ + +// WASM binary entry structure +typedef struct { + const char *name; // Container name + const uint8_t *data; // Pointer to WASM binary +} wasm_binary_entry_t; + +// Number of embedded WASM binaries +#define WASM_BINARY_COUNT @COUNT@ + +// Manifest array (size calculated on access, not at initialization) +static const wasm_binary_entry_t wasm_manifest[WASM_BINARY_COUNT] = { +@MANIFEST_ENTRIES@ +}; + +// Helper function to get size (calculated at runtime) +static inline size_t wasm_get_size(int index) { + if (index < 0 || index >= WASM_BINARY_COUNT) return 0; +@SIZE_CALCULATIONS@ + return 0; +} + +// Helper function to find a WASM binary by name +static inline const wasm_binary_entry_t* wasm_find(const char *name) { + if (!name) return NULL; + for (int i = 0; i < WASM_BINARY_COUNT; i++) { + if (strcmp(wasm_manifest[i].name, name) == 0) { + return &wasm_manifest[i]; + } + } + return NULL; +} + +// Helper function to get WASM binary by index (with runtime size calculation) +static inline const wasm_binary_entry_t* wasm_get(int index) { + if (index < 0 || index >= WASM_BINARY_COUNT) return NULL; + // Note: size field is 0 in static array, use wasm_get_size() to get actual size + return &wasm_manifest[index]; +} + +#endif // OCRE_WASM_MANIFEST_H diff --git a/src/samples-mini/zephyr/main.c b/src/samples-mini/zephyr/main.c index 024cf0a..577ab73 100644 --- a/src/samples-mini/zephyr/main.c +++ b/src/samples-mini/zephyr/main.c @@ -5,106 +5,146 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include "ocre_core_external.h" -#include -#include - -#include -#include - -#ifdef HAS_GENERATED_INPUT -#include -#else -#include -#endif - -void create_sample_container(); -int ocre_network_init(); - -int main(int argc, char *argv[]) { - ocre_cs_ctx ctx; - ocre_container_init_arguments_t args; - char *container_filename = "hello"; - -#ifdef CONFIG_OCRE_NETWORKING - int net_status = ocre_network_init(); - if (net_status < 0) { - printf("Unable to connect to network\n"); - } else { - printf("Network is UP\n"); - } -#endif - - ocre_app_storage_init(); - - // Step 1: Initialize the Ocre runtime - ocre_container_runtime_status_t ret = ocre_container_runtime_init(&ctx, &args); - - if (ret == RUNTIME_STATUS_INITIALIZED) { - printf("\n\nOcre runtime started\n"); - - create_sample_container(container_filename); - - // Step 2: Create the container, this allocates and loads the container binary - ocre_container_data_t ocre_container_data; - int container_ID; - - ocre_container_data.heap_size = 0; - snprintf(ocre_container_data.name, sizeof(ocre_container_data.name), "Hello World"); - snprintf(ocre_container_data.sha256, sizeof(ocre_container_data.sha256), "%s", container_filename); - ocre_container_data.timers = 0; - ocre_container_runtime_create_container(&ctx, &ocre_container_data, &container_ID, NULL); - - // Step 3: Execute the container - ocre_container_runtime_run_container(container_ID, NULL); - // Loop forever, without this the application will exit and stop all execution - while (true) { - core_sleep_ms(1000); + #include + #include + #include "ocre_core_external.h" + #include + #include + + #include + #include + + #ifdef HAS_WASM_MANIFEST + #include "wasm_manifest.h" + #endif + + void create_containers_from_manifest(ocre_cs_ctx *ctx); + int ocre_network_init(); + + int main(int argc, char *argv[]) { + ocre_cs_ctx ctx; + ocre_container_init_arguments_t args; + + #ifdef CONFIG_OCRE_NETWORKING + int net_status = ocre_network_init(); + if (net_status < 0) { + printf("Unable to connect to network\n"); + } else { + printf("Network is UP\n"); + } + #endif + + ocre_app_storage_init(); + + // Step 1: Initialize the Ocre runtime + ocre_container_runtime_status_t ret = ocre_container_runtime_init(&ctx, &args); + + if (ret == RUNTIME_STATUS_INITIALIZED) { + printf("\n\nOcre runtime started\n"); + + #ifdef HAS_WASM_MANIFEST + // Create and run all containers from manifest + printf("Found %d WASM binaries to load\n", WASM_BINARY_COUNT); + create_containers_from_manifest(&ctx); + #else + printf("ERROR: No WASM binaries provided. Build with -f option.\n"); + #endif + + // Loop forever, without this the application will exit and stop all execution + while (true) { + core_sleep_ms(1000); + } + + } else { + printf("\n\nOcre runtime failed to start.\n"); + } + } + + #ifdef HAS_WASM_MANIFEST + /** + * Create and run all containers from the embedded WASM manifest + */ + void create_containers_from_manifest(ocre_cs_ctx *ctx) { + int container_IDs[WASM_BINARY_COUNT]; + + // Step 1: Write all WASM binaries to filesystem + for (int i = 0; i < WASM_BINARY_COUNT; i++) { + const wasm_binary_entry_t *entry = wasm_get(i); + size_t actual_size = wasm_get_size(i); // ← Use the helper function! + + printf("Loading WASM: %s (%zu bytes) from flash\n", entry->name, actual_size); + + // Write to filesystem + char file_path[64]; + struct fs_file_t f; + snprintf(file_path, sizeof(file_path), "/lfs/ocre/images/%s.bin", entry->name); + + fs_file_t_init(&f); + int res = fs_open(&f, file_path, FS_O_CREATE | FS_O_RDWR); + if (res < 0) { + printf(" ERROR: Failed to create file: %d\n", res); + continue; } - } else { - printf("\n\nOcre runtime failed to start.\n"); + fs_write(&f, entry->data, actual_size); // ← Use actual_size + fs_close(&f); + printf(" Written to: %s\n", file_path); } -} -/** - * Creates a container image file using the sample "hello-word" WASM module - * This is for demostration purposes only and does not perform any error checking. - * - * @param file_name a string containing the name of the file to create - */ + // Step 2: Create all containers + for (int i = 0; i < WASM_BINARY_COUNT; i++) { + const wasm_binary_entry_t *entry = wasm_get(i); + + ocre_container_data_t container_data; + container_data.heap_size = 0; + snprintf(container_data.name, sizeof(container_data.name), "%s", entry->name); + snprintf(container_data.sha256, sizeof(container_data.sha256), "%s", entry->name); + container_data.timers = 0; + + ocre_container_status_t status = ocre_container_runtime_create_container(ctx, &container_data, + &container_IDs[i], NULL); + // Check for CREATED status, not 0! + if (status == CONTAINER_STATUS_CREATED) { + printf("Container requested: %s (ID: %d)\n", entry->name, container_IDs[i]); + core_sleep_ms(100); + } else { + printf("ERROR: Failed to request container %s: %d\n", entry->name, status); + container_IDs[i] = -1; + } + } -void create_sample_container(char *file_name) { - static char file_path[64]; - struct fs_file_t f; - snprintf((char *)&file_path, 64, "/lfs/ocre/images/%s.bin", file_name); - int res; + // Give containers time to actually be created asynchronously + printf("Waiting for containers to be created...\n"); + core_sleep_ms(500); // Wait for async creation to complete - fs_file_t_init(&f); - res = fs_open(&f, file_path, FS_O_CREATE | FS_O_RDWR); + // Run all containers + for (int i = 0; i < WASM_BINARY_COUNT; i++) { + if (container_IDs[i] >= 0) { + const wasm_binary_entry_t *entry = wasm_get(i); + printf("Starting container: %s\n", entry->name); + ocre_container_runtime_run_container(container_IDs[i], NULL); + } + } - fs_write(&f, &wasm_binary, wasm_binary_len); - fs_close(&f); + printf("All containers started!\n"); } + #endif -int ocre_network_init() { + int ocre_network_init() { + struct net_if *iface = net_if_get_default(); + net_dhcpv4_start(iface); - struct net_if *iface = net_if_get_default(); - net_dhcpv4_start(iface); + printf("Waiting for network to be ready...\n"); - printf("Waiting for network to be ready...\n"); + int sleep_cnt = 0; + while (!net_if_is_up(iface) && (sleep_cnt < 10)) { + k_sleep(K_MSEC(200)); + sleep_cnt++; + } - int sleep_cnt = 0; - while (!net_if_is_up(iface) && (sleep_cnt < 10)) { - k_sleep(K_MSEC(200)); - sleep_cnt++; - } + if (!net_if_is_up(iface)) { + return -ENOTCONN; + } - if (!net_if_is_up(iface)) { - return -ENOTCONN; - } - - return 0; -} + return 0; + } diff --git a/src/shared/platform/zephyr/ocre_internal.cmake b/src/shared/platform/zephyr/ocre_internal.cmake index 38fbcd1..7ff1c8f 100644 --- a/src/shared/platform/zephyr/ocre_internal.cmake +++ b/src/shared/platform/zephyr/ocre_internal.cmake @@ -20,7 +20,7 @@ elseif (DEFINED CONFIG_XTENSA) elseif (DEFINED CONFIG_RISCV) set(TARGET_ISA RISCV32) elseif (DEFINED CONFIG_ARCH_POSIX) - set(TARGET_ISA X86_32) + set(TARGET_ISA X86_32) else () message(FATAL_ERROR "Unsupported ISA: ${CONFIG_ARCH}") endif () @@ -119,6 +119,21 @@ target_sources(app PRIVATE add_dependencies(app generate_messages) -if(NOT "${OCRE_INPUT_FILE}" STREQUAL "") - add_dependencies(app generate_ocre_file) +message(STATUS "DEBUG: WASM_MANIFEST_ENTRIES = '${WASM_MANIFEST_ENTRIES}'") +message(STATUS "DEBUG: CMAKE_CURRENT_BINARY_DIR = '${CMAKE_CURRENT_BINARY_DIR}'") + +# Link WASM object files if manifest was generated +if(DEFINED WASM_MANIFEST_ENTRIES AND WASM_MANIFEST_ENTRIES) + message(STATUS "Linking WASM object files: ${WASM_MANIFEST_ENTRIES}") + + foreach(WASM_NAME ${WASM_MANIFEST_ENTRIES}) + set(WASM_OBJ ${CMAKE_CURRENT_BINARY_DIR}/wasm_${WASM_NAME}.o) + + # Don't check if EXISTS - files are generated at build time! + target_sources(app PRIVATE ${WASM_OBJ}) + add_dependencies(app generate_${WASM_NAME}_wasm) + message(STATUS " → Will link: ${WASM_OBJ}") + endforeach() +else() + message(WARNING "No WASM_MANIFEST_ENTRIES defined!") endif() diff --git a/tools/generate_wasm_manifest.py b/tools/generate_wasm_manifest.py new file mode 100644 index 0000000..32e23f6 --- /dev/null +++ b/tools/generate_wasm_manifest.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python3 +""" +Generate a C header manifest for embedded WASM binaries from template +""" +import sys +import argparse +from pathlib import Path + +def sanitize_name(name): + """Convert name to valid C symbol (replace - and . with _)""" + return name.replace('-', '_').replace('.', '_') + +def generate_extern_declarations(wasm_names): + """Generate extern declarations for all WASM symbols""" + declarations = [] + for name in wasm_names: + safe_name = sanitize_name(name) + declarations.append(f"// {name}") + declarations.append(f"extern const uint8_t _binary_{safe_name}_wasm_start[];") + declarations.append(f"extern const uint8_t _binary_{safe_name}_wasm_end[];") + return "\n".join(declarations) + +def generate_manifest_entries(wasm_names): + """Generate manifest array entries WITHOUT size field""" + entries = [] + for name in wasm_names: + safe_name = sanitize_name(name) + entry = f""" {{ + .name = "{name}", + .data = _binary_{safe_name}_wasm_start + }}""" + entries.append(entry) + return ",\n".join(entries) + +def generate_size_calculations(wasm_names): + """Generate size calculation switch statement""" + cases = [] + for i, name in enumerate(wasm_names): + safe_name = sanitize_name(name) + cases.append(f" if (index == {i}) return (size_t)(_binary_{safe_name}_wasm_end - _binary_{safe_name}_wasm_start);") + return "\n".join(cases) + +def main(): + parser = argparse.ArgumentParser(description='Generate WASM manifest header from template') + parser.add_argument('names', nargs='+', help='WASM container names') + parser.add_argument('-t', '--template', required=True, help='Input template file') + parser.add_argument('-o', '--output', required=True, help='Output header file') + + args = parser.parse_args() + + # Read template + template_path = Path(args.template) + if not template_path.exists(): + print(f"Error: Template file not found: {args.template}", file=sys.stderr) + return 1 + + template = template_path.read_text() + + # Generate content pieces + extern_decls = generate_extern_declarations(args.names) + manifest_entries = generate_manifest_entries(args.names) + size_calculations = generate_size_calculations(args.names) + + # Replace placeholders + content = template.replace('@EXTERN_DECLARATIONS@', extern_decls) + content = content.replace('@COUNT@', str(len(args.names))) + content = content.replace('@MANIFEST_ENTRIES@', manifest_entries) + content = content.replace('@SIZE_CALCULATIONS@', size_calculations) + + # Write output + output_path = Path(args.output) + output_path.parent.mkdir(parents=True, exist_ok=True) + output_path.write_text(content) + + print(f"Generated manifest for {len(args.names)} WASM binaries: {', '.join(args.names)}") + print(f"Template: {args.template}") + print(f"Output: {args.output}") + + return 0 + +if __name__ == '__main__': + sys.exit(main())