Skip to content

Commit

Permalink
Merge branch 'feature/elf_loader' into 'master'
Browse files Browse the repository at this point in the history
feat(elf_loader): Add ELF loader

See merge request ae_group/esp-iot-solution!830
  • Loading branch information
wujiangang committed Aug 29, 2023
2 parents 09b1493 + a8582e8 commit 1e1de02
Show file tree
Hide file tree
Showing 37 changed files with 2,200 additions and 0 deletions.
1 change: 1 addition & 0 deletions .github/workflows/upload_component.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ jobs:
components/bootloader_support_plus;
components/button;
components/display/lcd/esp_lcd_panel_io_additions;
components/elf_loader;
components/extended_vfs;
components/gprof;
components/knob;
Expand Down
23 changes: 23 additions & 0 deletions .gitlab/ci/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -551,3 +551,26 @@ build_tools_cmake_utilities_test_apps:
- IMAGE: espressif/idf:release-v5.0
variables:
EXAMPLE_DIR: tools/cmake_utilities/test_apps

build_example_elf_loader_elf_loader_example:
extends:
- .build_examples_template
- .rules:build:example_elf_loader_elf_loader_example
parallel:
matrix:
- IMAGE: espressif/idf:release-v4.4
- IMAGE: espressif/idf:release-v5.0
EXAMPLE_CONFIG: "sdkconfig.ci=default"
variables:
EXAMPLE_DIR: examples/elf_loader/elf_loader_example

build_example_elf_loader_build_elf_file_example:
extends:
- .build_examples_template
- .rules:build:example_elf_loader_build_elf_file_example
parallel:
matrix:
- IMAGE: espressif/idf:release-v4.4
- IMAGE: espressif/idf:release-v5.0
variables:
EXAMPLE_DIR: examples/elf_loader/build_elf_file_example
26 changes: 26 additions & 0 deletions .gitlab/ci/rules.yml
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,12 @@
.patterns-example_gprof_gprof_simple: &patterns-example_gprof_gprof_simple
- "examples/gprof/gprof_simple/**/*"

.patterns-example_elf_loader_elf_loader_example: &patterns-example_elf_loader_elf_loader_example
- "examples/elf_loader/elf_loader_example/**/*"

.patterns-example_elf_loader_build_elf_file_example: &patterns-example_elf_loader_build_elf_file_example
- "examples/elf_loader/build_elf_file_example/**/*"

# tools folder, in the alphabetic order
.patterns-tools_cmake_utilities: &patterns-tools_cmake_utilities
- "tools/cmake_utilities/**/*"
Expand Down Expand Up @@ -820,6 +826,26 @@
- <<: *if-dev-push
changes: *patterns-example_utilities_xz_decompress_file

.rules:build:example_elf_loader_elf_loader_example:
rules:
- <<: *if-protected
- <<: *if-label-build
- <<: *if-trigger-job
- <<: *if-dev-push
changes: *patterns-build_system
- <<: *if-dev-push
changes: *patterns-example_elf_loader_elf_loader_example

.rules:build:example_elf_loader_build_elf_file_example:
rules:
- <<: *if-protected
- <<: *if-label-build
- <<: *if-trigger-job
- <<: *if-dev-push
changes: *patterns-build_system
- <<: *if-dev-push
changes: *patterns-example_elf_loader_build_elf_file_example

# rules for ut
.rules:build:component_audio_dac_audio_test:
rules:
Expand Down
5 changes: 5 additions & 0 deletions components/elf_loader/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# ChangeLog

## v0.1.0 - 2023-08-14

* Add basic ELF loader component
26 changes: 26 additions & 0 deletions components/elf_loader/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

if(CONFIG_ELF_LOADER)
set(srcs "src/esp_elf_symbol.c"
"src/esp_elf.c"
"src/esp_elf_adapter.c")

if(CONFIG_IDF_TARGET_ARCH_XTENSA)
list(APPEND srcs "src/arch/esp_elf_xtensa.c")

# ESP32-S2 need to set MMU to run ELF
if(CONFIG_IDF_TARGET_ESP32S2 AND (CONFIG_ELF_LOADER_LOAD_PSRAM))
list(APPEND srcs "src/soc/esp_elf_esp32s2.c")
endif()
endif()

set(include_dirs "include")
endif()

idf_component_register(SRCS ${srcs}
INCLUDE_DIRS ${include_dirs}
PRIV_REQUIRES spi_flash)

include(package_manager)
if(CONFIG_ELF_LOADER)
cu_pkg_define_version(${CMAKE_CURRENT_LIST_DIR})
endif()
48 changes: 48 additions & 0 deletions components/elf_loader/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
menu "Espressif ELF Loader Configuration"
visible if (IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3)

config ELF_LOADER
bool "Enable Espressif ELF Loader"
default y
depends on (IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3)
help
Select this option to enable ELF Loader and show the submenu with ELF Loader configuration choices.

if ELF_LOADER
config ELF_LOADER_CACHE_OFFSET
bool
default n
help
Select this option if D-cache and I-cache has different offset to access the same physical address.

config ELF_LOADER_SET_MMU
bool
default n
help
Select this option if D-cache and I-cache is not symmetry。

config ELF_LOADER_LOAD_PSRAM
bool "Load ELF to PSRAM"
default y
depends on (IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3) && SPIRAM
select ELF_LOADER_CACHE_OFFSET if (IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3)
select ELF_LOADER_SET_MMU if IDF_TARGET_ESP32S2
help
Load ELF file into PSRAM instead of internal SRAM.

menu "ELF Symbols Table"

config ELF_LOADER_LIBC_SYMBOLS
bool "Libc Symbols Table"
default y

