From 9c366973e410ea9fa6ecc0684d6af152fbc92638 Mon Sep 17 00:00:00 2001 From: Tom Burdick Date: Wed, 27 Sep 2023 08:13:31 -0500 Subject: [PATCH] llext: Shell loader sample Adds a sample application that can be used for trying out llext with the shell. The docs cover how to load a hello world ELF on to the device, assuming its an arm v7 architecture. Signed-off-by: Tom Burdick --- samples/subsys/llext/llext.rst | 10 ++ .../subsys/llext/shell_loader/CMakeLists.txt | 9 ++ samples/subsys/llext/shell_loader/README.rst | 119 ++++++++++++++++++ samples/subsys/llext/shell_loader/prj.conf | 12 ++ samples/subsys/llext/shell_loader/sample.yaml | 14 +++ samples/subsys/llext/shell_loader/src/main.c | 15 +++ 6 files changed, 179 insertions(+) create mode 100644 samples/subsys/llext/llext.rst create mode 100644 samples/subsys/llext/shell_loader/CMakeLists.txt create mode 100644 samples/subsys/llext/shell_loader/README.rst create mode 100644 samples/subsys/llext/shell_loader/prj.conf create mode 100644 samples/subsys/llext/shell_loader/sample.yaml create mode 100644 samples/subsys/llext/shell_loader/src/main.c diff --git a/samples/subsys/llext/llext.rst b/samples/subsys/llext/llext.rst new file mode 100644 index 00000000000..f9001e2847b --- /dev/null +++ b/samples/subsys/llext/llext.rst @@ -0,0 +1,10 @@ +.. _llext-samples: + +Linkable Loadable Extension Samples +################################### + +.. toctree:: + :maxdepth: 1 + :glob: + + **/* diff --git a/samples/subsys/llext/shell_loader/CMakeLists.txt b/samples/subsys/llext/shell_loader/CMakeLists.txt new file mode 100644 index 00000000000..a9d5d832334 --- /dev/null +++ b/samples/subsys/llext/shell_loader/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(fs_shell) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/samples/subsys/llext/shell_loader/README.rst b/samples/subsys/llext/shell_loader/README.rst new file mode 100644 index 00000000000..d24ff89478f --- /dev/null +++ b/samples/subsys/llext/shell_loader/README.rst @@ -0,0 +1,119 @@ +.. zephyr:code-sample:: llext-shell-loader + :name: Linkable loadable extensions shell module + :relevant-api: llext + + Manage loadable extensions using shell commands. + +Overview +******** + +This example provides shell access to the :ref:`llext` system and provides the +ability to manage loadable code extensions in the shell. + +Requirements +************ + +A board with shell capable console. + +Building +******** + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/llext/shell_loader + :goals: build + :compact: + +.. note:: You may need to disable memory protection for the sample to work (e.g. CONFIG_ARM_MPU=n). + +Running +******* + +Once the board has booted, you will be presented with a shell prompt. +All the llext system related commands are available as sub-commands of llext +which can be seen with llext help + +.. code-block:: console + + uart:~$ llext help + llext - Loadable extension commands + Subcommands: + list :List loaded extensions and their size in memory + load_hex :Load an elf file encoded in hex directly from the shell input. + Syntax: + + unload :Unload an extension by name. Syntax: + + list_symbols :List extension symbols. Syntax: + + call_fn :Call extension function with prototype void fn(void). Syntax: + + +A hello world C file can be found in tests/subsys/llext/hello_world/hello_world.c + +This can be built into a relocatable elf usable on arm v7 platforms. It can be +inspected with some binutils to see symbols, sections, and relocations. +Then using additional tools converted to a hex string usable by the llext +load_hex shell command. + +On a host machine with the zephyr sdk setup and the arm toolchain in PATH + +.. code-block:: console + + $ arm-zephyr-eabi-gcc -mlong-calls -mthumb -c -o hello_world.elf tests/subsys/llext/hello_world/hello_world.c + $ arm-zephyr-eabi-objdump -x -t hello_world.elf + + hello_world.elf: file format elf32-littlearm + hello_world.elf + architecture: armv4t, flags 0x00000011: + HAS_RELOC, HAS_SYMS + start address 0x00000000 + private flags = 0x5000000: [Version5 EABI] + + Sections: + Idx Name Size VMA LMA File off Algn + 0 .text 00000024 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 1 .data 00000000 00000000 00000000 00000058 2**0 + CONTENTS, ALLOC, LOAD, DATA + 2 .bss 00000000 00000000 00000000 00000058 2**0 + ALLOC + 3 .rodata 0000000d 00000000 00000000 00000058 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 4 .comment 00000021 00000000 00000000 00000065 2**0 + CONTENTS, READONLY + 5 .ARM.attributes 0000002a 00000000 00000000 00000086 2**0 + CONTENTS, READONLY + arm-zephyr-eabi-objdump: hello_world.elf: not a dynamic object + SYMBOL TABLE: + 00000000 l df *ABS* 00000000 hello_world.c + 00000000 l d .text 00000000 .text + 00000000 l d .data 00000000 .data + 00000000 l d .bss 00000000 .bss + 00000000 l d .rodata 00000000 .rodata + 00000000 l d .comment 00000000 .comment + 00000000 l d .ARM.attributes 00000000 .ARM.attributes + 00000000 g F .text 00000020 hello_world + 00000000 *UND* 00000000 printk + + + RELOCATION RECORDS FOR [.text]: + OFFSET TYPE VALUE + 00000018 R_ARM_ABS32 .rodata + 0000001c R_ARM_ABS32 printk + + $ xxd -p hello_world.elf | tr -d '\n' + + +The resulting hex string can be used to load the extension. + +.. code-block:: console + + uart:~$ llext load_hex hello_world 7f454c4601010100000000000000000001002800010000000000000000000000180200000000000534000000000028000b000a0080b500af044b1800044b00f009f8c046bd4680bc01bc004700000000000000001847c04668656c6c6f20776f726c640a00004743433a20285a65706879722053444b20302e31362e31292031322e322e30004129000000616561626900011f000000053454000602080109011204140115011703180119011a011e06000000000000000000000000000000000100000000000000000000000400f1ff00000000000000000000000003000100000000000000000000000000030003000000000000000000000000000300040000000000000000000000000003000500090000000000000000000000000005000c000000000000000000000000000100090000001800000000000000000001000c00000020000000000000000000010000000000000000000000000003000600000000000000000000000000030007000f0000000100000020000000120001001b0000000000000000000000100000000068656c6c6f2e630024640024740068656c6c6f5f776f726c64007072696e746b00000018000000020500001c000000020d0000002e73796d746162002e737472746162002e7368737472746162002e72656c2e74657874002e64617461002e627373002e726f64617461002e636f6d6d656e74002e41524d2e6174747269627574657300000000000000000000000000000000000000000000000000000000000000000000000000000000000000001f0000000100000006000000000000003400000024000000000000000000000004000000000000001b000000090000004000000000000000b40100001000000008000000010000000400000008000000250000000100000003000000000000005800000000000000000000000000000001000000000000002b00000008000000030000000000000058000000000000000000000000000000010000000000000030000000010000000200000000000000580000000d000000000000000000000004000000000000003800000001000000300000000000000065000000210000000000000000000000010000000100000041000000030000700000000000000000860000002a0000000000000000000000010000000000000001000000020000000000000000000000b0000000e0000000090000000c00000004000000100000000900000003000000000000000000000090010000220000000000000000000000010000000000000011000000030000000000000000000000c40100005100000000000000000000000100000000000000 + +This extension can then be seen in the list of loaded extensions (`list`), its symbols printed (`list_symbols`), and the hello_world +function which the extension exports can be called and run (`call_fn`). + +.. code-block:: console + + uart:~$ llext call_fn hello_world hello_world + hello world diff --git a/samples/subsys/llext/shell_loader/prj.conf b/samples/subsys/llext/shell_loader/prj.conf new file mode 100644 index 00000000000..678e5eb55ae --- /dev/null +++ b/samples/subsys/llext/shell_loader/prj.conf @@ -0,0 +1,12 @@ +CONFIG_LOG=y +CONFIG_LOG_MODE_IMMEDIATE=y + +CONFIG_SHELL=y +CONFIG_SHELL_CMD_BUFF_SIZE=32768 +CONFIG_SHELL_LOG_LEVEL_INF=y +CONFIG_SHELL_STACK_SIZE=8192 + +CONFIG_LLEXT=y +CONFIG_LLEXT_LOG_LEVEL_DBG=y +CONFIG_LLEXT_HEAP_SIZE=32 +CONFIG_LLEXT_SHELL=y diff --git a/samples/subsys/llext/shell_loader/sample.yaml b/samples/subsys/llext/shell_loader/sample.yaml new file mode 100644 index 00000000000..5ef2a080286 --- /dev/null +++ b/samples/subsys/llext/shell_loader/sample.yaml @@ -0,0 +1,14 @@ +sample: + description: Loadable extensions with shell sample + name: Extension loader shell +tests: + sample.llext.shell: + tags: shell llext + harness: keyboard + filter: not CONFIG_CPU_HAS_MMU + arch_allow: arm + extra_configs: + - CONFIG_ARM_MPU=n + # Broken platforms + platform_exclude: + - nuvoton_pfm_m487 # See #63167 diff --git a/samples/subsys/llext/shell_loader/src/main.c b/samples/subsys/llext/shell_loader/src/main.c new file mode 100644 index 00000000000..f22be157314 --- /dev/null +++ b/samples/subsys/llext/shell_loader/src/main.c @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +#define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL +#include +LOG_MODULE_REGISTER(app); + +int main(void) +{ + return 0; +}