config ELF_LOADER_ESPIDF_SYMBOLS
bool "ESP-IDF Symbols Table"
default y

config ELF_LOADER_CUSTOMER_SYMBOLS
bool "Customer Symbols Table"
default n
endmenu
endif
endmenu
83 changes: 83 additions & 0 deletions components/elf_loader/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
## Description

[![Component Registry](https://components.espressif.com/components/espressif/elf_loader/badge.svg)](https://components.espressif.com/components/espressif/elf_loader)

Espressif ELF(Executable and Linkable Format) loader is a software development kit that is developed based on the ESP-IDF, mainly used to load ELF file compiled based on ESP32 series SoCs to the executable memory area, then link and execute it.

In this way, the application does not need compile into the whole firmware in advance. It is like running the compiled program through terminal input `./main.o` on the Ubuntu platform automatically, which realizes the separation of application and kernel.

This ELF loader supports following SoCs:

- ESP32
- ESP32-S2, support running ELF in PSRAM
- ESP32-S3, support running ELF in PSRAM

### Usage

#### Firmware

Add a dependency on this component in your component or project's idf_component.yml file.

```yml
dependencies:
espressif/elf_loader: "0.*"
```

Enable ELF loader in the menuconfig:

```
Component config --->
ESP-ELFLoader Configuration --->
[*] Enable Espressif ELF Loader
```

Add API calls in your project as follows:

```c
#include "esp_elf.h"

esp_elf_t elf;

// Your Code

esp_elf_init(&elf);
esp_elf_relocate(&elf, elf_file_data_bytes);
esp_elf_request(&elf, 0, argc, argv);
esp_elf_deinit(&elf);
```
#### ELF APP
To use this feature to compile ELF file, including the required CMake file in your project's CMakeLists.txt file after the line project(XXXX).
```cmake
project(XXXX)
# Add
include(elf_loader)
project_elf(XXXX)
```

Build the project as an ordinary ESP-IDF project, and then the ELF file named `XXXX.app.elf` is in the build directory.

### Adding the Component to Your Project

Please use the component manager command add-dependency to add the elf_loader component as a dependency in your project. During the CMake step, the component will be downloaded automatically.

```
idf.py add-dependency "espressif/elf_loader=*"
```

### Examples

Please use the component manager command create-project-from-example to create a project from the example template.

```
idf.py create-project-from-example "espressif/elf_loader=*:elf_loader_example"
```

This command will download the example elf_loader_example into the current folder. You can navigate into it to build and flash the example.

Alternatively, you can download examples from the esp-iot-solution repository:
1. [build_elf_file_example](https://github.com/espressif/esp-iot-solution/tree/master/examples/elf_loader/build_elf_file_example)
2. [elf_loader_example](https://github.com/espressif/esp-iot-solution/tree/master/examples/elf_loader/elf_loader_example)
62 changes: 62 additions & 0 deletions components/elf_loader/elf_loader.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# The script is to generate ELF for application

# Trick to temporarily redefine project(). When functions are overriden in CMake, the originals can still be accessed
# using an underscore prefixed function of the same name. The following lines make sure that project calls
# the original project(). See https://cmake.org/pipermail/cmake/2015-October/061751.html.
function(project_elf)
endfunction()

function(_project_elf)
endfunction()

macro(project_elf project_name)
# Enable these options to remove unused symbols and reduce linked objects
set(cflags -nostartfiles
-nostdlib
-fPIC
-shared
-e app_main
-fdata-sections
-ffunction-sections
-Wl,--gc-sections
-fvisibility=hidden)

# Enable this options to remove unnecessary sections in
list(APPEND cflags -Wl,--strip-all
-Wl,--strip-debug
-Wl,--strip-discarded)

list(APPEND cflags -Dmain=app_main)

idf_build_set_property(COMPILE_OPTIONS "${cflags}" APPEND)

set(elf_app "${CMAKE_PROJECT_NAME}.app.elf")

# Remove more unused sections
string(REPLACE "-elf-gcc" "-elf-strip" ${CMAKE_STRIP} ${CMAKE_C_COMPILER})
set(strip_flags --strip-unneeded
--remove-section=.xt.lit
--remove-section=.xt.prop
--remove-section=.comment
--remove-section=.xtensa.info
--remove-section=.got.loc
--remove-section=.got)

# Link input list of libraries to ELF
if(ELF_COMPONENTS)
foreach(c "${ELF_COMPONENTS}")
set(elf_libs "${elf_libs}" "esp-idf/${c}/lib${c}.a")
endforeach()
endif()

set(elf_libs ${elf_libs} "${ELF_LIBS}" "esp-idf/main/libmain.a")
spaces2list(elf_libs)

add_custom_command(OUTPUT elf_app
COMMAND ${CMAKE_C_COMPILER} ${cflags} ${elf_libs} -o ${elf_app}
COMMAND ${CMAKE_STRIP} ${strip_flags} ${elf_app}
DEPENDS idf::main
COMMENT "Build ELF: ${elf_app}"
)
add_custom_target(elf ALL DEPENDS elf_app)
endmacro()
9 changes: 9 additions & 0 deletions components/elf_loader/idf_component.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
version: "0.1.0"
description: Espressif ELF(Executable and Linkable Format) Loader
url: https://github.com/espressif/esp-iot-solution/tree/master/components/elf_loader
dependencies:
idf: ">=4.4.3"
espressif/cmake_utilities: "0.*"
examples:
- path: ../../examples/elf_loader/build_elf_file_example
- path: ../../examples/elf_loader/elf_loader_example
Loading

0 comments on commit 1e1de02

Please sign in to comment.