Updated elf_loader library to latest from GitHub (#234)

This commit is contained in:
Ken Van Hoeylandt 2025-02-22 23:57:45 +01:00 committed by GitHub
parent 6d1d08944b
commit bd2786b122
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
45 changed files with 641 additions and 483 deletions

View File

@ -1 +0,0 @@
ec9b5b8881cf5c38113ed7eab28a71ed7bfc9f477d6faef851f7f59f7a07b536

View File

@ -1,5 +1,11 @@
# ChangeLog # ChangeLog
## v1.0.0 - 2024-12-09
* Added support for the following RISC-V chips: ESP32-P4 and ESP32-C6
* Added support for linking other components to ELF file
* Fixed the issue of getting wrong symbol type
## v0.1.0 - 2023-08-14 ## v0.1.0 - 2023-08-14
* Add basic ELF loader component * Add basic ELF loader component

View File

@ -11,14 +11,24 @@ if(CONFIG_ELF_LOADER)
if(CONFIG_IDF_TARGET_ESP32S2 AND (CONFIG_ELF_LOADER_LOAD_PSRAM)) if(CONFIG_IDF_TARGET_ESP32S2 AND (CONFIG_ELF_LOADER_LOAD_PSRAM))
list(APPEND srcs "src/soc/esp_elf_esp32s2.c") list(APPEND srcs "src/soc/esp_elf_esp32s2.c")
endif() endif()
elseif(CONFIG_IDF_TARGET_ARCH_RISCV)
list(APPEND srcs "src/arch/esp_elf_riscv.c")
endif() endif()
set(include_dirs "include") set(include_dirs "include")
set(ldfragments "linker.lf")
endif()
if(CONFIG_IDF_TARGET_ESP32P4)
set(priv_req spi_flash esp_mm)
else()
set(priv_req spi_flash)
endif() endif()
idf_component_register(SRCS ${srcs} idf_component_register(SRCS ${srcs}
INCLUDE_DIRS ${include_dirs} INCLUDE_DIRS ${include_dirs}
PRIV_REQUIRES spi_flash) PRIV_REQUIRES spi_flash ${priv_req}
LDFRAGMENTS ${ldfragments})
include(package_manager) include(package_manager)
if(CONFIG_ELF_LOADER) if(CONFIG_ELF_LOADER)

View File

@ -1,10 +1,15 @@
menu "Espressif ELF Loader Configuration" menu "Espressif ELF Loader Configuration"
visible if (IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3) visible if (IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32P4)
config ELF_LOADER_BUS_ADDRESS_MIRROR
bool
default y if (IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3)
default n if (IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32P4)
config ELF_LOADER config ELF_LOADER
bool "Enable Espressif ELF Loader" bool "Enable Espressif ELF Loader"
default y default y
depends on (IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3) depends on (IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32P4)
help help
Select this option to enable ELF Loader and show the submenu with ELF Loader configuration choices. Select this option to enable ELF Loader and show the submenu with ELF Loader configuration choices.
@ -24,7 +29,7 @@ menu "Espressif ELF Loader Configuration"
config ELF_LOADER_LOAD_PSRAM config ELF_LOADER_LOAD_PSRAM
bool "Load ELF to PSRAM" bool "Load ELF to PSRAM"
default y default y
depends on (IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3) && SPIRAM depends on (IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4) && SPIRAM
select ELF_LOADER_CACHE_OFFSET if (IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3) select ELF_LOADER_CACHE_OFFSET if (IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3)
select ELF_LOADER_SET_MMU if IDF_TARGET_ESP32S2 select ELF_LOADER_SET_MMU if IDF_TARGET_ESP32S2
help help

View File

@ -11,6 +11,8 @@ This ELF loader supports following SoCs:
- ESP32 - ESP32
- ESP32-S2, support running ELF in PSRAM - ESP32-S2, support running ELF in PSRAM
- ESP32-S3, support running ELF in PSRAM - ESP32-S3, support running ELF in PSRAM
- ESP32-P4, support running ELF in PSRAM
- ESP32-C6
### Usage ### Usage
@ -20,7 +22,7 @@ Add a dependency on this component in your component or project's idf_component.
```yml ```yml
dependencies: dependencies:
espressif/elf_loader: "0.*" espressif/elf_loader: "1.*"
``` ```
Enable ELF loader in the menuconfig: Enable ELF loader in the menuconfig:

View File

@ -1,6 +1,6 @@
# The script is to generate ELF for application # 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 # Trick to temporarily redefine project(). When functions are overridden 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 # 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. # the original project(). See https://cmake.org/pipermail/cmake/2015-October/061751.html.
function(project_elf) function(project_elf)
@ -35,27 +35,35 @@ macro(project_elf project_name)
# Remove more unused sections # Remove more unused sections
string(REPLACE "-elf-gcc" "-elf-strip" ${CMAKE_STRIP} ${CMAKE_C_COMPILER}) string(REPLACE "-elf-gcc" "-elf-strip" ${CMAKE_STRIP} ${CMAKE_C_COMPILER})
set(strip_flags --strip-unneeded set(strip_flags --strip-unneeded
--remove-section=.xt.lit
--remove-section=.xt.prop
--remove-section=.comment --remove-section=.comment
--remove-section=.xtensa.info
--remove-section=.got.loc --remove-section=.got.loc
--remove-section=.got) --remove-section=.dynamic)
# Link input list of libraries to ELF if(CONFIG_IDF_TARGET_ARCH_XTENSA)
if(ELF_COMPONENTS) list(APPEND strip_flags --remove-section=.xt.lit
foreach(c "${ELF_COMPONENTS}") --remove-section=.xt.prop
set(elf_libs "${elf_libs}" "esp-idf/${c}/lib${c}.a") --remove-section=.xtensa.info)
endforeach() elseif(CONFIG_IDF_TARGET_ARCH_RISCV)
list(APPEND strip_flags --remove-section=.riscv.attributes)
endif() endif()
set(elf_libs ${elf_libs} "${ELF_LIBS}" "esp-idf/main/libmain.a") # Link input list of libraries to ELF
list(PREPEND ELF_COMPONENTS "main")
if(ELF_COMPONENTS)
foreach(c ${ELF_COMPONENTS})
list(APPEND elf_libs "esp-idf/${c}/lib${c}.a")
list(APPEND elf_dependeces "idf::${c}")
endforeach()
endif()
if (ELF_LIBS)
list(APPEND elf_libs "${ELF_LIBS}")
endif()
spaces2list(elf_libs) spaces2list(elf_libs)
add_custom_command(OUTPUT elf_app add_custom_command(OUTPUT elf_app
COMMAND ${CMAKE_C_COMPILER} ${cflags} ${elf_libs} -o ${elf_app} COMMAND ${CMAKE_C_COMPILER} ${cflags} ${elf_libs} -o ${elf_app}
COMMAND ${CMAKE_STRIP} ${strip_flags} ${elf_app} COMMAND ${CMAKE_STRIP} ${strip_flags} ${elf_app}
DEPENDS idf::main DEPENDS ${elf_dependeces}
COMMENT "Build ELF: ${elf_app}" COMMENT "Build ELF: ${elf_app}"
) )
add_custom_target(elf ALL DEPENDS elf_app) add_custom_target(elf ALL DEPENDS elf_app)

View File

@ -1,11 +0,0 @@
# For more information about build system see
# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(hello_world)
include(elf_loader)
project_elf(hello_world)

View File

@ -1,13 +0,0 @@
## Build ELF file Example
This example shows how to build ELF file.
## How to Use Example
Before project configuration and build, be sure to set the correct chip target using `idf.py set-target <chip_name>`.
* Note: Only ESP32, ESP32-S2 and ESP32-S3 are supported
### Build and Flash
Run `idf.py build` to build project, and when compiling is done you can see `hello_world.app.elf` in `build` directory.

View File

@ -1 +0,0 @@
idf_component_register(SRCS "main.c")

View File

@ -1,5 +0,0 @@
dependencies:
elf_loader:
version: "0.*"
override_path: "../../../../components/elf_loader"

View File

@ -1,28 +0,0 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <unistd.h>
char buffer[] = "hello world %d\n";
static int s_cnt;
int try_test(void)
{
for (int i = 0; i < 10; i++) {
printf(buffer, s_cnt++);
sleep(1);
}
return 0;
}
int main(int argc, char *argv[])
{
try_test();
return 0;
}

View File

@ -1 +0,0 @@
CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK=n

View File

@ -1,6 +0,0 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(elf-loader)

View File

@ -1,50 +0,0 @@
## ELF Loader Example
This example shows how to use ELF loader to run ELF file.
## How to Use Example
Before project configuration and build, be sure to set the correct chip target using `idf.py set-target <chip_name>`.
* Note: Only ESP32, ESP32-S2 and ESP32-S3 are supported
### Hardware Required
* A development board based on espressif ESP32/ESP32-S2/ESP32-S3 SoC
* A USB cable for power supply and programming
### Configure the Project
Open the project configuration menu (`idf.py menuconfig`).
In the `Example Configuration` menu:
* Enable ELF input arguments in the `Support arguments for ELF main` option if necessary.
* Set the arguments in the `Arguments of ELF main` option.
### Build and Flash
Run `idf.py -p PORT flash monitor` to build, flash and monitor the project.
(To exit the serial monitor, type ``Ctrl-]``.)
## Example Output
As you run the example, you will see the following log:
```
I (0) cpu_start: Starting scheduler on APP CPU.
I (382) elf_loader: Start to relocate ELF
I (392) elf_loader: Start to run ELF
hello world 0
hello world 1
hello world 2
hello world 3
hello world 4
hello world 5
hello world 6
hello world 7
hello world 8
hello world 9
I (10392) elf_loader: Success to exit from APP of ELF
```

View File

@ -1,3 +0,0 @@
idf_component_register(SRCS "elf_loader_example_main.c"
INCLUDE_DIRS ""
EMBED_TXTFILES "test.elf")

View File

@ -1,12 +0,0 @@
menu "ELF Loader Example Configuration"
config ELF_LOADER_MAIN_ARGS
bool "Support arguments for ELF main"
default n
config ELF_LOADER_MAIN_ARGS_STRING
string "Arguments of ELF main"
default "main"
depends on ELF_LOADER_MAIN_ARGS
endmenu

View File

@ -1,119 +0,0 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <stdlib.h>
#include <sys/errno.h>
#include "esp_log.h"
#include "esp_elf.h"
static const char *TAG = "elf_loader";
extern const uint8_t test_elf_start[] asm("_binary_test_elf_start");
extern const uint8_t test_elf_end[] asm("_binary_test_elf_end");
#ifdef CONFIG_ELF_LOADER_MAIN_ARGS
static int elf_args_decode(const char *str, int *argc, char ***argv)
{
int n;
char **argv_buf;
char *s;
char *pbuf;
int len;
s = (char *)str;
n = 1;
len = 1;
while (*s) {
if (*s++ == ' ') {
n++;
}
len++;
}
pbuf = malloc(n * sizeof(char *) + len);
if (!pbuf) {
return -ENOMEM;
}
argv_buf = (char **)pbuf;
s = pbuf + n * sizeof(char *);
memcpy(s, str, len);
for (int i = 0; i < n; i++) {
argv_buf[i] = s;
while (*s != ' ' || *s == 0) {
s++;
}
*s++ = 0;
}
*argc = n;
*argv = argv_buf;
return 0;
}
#endif
int app_main(void)
{
int ret;
int argc;
char **argv;
esp_elf_t elf;
const uint8_t *buffer = test_elf_start;
ESP_LOGI(TAG, "Start to relocate ELF file");
#ifdef CONFIG_ELF_LOADER_MAIN_ARGS
if (strlen(CONFIG_ELF_LOADER_MAIN_ARGS_STRING) <= 0) {
ESP_LOGE(TAG, "Failed to check arguments %s",
CONFIG_ELF_LOADER_MAIN_ARGS_STRING);
return -1;
}
ret = elf_args_decode(CONFIG_ELF_LOADER_MAIN_ARGS_STRING, &argc, &argv);
if (ret < 0) {
ESP_LOGE(TAG, "Failed to decode arguments %s errno=%d",
CONFIG_ELF_LOADER_MAIN_ARGS_STRING, ret);
return ret;
}
#else
argc = 0;
argv = NULL;
#endif
ret = esp_elf_init(&elf);
if (ret < 0) {
ESP_LOGE(TAG, "Failed to initialize ELF file errno=%d", ret);
return ret;
}
ret = esp_elf_relocate(&elf, buffer);
if (ret < 0) {
ESP_LOGE(TAG, "Failed to relocate ELF file errno=%d", ret);
return ret;
}
ESP_LOGI(TAG, "Start to run ELF file");
esp_elf_request(&elf, 0, argc, argv);
ESP_LOGI(TAG, "Success to exit from ELF file");
esp_elf_deinit(&elf);
#ifdef CONFIG_ELF_LOADER_MAIN_ARGS
if (argv) {
free(argv);
}
#endif
return 0;
}

View File

@ -1,5 +0,0 @@
dependencies:
elf_loader:
version: "0.*"
override_path: "../../../../components/elf_loader"

View File

@ -1,2 +0,0 @@
CONFIG_SPIRAM=y
CONFIG_ELF_LOADER_LOAD_PSRAM=y

View File

@ -1 +0,0 @@
CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=n

View File

@ -1 +0,0 @@
CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=n

View File

@ -1,8 +1,12 @@
dependencies: version: "1.0.0"
espressif/cmake_utilities:
version: 0.*
idf:
version: '>=4.4.3'
description: Espressif ELF(Executable and Linkable Format) Loader description: Espressif ELF(Executable and Linkable Format) Loader
url: https://github.com/espressif/esp-iot-solution/tree/master/components/elf_loader url: https://github.com/espressif/esp-iot-solution/tree/master/components/elf_loader
version: 0.1.0 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
sbom:
supplier: 'Organization: Espressif Systems (Shanghai) CO LTD'
originator: 'Organization: Espressif Systems (Shanghai) CO LTD'

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -27,7 +27,7 @@ uintptr_t esp_elf_map_sym(esp_elf_t *elf, uintptr_t sym);
* *
* @param elf - ELF object pointer * @param elf - ELF object pointer
* *
* @return ESP_OK if sucess or other if failed. * @return ESP_OK if success or other if failed.
*/ */
int esp_elf_init(esp_elf_t *elf); int esp_elf_init(esp_elf_t *elf);
@ -37,7 +37,7 @@ int esp_elf_init(esp_elf_t *elf);
* @param elf - ELF object pointer * @param elf - ELF object pointer
* @param pbuf - ELF data buffer * @param pbuf - ELF data buffer
* *
* @return ESP_OK if sucess or other if failed. * @return ESP_OK if success or other if failed.
*/ */
int esp_elf_relocate(esp_elf_t *elf, const uint8_t *pbuf); int esp_elf_relocate(esp_elf_t *elf, const uint8_t *pbuf);
@ -49,7 +49,7 @@ int esp_elf_relocate(esp_elf_t *elf, const uint8_t *pbuf);
* @param argc - Arguments number * @param argc - Arguments number
* @param argv - Arguments value array * @param argv - Arguments value array
* *
* @return ESP_OK if sucess or other if failed. * @return ESP_OK if success or other if failed.
*/ */
int esp_elf_request(esp_elf_t *elf, int opt, int argc, char *argv[]); int esp_elf_request(esp_elf_t *elf, int opt, int argc, char *argv[]);
@ -69,7 +69,16 @@ void esp_elf_deinit(esp_elf_t *elf);
* *
* @return None * @return None
*/ */
void esp_elf_print_hdr(const uint8_t *pbuf); void esp_elf_print_ehdr(const uint8_t *pbuf);
/**
* @brief Print program header description information of ELF.
*
* @param pbuf - ELF data buffer
*
* @return None
*/
void esp_elf_print_phdr(const uint8_t *pbuf);
/** /**
* @brief Print section header description information of ELF. * @brief Print section header description information of ELF.

View File

@ -12,12 +12,10 @@
extern "C" { extern "C" {
#endif #endif
#ifndef ELF_ALIGN_SIZE /* Notes: align_size needs to be a power of 2 */
#define ELF_ALIGN_SIZE 4
#endif
#define ELF_ALIGN(_a) (((_a) + (ELF_ALIGN_SIZE - 1)) & \ #define ELF_ALIGN(_a, align_size) (((_a) + (align_size - 1)) & \
(~(ELF_ALIGN_SIZE - 1))) ~(align_size - 1))
/** /**
* @brief Allocate block of memory. * @brief Allocate block of memory.
@ -46,7 +44,7 @@ void esp_elf_free(void *ptr);
* @param sym - ELF symbol table * @param sym - ELF symbol table
* @param addr - Jumping target address * @param addr - Jumping target address
* *
* @return ESP_OK if sucess or other if failed. * @return ESP_OK if success or other if failed.
*/ */
int esp_elf_arch_relocate(esp_elf_t *elf, const elf32_rela_t *rela, int esp_elf_arch_relocate(esp_elf_t *elf, const elf32_rela_t *rela,
const elf32_sym_t *sym, uint32_t addr); const elf32_sym_t *sym, uint32_t addr);

View File

@ -6,14 +6,15 @@
#pragma once #pragma once
#include "private/elf_types.h" #include <stdint.h>
#include "elf_symbol.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#define ESP_ELFSYM_EXPORT(_sym) { #_sym, (void*)&_sym } // Tactility custom -->
#define ESP_ELFSYM_EXPORT(_sym) { #_sym, (const void*)&_sym }
// <-- Tactility custom
#define ESP_ELFSYM_END { NULL, NULL } #define ESP_ELFSYM_END { NULL, NULL }
/** @brief Function symbol description */ /** @brief Function symbol description */
@ -32,9 +33,9 @@ struct esp_elfsym {
*/ */
uintptr_t elf_find_sym(const char *sym_name); uintptr_t elf_find_sym(const char *sym_name);
#ifdef CONFIG_ELF_LOADER_CUSTOMER_SYMBOLS // Tactility custom -->
void elf_set_custom_symbols(const struct esp_elfsym* symbols); void elf_set_custom_symbols(const struct esp_elfsym* symbols);
#endif // <-- Tactility custom
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -18,6 +18,29 @@ extern "C" {
#define EI_NIDENT 16 /*!< Magic number and other information length */ #define EI_NIDENT 16 /*!< Magic number and other information length */
/** @brief Type of segment */
#define PT_NULL 0 /*!< Program header table entry unused */
#define PT_LOAD 1 /*!< Loadable program segment */
#define PT_DYNAMIC 2 /*!< Dynamic linking information */
#define PT_INTERP 3 /*!< Program interpreter */
#define PT_NOTE 4 /*!< Auxiliary information */
#define PT_SHLIB 5 /*!< Reserved */
#define PT_PHDR 6 /*!< Entry for header table itself */
#define PT_TLS 7 /*!< Thread-local storage segment */
#define PT_NUM 8 /*!< Number of defined types */
#define PT_LOOS 0x60000000 /*!< Start of OS-specific */
#define PT_GNU_EH_FRAME 0x6474e550 /*!< GCC .eh_frame_hdr segment */
#define PT_GNU_STACK 0x6474e551 /*!< Indicates stack executability */
#define PT_GNU_RELRO 0x6474e552 /*!< Read-only after relocation */
#define PT_LOSUNW 0x6ffffffa
#define PT_SUNWBSS 0x6ffffffa /*!< Sun Specific segment */
#define PT_SUNWSTACK 0x6ffffffb /*!< Stack segment */
#define PT_HISUNW 0x6fffffff
#define PT_HIOS 0x6fffffff /*!< End of OS-specific */
#define PT_LOPROC 0x70000000 /*!< Start of processor-specific */
#define PT_HIPROC 0x7fffffff /*!< End of processor-specific */
/** @brief Section Type */ /** @brief Section Type */
#define SHT_NULL 0 /*!< invalid section header */ #define SHT_NULL 0 /*!< invalid section header */
@ -82,6 +105,8 @@ extern "C" {
#define ELF_SYMTAB ".symtab" /*!< symbol table */ #define ELF_SYMTAB ".symtab" /*!< symbol table */
#define ELF_TEXT ".text" /*!< code */ #define ELF_TEXT ".text" /*!< code */
#define ELF_DATA_REL_RO ".data.rel.ro" /*!< dynamic read-only data */ #define ELF_DATA_REL_RO ".data.rel.ro" /*!< dynamic read-only data */
#define ELF_PLT ".plt" /*!< procedure linkage table. */
#define ELF_GOT_PLT ".got.plt" /*!< a table where resolved addresses from external functions are stored */
/** @brief ELF section and symbol operation */ /** @brief ELF section and symbol operation */
@ -130,6 +155,19 @@ typedef struct elf32_hdr {
Elf32_Half shstrndx; /*!< section header table's "section header string table" entry offset */ Elf32_Half shstrndx; /*!< section header table's "section header string table" entry offset */
} elf32_hdr_t; } elf32_hdr_t;
/** @brief Program Header */
typedef struct elf32_phdr {
Elf32_Word type; /* segment type */
Elf32_Off offset; /* segment offset */
Elf32_Addr vaddr; /* virtual address of segment */
Elf32_Addr paddr; /* physical address - ignored? */
Elf32_Word filesz; /* number of bytes in file for seg. */
Elf32_Word memsz; /* number of bytes in mem. for seg. */
Elf32_Word flags; /* flags */
Elf32_Word align; /* memory alignment */
} elf32_phdr_t;
/** @brief Section Header */ /** @brief Section Header */
typedef struct elf32_shdr { typedef struct elf32_shdr {
@ -184,6 +222,10 @@ typedef struct esp_elf_sec {
/** @brief ELF object */ /** @brief ELF object */
typedef struct esp_elf { typedef struct esp_elf {
unsigned char *psegment; /*!< segment buffer pointer */
uint32_t svaddr; /*!< start virtual address of segment */
unsigned char *ptext; /*!< instruction buffer pointer */ unsigned char *ptext; /*!< instruction buffer pointer */
unsigned char *pdata; /*!< data buffer pointer */ unsigned char *pdata; /*!< data buffer pointer */

View File

@ -0,0 +1,14 @@
[sections:elf_loader_got_plt]
entries:
.got.plt
.got
[scheme:elf_loader_default]
entries:
elf_loader_got_plt -> flash_rodata
[mapping:elf_loader]
archive: *
entries:
* (elf_loader_default);
elf_loader_got_plt -> flash_rodata KEEP() SURROUND(_esp_elf_loader_got_plt)

View File

@ -0,0 +1,112 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <assert.h>
#include <sys/errno.h>
#include "esp_elf.h"
#include "esp_log.h"
#include "private/elf_platform.h"
/** @brief RISC-V relocations defined by the ABIs */
#define R_RISCV_NONE 0
#define R_RISCV_32 1
#define R_RISCV_64 2
#define R_RISCV_RELATIVE 3
#define R_RISCV_COPY 4
#define R_RISCV_JUMP_SLOT 5
#define R_RISCV_TLS_DTPMOD32 6
#define R_RISCV_TLS_DTPMOD64 7
#define R_RISCV_TLS_DTPREL32 8
#define R_RISCV_TLS_DTPREL64 9
#define R_RISCV_TLS_TPREL32 10
#define R_RISCV_TLS_TPREL64 11
#define R_RISCV_TLS_DESC 12
#define R_RISCV_BRANCH 16
#define R_RISCV_JAL 17
#define R_RISCV_CALL 18
#define R_RISCV_CALL_PLT 19
#define R_RISCV_GOT_HI20 20
#define R_RISCV_TLS_GOT_HI20 21
#define R_RISCV_TLS_GD_HI20 22
#define R_RISCV_PCREL_HI20 23
#define R_RISCV_PCREL_LO12_I 24
#define R_RISCV_PCREL_LO12_S 25
#define R_RISCV_HI20 26
#define R_RISCV_LO12_I 27
#define R_RISCV_LO12_S 28
#define R_RISCV_TPREL_HI20 29
#define R_RISCV_TPREL_LO12_I 30
#define R_RISCV_TPREL_LO12_S 31
#define R_RISCV_TPREL_ADD 32
#define R_RISCV_ADD8 33
#define R_RISCV_ADD16 34
#define R_RISCV_ADD32 35
#define R_RISCV_ADD64 36
#define R_RISCV_SUB8 37
#define R_RISCV_SUB16 38
#define R_RISCV_SUB32 39
#define R_RISCV_SUB64 40
#define R_RISCV_GNU_VTINHERIT 41
#define R_RISCV_GNU_VTENTRY 42
#define R_RISCV_ALIGN 43
#define R_RISCV_RVC_BRANCH 44
#define R_RISCV_RVC_JUMP 45
#define R_RISCV_RVC_LUI 46
#define R_RISCV_RELAX 51
#define R_RISCV_SUB6 52
#define R_RISCV_SET6 53
#define R_RISCV_SET8 54
#define R_RISCV_SET16 55
#define R_RISCV_SET32 56
#define R_RISCV_32_PCREL 57
#define R_RISCV_IRELATIVE 58
#define R_RISCV_PLT32 59
static const char *TAG = "elf_arch";
/**
* @brief Relocates target architecture symbol of ELF
*
* @param elf - ELF object pointer
* @param rela - Relocated symbol data
* @param sym - ELF symbol table
* @param addr - Jumping target address
*
* @return ESP_OK if success or other if failed.
*/
int esp_elf_arch_relocate(esp_elf_t *elf, const elf32_rela_t *rela,
const elf32_sym_t *sym, uint32_t addr)
{
uint32_t *where;
assert(elf && rela);
where = (uint32_t *)((uint8_t *)elf->psegment + rela->offset + elf->svaddr);
ESP_LOGD(TAG, "type: %d, where=%p addr=0x%x offset=0x%x",
ELF_R_TYPE(rela->info), where, (int)elf->psegment, (int)rela->offset);
/* Do relocation based on relocation type */
switch (ELF_R_TYPE(rela->info)) {
case R_RISCV_NONE:
break;
case R_RISCV_32:
*where = addr + rela->addend;
break;
case R_RISCV_RELATIVE:
*where = (Elf32_Addr)((uint8_t *)elf->psegment - elf->svaddr + rela->addend);
break;
case R_RISCV_JUMP_SLOT:
*where = addr;
break;
default:
ESP_LOGE(TAG, "info=%d is not supported\n", ELF_R_TYPE(rela->info));
return -EINVAL;
}
return 0;
}

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -70,7 +70,7 @@ static const char *TAG = "elf_arch";
* @param sym - ELF symbol table * @param sym - ELF symbol table
* @param addr - Jumping target address * @param addr - Jumping target address
* *
* @return ESP_OK if sucess or other if failed. * @return ESP_OK if success or other if failed.
*/ */
int esp_elf_arch_relocate(esp_elf_t *elf, const elf32_rela_t *rela, int esp_elf_arch_relocate(esp_elf_t *elf, const elf32_rela_t *rela,
const elf32_sym_t *sym, uint32_t addr) const elf32_sym_t *sym, uint32_t addr)
@ -82,7 +82,8 @@ int esp_elf_arch_relocate(esp_elf_t *elf, const elf32_rela_t *rela,
where = (uint32_t *)esp_elf_map_sym(elf, rela->offset); where = (uint32_t *)esp_elf_map_sym(elf, rela->offset);
ESP_LOGD(TAG, "where=%p addr=%x offset=%x\n", where, (int)addr, (int)rela->offset); ESP_LOGD(TAG, "type: %d, where=%p addr=0x%x offset=0x%x\n",
ELF_R_TYPE(rela->info), where, (int)addr, (int)rela->offset);
switch (ELF_R_TYPE(rela->info)) { switch (ELF_R_TYPE(rela->info)) {
case R_XTENSA_RELATIVE: case R_XTENSA_RELATIVE:

View File

@ -1,149 +1,111 @@
/* /*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/errno.h> #include <sys/errno.h>
#include <sys/param.h> #include <sys/param.h>
#include "esp_log.h" #include "esp_log.h"
#include "soc/soc_caps.h"
#include "elf_symbol.h" #if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
#include "hal/cache_ll.h"
#endif
#include "private/elf_symbol.h"
#include "private/elf_platform.h" #include "private/elf_platform.h"
#define stype(_s, _t) ((_s)->type == (_t)) #define stype(_s, _t) ((_s)->type == (_t))
#define sflags(_s, _f) (((_s)->flags & (_f)) == (_f)) #define sflags(_s, _f) (((_s)->flags & (_f)) == (_f))
#define ADDR_OFFSET (0x400)
static const char *TAG = "ELF"; static const char *TAG = "ELF";
/** #if CONFIG_ELF_LOADER_BUS_ADDRESS_MIRROR
* @brief Map symbol's address of ELF to physic space.
*
* @param elf - ELF object pointer
* @param sym - ELF symbol address
*
* @return ESP_OK if sucess or other if failed.
*/
uintptr_t esp_elf_map_sym(esp_elf_t *elf, uintptr_t sym)
{
for (int i = 0; i < ELF_SECS; i++) {
if ((sym >= elf->sec[i].v_addr) &&
(sym < (elf->sec[i].v_addr + elf->sec[i].size))) {
return sym - elf->sec[i].v_addr + elf->sec[i].addr;
}
}
return 0;
}
/** /**
* @brief Initialize ELF object. * @brief Load ELF section.
*
* @param elf - ELF object pointer
*
* @return ESP_OK if sucess or other if failed.
*/
int esp_elf_init(esp_elf_t *elf)
{
ESP_LOGI(TAG, "ELF loader version: %d.%d.%d", ELF_LOADER_VER_MAJOR, ELF_LOADER_VER_MINOR, ELF_LOADER_VER_PATCH);
if (!elf) {
return -EINVAL;
}
memset(elf, 0, sizeof(esp_elf_t));
return 0;
}
/**
* @brief Decode and relocate ELF data.
* *
* @param elf - ELF object pointer * @param elf - ELF object pointer
* @param pbuf - ELF data buffer * @param pbuf - ELF data buffer
* *
* @return ESP_OK if sucess or other if failed. * @return ESP_OK if success or other if failed.
*/ */
int esp_elf_relocate(esp_elf_t *elf, const uint8_t *pbuf)
static int esp_elf_load_section(esp_elf_t *elf, const uint8_t *pbuf)
{ {
uint32_t entry; uint32_t entry;
uint32_t size; uint32_t size;
const elf32_hdr_t *phdr; const elf32_hdr_t *ehdr = (const elf32_hdr_t *)pbuf;
const elf32_shdr_t *pshdr; const elf32_shdr_t *shdr = (const elf32_shdr_t *)(pbuf + ehdr->shoff);
const char *shstrab; const char *shstrab = (const char *)pbuf + shdr[ehdr->shstrndx].offset;
if (!elf || !pbuf) {
return -EINVAL;
}
phdr = (const elf32_hdr_t *)pbuf;
pshdr = (const elf32_shdr_t *)(pbuf + phdr->shoff);
shstrab = (const char *)pbuf + pshdr[phdr->shstrndx].offset;
/* Calculate ELF image size */ /* Calculate ELF image size */
for (uint32_t i = 0; i < phdr->shnum; i++) { for (uint32_t i = 0; i < ehdr->shnum; i++) {
const char *name = shstrab + pshdr[i].name; const char *name = shstrab + shdr[i].name;
if (stype(&pshdr[i], SHT_PROGBITS) && sflags(&pshdr[i], SHF_ALLOC)) { if (stype(&shdr[i], SHT_PROGBITS) && sflags(&shdr[i], SHF_ALLOC)) {
if (sflags(&pshdr[i], SHF_EXECINSTR) && !strcmp(ELF_TEXT, name)) { if (sflags(&shdr[i], SHF_EXECINSTR) && !strcmp(ELF_TEXT, name)) {
ESP_LOGD(TAG, ".text sec addr=0x%08x size=0x%08x offset=0x%08x", ESP_LOGD(TAG, ".text sec addr=0x%08x size=0x%08x offset=0x%08x",
pshdr[i].addr, pshdr[i].size, pshdr[i].offset); shdr[i].addr, shdr[i].size, shdr[i].offset);
elf->sec[ELF_SEC_TEXT].v_addr = pshdr[i].addr; elf->sec[ELF_SEC_TEXT].v_addr = shdr[i].addr;
elf->sec[ELF_SEC_TEXT].size = ELF_ALIGN(pshdr[i].size); elf->sec[ELF_SEC_TEXT].size = ELF_ALIGN(shdr[i].size, 4);
elf->sec[ELF_SEC_TEXT].offset = pshdr[i].offset; elf->sec[ELF_SEC_TEXT].offset = shdr[i].offset;
ESP_LOGD(TAG, ".text offset is 0x%lx size is 0x%x", ESP_LOGD(TAG, ".text offset is 0x%lx size is 0x%x",
elf->sec[ELF_SEC_TEXT].offset, elf->sec[ELF_SEC_TEXT].offset,
elf->sec[ELF_SEC_TEXT].size); elf->sec[ELF_SEC_TEXT].size);
} else if (sflags(&pshdr[i], SHF_WRITE) && !strcmp(ELF_DATA, name)) { } else if (sflags(&shdr[i], SHF_WRITE) && !strcmp(ELF_DATA, name)) {
ESP_LOGD(TAG, ".data sec addr=0x%08x size=0x%08x offset=0x%08x", ESP_LOGD(TAG, ".data sec addr=0x%08x size=0x%08x offset=0x%08x",
pshdr[i].addr, pshdr[i].size, pshdr[i].offset); shdr[i].addr, shdr[i].size, shdr[i].offset);
elf->sec[ELF_SEC_DATA].v_addr = pshdr[i].addr; elf->sec[ELF_SEC_DATA].v_addr = shdr[i].addr;
elf->sec[ELF_SEC_DATA].size = pshdr[i].size; elf->sec[ELF_SEC_DATA].size = shdr[i].size;
elf->sec[ELF_SEC_DATA].offset = pshdr[i].offset; elf->sec[ELF_SEC_DATA].offset = shdr[i].offset;
ESP_LOGD(TAG, ".data offset is 0x%lx size is 0x%x", ESP_LOGD(TAG, ".data offset is 0x%lx size is 0x%x",
elf->sec[ELF_SEC_DATA].offset, elf->sec[ELF_SEC_DATA].offset,
elf->sec[ELF_SEC_DATA].size); elf->sec[ELF_SEC_DATA].size);
} else if (!strcmp(ELF_RODATA, name)) { } else if (!strcmp(ELF_RODATA, name)) {
ESP_LOGD(TAG, ".rodata sec addr=0x%08x size=0x%08x offset=0x%08x", ESP_LOGD(TAG, ".rodata sec addr=0x%08x size=0x%08x offset=0x%08x",
pshdr[i].addr, pshdr[i].size, pshdr[i].offset); shdr[i].addr, shdr[i].size, shdr[i].offset);
elf->sec[ELF_SEC_RODATA].v_addr = pshdr[i].addr; elf->sec[ELF_SEC_RODATA].v_addr = shdr[i].addr;
elf->sec[ELF_SEC_RODATA].size = pshdr[i].size; elf->sec[ELF_SEC_RODATA].size = shdr[i].size;
elf->sec[ELF_SEC_RODATA].offset = pshdr[i].offset; elf->sec[ELF_SEC_RODATA].offset = shdr[i].offset;
ESP_LOGD(TAG, ".rodata offset is 0x%lx size is 0x%x", ESP_LOGD(TAG, ".rodata offset is 0x%lx size is 0x%x",
elf->sec[ELF_SEC_RODATA].offset, elf->sec[ELF_SEC_RODATA].offset,
elf->sec[ELF_SEC_RODATA].size); elf->sec[ELF_SEC_RODATA].size);
} else if (!strcmp(ELF_DATA_REL_RO, name)) { } else if (!strcmp(ELF_DATA_REL_RO, name)) {
ESP_LOGD(TAG, ".data.rel.ro sec addr=0x%08x size=0x%08x offset=0x%08x", ESP_LOGD(TAG, ".data.rel.ro sec addr=0x%08x size=0x%08x offset=0x%08x",
pshdr[i].addr, pshdr[i].size, pshdr[i].offset); shdr[i].addr, shdr[i].size, shdr[i].offset);
elf->sec[ELF_SEC_DRLRO].v_addr = pshdr[i].addr; elf->sec[ELF_SEC_DRLRO].v_addr = shdr[i].addr;
elf->sec[ELF_SEC_DRLRO].size = pshdr[i].size; elf->sec[ELF_SEC_DRLRO].size = shdr[i].size;
elf->sec[ELF_SEC_DRLRO].offset = pshdr[i].offset; elf->sec[ELF_SEC_DRLRO].offset = shdr[i].offset;
ESP_LOGD(TAG, ".data.rel.ro offset is 0x%lx size is 0x%x", ESP_LOGD(TAG, ".data.rel.ro offset is 0x%lx size is 0x%x",
elf->sec[ELF_SEC_DRLRO].offset, elf->sec[ELF_SEC_DRLRO].offset,
elf->sec[ELF_SEC_DRLRO].size); elf->sec[ELF_SEC_DRLRO].size);
} }
} else if (stype(&pshdr[i], SHT_NOBITS) && } else if (stype(&shdr[i], SHT_NOBITS) &&
sflags(&pshdr[i], SHF_ALLOC | SHF_WRITE) && sflags(&shdr[i], SHF_ALLOC | SHF_WRITE) &&
!strcmp(ELF_BSS, name)) { !strcmp(ELF_BSS, name)) {
ESP_LOGD(TAG, ".bss sec addr=0x%08x size=0x%08x offset=0x%08x", ESP_LOGD(TAG, ".bss sec addr=0x%08x size=0x%08x offset=0x%08x",
pshdr[i].addr, pshdr[i].size, pshdr[i].offset); shdr[i].addr, shdr[i].size, shdr[i].offset);
elf->sec[ELF_SEC_BSS].v_addr = pshdr[i].addr; elf->sec[ELF_SEC_BSS].v_addr = shdr[i].addr;
elf->sec[ELF_SEC_BSS].size = pshdr[i].size; elf->sec[ELF_SEC_BSS].size = shdr[i].size;
elf->sec[ELF_SEC_BSS].offset = pshdr[i].offset; elf->sec[ELF_SEC_BSS].offset = shdr[i].offset;
ESP_LOGD(TAG, ".bss offset is 0x%lx size is 0x%x", ESP_LOGD(TAG, ".bss offset is 0x%lx size is 0x%x",
elf->sec[ELF_SEC_BSS].offset, elf->sec[ELF_SEC_BSS].offset,
@ -174,7 +136,7 @@ int esp_elf_relocate(esp_elf_t *elf, const uint8_t *pbuf)
} }
} }
/* Dump ".text" from ELF to excutable space memory */ /* Dump ".text" from ELF to executable space memory */
elf->sec[ELF_SEC_TEXT].addr = (Elf32_Addr)elf->ptext; elf->sec[ELF_SEC_TEXT].addr = (Elf32_Addr)elf->ptext;
memcpy(elf->ptext, pbuf + elf->sec[ELF_SEC_TEXT].offset, memcpy(elf->ptext, pbuf + elf->sec[ELF_SEC_TEXT].offset,
@ -183,6 +145,7 @@ int esp_elf_relocate(esp_elf_t *elf, const uint8_t *pbuf)
#ifdef CONFIG_ELF_LOADER_SET_MMU #ifdef CONFIG_ELF_LOADER_SET_MMU
if (esp_elf_arch_init_mmu(elf)) { if (esp_elf_arch_init_mmu(elf)) {
esp_elf_free(elf->ptext); esp_elf_free(elf->ptext);
esp_elf_free(elf->pdata);
return -EIO; return -EIO;
} }
#endif #endif
@ -231,7 +194,7 @@ int esp_elf_relocate(esp_elf_t *elf, const uint8_t *pbuf)
/* Set ELF entry */ /* Set ELF entry */
entry = phdr->entry + elf->sec[ELF_SEC_TEXT].addr - entry = ehdr->entry + elf->sec[ELF_SEC_TEXT].addr -
elf->sec[ELF_SEC_TEXT].v_addr; elf->sec[ELF_SEC_TEXT].v_addr;
#ifdef CONFIG_ELF_LOADER_CACHE_OFFSET #ifdef CONFIG_ELF_LOADER_CACHE_OFFSET
@ -240,21 +203,203 @@ int esp_elf_relocate(esp_elf_t *elf, const uint8_t *pbuf)
elf->entry = (void *)entry; elf->entry = (void *)entry;
#endif #endif
return 0;
}
#else
/**
* @brief Load ELF segment.
*
* @param elf - ELF object pointer
* @param pbuf - ELF data buffer
*
* @return ESP_OK if success or other if failed.
*/
static int esp_elf_load_segment(esp_elf_t *elf, const uint8_t *pbuf)
{
uint32_t size;
bool first_segment = false;
Elf32_Addr vaddr_s = 0;
Elf32_Addr vaddr_e = 0;
const elf32_hdr_t *ehdr = (const elf32_hdr_t *)pbuf;
const elf32_phdr_t *phdr = (const elf32_phdr_t *)(pbuf + ehdr->phoff);
for (int i = 0; i < ehdr->phnum; i++) {
if (phdr[i].type != PT_LOAD) {
continue;
}
if (phdr[i].memsz < phdr[i].filesz) {
ESP_LOGE(TAG, "Invalid segment[%d], memsz: %d, filesz: %d",
i, phdr[i].memsz, phdr[i].filesz);
return -EINVAL;
}
if (first_segment == true) {
vaddr_s = phdr[i].vaddr;
vaddr_e = phdr[i].vaddr + phdr[i].memsz;
first_segment = true;
if (vaddr_e < vaddr_s) {
ESP_LOGE(TAG, "Invalid segment[%d], vaddr: 0x%x, memsz: %d",
i, phdr[i].vaddr, phdr[i].memsz);
return -EINVAL;
}
} else {
if (phdr[i].vaddr < vaddr_e) {
ESP_LOGE(TAG, "Invalid segment[%d], should not overlap, vaddr: 0x%x, vaddr_e: 0x%x\n",
i, phdr[i].vaddr, vaddr_e);
return -EINVAL;
}
if (phdr[i].vaddr > vaddr_e + ADDR_OFFSET) {
ESP_LOGI(TAG, "Too much padding before segment[%d], padding: %d",
i, phdr[i].vaddr - vaddr_e);
}
vaddr_e = phdr[i].vaddr + phdr[i].memsz;
if (vaddr_e < phdr[i].vaddr) {
ESP_LOGE(TAG, "Invalid segment[%d], address overflow, vaddr: 0x%x, vaddr_e: 0x%x\n",
i, phdr[i].vaddr, vaddr_e);
return -EINVAL;
}
}
ESP_LOGD(TAG, "LOAD segment[%d], vaddr: 0x%x, memsize: 0x%08x",
i, phdr[i].vaddr, phdr[i].memsz);
}
size = vaddr_e - vaddr_s;
if (size == 0) {
return -EINVAL;
}
elf->svaddr = vaddr_s;
elf->psegment = esp_elf_malloc(size, true);
if (!elf->psegment) {
return -ENOMEM;
}
memset(elf->psegment, 0, size);
/* Dump "PT_LOAD" from ELF to memory space */
for (int i = 0; i < ehdr->phnum; i++) {
if (phdr[i].type == PT_LOAD) {
memcpy(elf->psegment + phdr[i].vaddr - vaddr_s,
(uint8_t *)pbuf + phdr[i].offset, phdr[i].filesz);
ESP_LOGD(TAG, "Copy segment[%d], mem_addr: 0x%x, vaddr: 0x%x, size: 0x%08x",
i, (int)((uint8_t *)elf->psegment + phdr[i].vaddr - vaddr_s),
phdr[i].vaddr, phdr[i].filesz);
}
}
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
cache_ll_writeback_all(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA, CACHE_LL_ID_ALL);
#endif
elf->entry = (void *)((uint8_t *)elf->psegment + ehdr->entry - vaddr_s);
return 0;
}
#endif
/**
* @brief Map symbol's address of ELF to physic space.
*
* @param elf - ELF object pointer
* @param sym - ELF symbol address
*
* @return ESP_OK if success or other if failed.
*/
uintptr_t esp_elf_map_sym(esp_elf_t *elf, uintptr_t sym)
{
for (int i = 0; i < ELF_SECS; i++) {
if ((sym >= elf->sec[i].v_addr) &&
(sym < (elf->sec[i].v_addr + elf->sec[i].size))) {
return sym - elf->sec[i].v_addr + elf->sec[i].addr;
}
}
return 0;
}
/**
* @brief Initialize ELF object.
*
* @param elf - ELF object pointer
*
* @return ESP_OK if success or other if failed.
*/
int esp_elf_init(esp_elf_t *elf)
{
ESP_LOGI(TAG, "ELF loader version: %d.%d.%d", ELF_LOADER_VER_MAJOR, ELF_LOADER_VER_MINOR, ELF_LOADER_VER_PATCH);
if (!elf) {
return -EINVAL;
}
memset(elf, 0, sizeof(esp_elf_t));
return 0;
}
/**
* @brief Decode and relocate ELF data.
*
* @param elf - ELF object pointer
* @param pbuf - ELF data buffer
*
* @return ESP_OK if success or other if failed.
*/
int esp_elf_relocate(esp_elf_t *elf, const uint8_t *pbuf)
{
int ret;
const elf32_hdr_t *ehdr;
const elf32_shdr_t *shdr;
const char *shstrab;
if (!elf || !pbuf) {
return -EINVAL;
}
ehdr = (const elf32_hdr_t *)pbuf;
shdr = (const elf32_shdr_t *)(pbuf + ehdr->shoff);
shstrab = (const char *)pbuf + shdr[ehdr->shstrndx].offset;
/* Load section or segment to memory space */
#if CONFIG_ELF_LOADER_BUS_ADDRESS_MIRROR
ret = esp_elf_load_section(elf, pbuf);
#else
ret = esp_elf_load_segment(elf, pbuf);
#endif
if (ret) {
ESP_LOGE(TAG, "Error to load elf file, ret=%d", ret);
return ret;
}
ESP_LOGI(TAG, "elf->entry=%p\n", elf->entry);
/* Relocation section data */ /* Relocation section data */
for (uint32_t i = 0; i < phdr->shnum; i++) { for (uint32_t i = 0; i < ehdr->shnum; i++) {
if (stype(&pshdr[i], SHT_RELA)) { if (stype(&shdr[i], SHT_RELA)) {
uint32_t nr_reloc; uint32_t nr_reloc;
const elf32_rela_t *rela; const elf32_rela_t *rela;
const elf32_sym_t *symtab; const elf32_sym_t *symtab;
const char *strtab; const char *strtab;
nr_reloc = pshdr[i].size / sizeof(elf32_rela_t); nr_reloc = shdr[i].size / sizeof(elf32_rela_t);
rela = (const elf32_rela_t *)(pbuf + pshdr[i].offset); rela = (const elf32_rela_t *)(pbuf + shdr[i].offset);
symtab = (const elf32_sym_t *)(pbuf + pshdr[pshdr[i].link].offset); symtab = (const elf32_sym_t *)(pbuf + shdr[shdr[i].link].offset);
strtab = (const char *)(pbuf + pshdr[pshdr[pshdr[i].link].link].offset); strtab = (const char *)(pbuf + shdr[shdr[shdr[i].link].link].offset);
ESP_LOGD(TAG, "Section %s has %d symbol tables", shstrab + pshdr[i].name, (int)nr_reloc); ESP_LOGD(TAG, "Section %s has %d symbol tables", shstrab + shdr[i].name, (int)nr_reloc);
for (int i = 0; i < nr_reloc; i++) { for (int i = 0; i < nr_reloc; i++) {
int type; int type;
@ -265,8 +410,8 @@ int esp_elf_relocate(esp_elf_t *elf, const uint8_t *pbuf)
const elf32_sym_t *sym = &symtab[ELF_R_SYM(rela_buf.info)]; const elf32_sym_t *sym = &symtab[ELF_R_SYM(rela_buf.info)];
type = ELF_R_TYPE(rela->info); type = ELF_R_TYPE(rela_buf.info);
if (type == STT_COMMON) { if (type == STT_COMMON || type == STT_OBJECT || type == STT_SECTION) {
const char *comm_name = strtab + sym->name; const char *comm_name = strtab + sym->name;
if (comm_name[0]) { if (comm_name[0]) {
@ -274,8 +419,12 @@ int esp_elf_relocate(esp_elf_t *elf, const uint8_t *pbuf)
if (!addr) { if (!addr) {
ESP_LOGE(TAG, "Can't find common %s", strtab + sym->name); ESP_LOGE(TAG, "Can't find common %s", strtab + sym->name);
#if CONFIG_ELF_LOADER_BUS_ADDRESS_MIRROR
esp_elf_free(elf->pdata); esp_elf_free(elf->pdata);
esp_elf_free(elf->ptext); esp_elf_free(elf->ptext);
#else
esp_elf_free(elf->psegment);
#endif
return -ENOSYS; return -ENOSYS;
} }
@ -292,8 +441,12 @@ int esp_elf_relocate(esp_elf_t *elf, const uint8_t *pbuf)
if (!addr) { if (!addr) {
ESP_LOGE(TAG, "Can't find symbol %s", func_name); ESP_LOGE(TAG, "Can't find symbol %s", func_name);
#if CONFIG_ELF_LOADER_BUS_ADDRESS_MIRROR
esp_elf_free(elf->pdata); esp_elf_free(elf->pdata);
esp_elf_free(elf->ptext); esp_elf_free(elf->ptext);
#else
esp_elf_free(elf->psegment);
#endif
return -ENOSYS; return -ENOSYS;
} }
@ -320,10 +473,14 @@ int esp_elf_relocate(esp_elf_t *elf, const uint8_t *pbuf)
* @param argc - Arguments number * @param argc - Arguments number
* @param argv - Arguments value array * @param argv - Arguments value array
* *
* @return ESP_OK if sucess or other if failed. * @return ESP_OK if success or other if failed.
*/ */
int esp_elf_request(esp_elf_t *elf, int opt, int argc, char *argv[]) int esp_elf_request(esp_elf_t *elf, int opt, int argc, char *argv[])
{ {
if (!elf || !(elf->entry)) {
return -EINVAL;
}
elf->entry(argc, argv); elf->entry(argc, argv);
return 0; return 0;
@ -338,6 +495,7 @@ int esp_elf_request(esp_elf_t *elf, int opt, int argc, char *argv[])
*/ */
void esp_elf_deinit(esp_elf_t *elf) void esp_elf_deinit(esp_elf_t *elf)
{ {
#if CONFIG_ELF_LOADER_BUS_ADDRESS_MIRROR
if (elf->pdata) { if (elf->pdata) {
esp_elf_free(elf->pdata); esp_elf_free(elf->pdata);
elf->pdata = NULL; elf->pdata = NULL;
@ -347,6 +505,12 @@ void esp_elf_deinit(esp_elf_t *elf)
esp_elf_free(elf->ptext); esp_elf_free(elf->ptext);
elf->ptext = NULL; elf->ptext = NULL;
} }
#else
if (elf->psegment) {
esp_elf_free(elf->ptext);
elf->ptext = NULL;
}
#endif
#ifdef CONFIG_ELF_LOADER_SET_MMU #ifdef CONFIG_ELF_LOADER_SET_MMU
esp_elf_arch_deinit_mmu(elf); esp_elf_arch_deinit_mmu(elf);
@ -360,7 +524,7 @@ void esp_elf_deinit(esp_elf_t *elf)
* *
* @return None * @return None
*/ */
void esp_elf_print_hdr(const uint8_t *pbuf) void esp_elf_print_ehdr(const uint8_t *pbuf)
{ {
const char *s_bits, *s_endian; const char *s_bits, *s_endian;
const elf32_hdr_t *hdr = (const elf32_hdr_t *)pbuf; const elf32_hdr_t *hdr = (const elf32_hdr_t *)pbuf;
@ -411,6 +575,32 @@ void esp_elf_print_hdr(const uint8_t *pbuf)
ESP_LOGI(TAG, "%-40s %d", "Section header string table i:", hdr->shstrndx); ESP_LOGI(TAG, "%-40s %d", "Section header string table i:", hdr->shstrndx);
} }
/**
* @brief Print program header description information of ELF.
*
* @param pbuf - ELF data buffer
*
* @return None
*/
void esp_elf_print_phdr(const uint8_t *pbuf)
{
const elf32_hdr_t *ehdr = (const elf32_hdr_t *)pbuf;
const elf32_phdr_t *phdr = (const elf32_phdr_t *)((size_t)pbuf + ehdr->phoff);
for (int i = 0; i < ehdr->phnum; i++) {
ESP_LOGI(TAG, "%-40s %d", "type:", phdr->type);
ESP_LOGI(TAG, "%-40s 0x%x", "offset:", phdr->offset);
ESP_LOGI(TAG, "%-40s 0x%x", "vaddr", phdr->vaddr);
ESP_LOGI(TAG, "%-40s 0x%x", "paddr:", phdr->paddr);
ESP_LOGI(TAG, "%-40s %d", "filesz", phdr->filesz);
ESP_LOGI(TAG, "%-40s %d", "memsz", phdr->memsz);
ESP_LOGI(TAG, "%-40s %d", "flags", phdr->flags);
ESP_LOGI(TAG, "%-40s 0x%x", "align", phdr->align);
phdr = (const elf32_phdr_t *)((size_t)phdr + sizeof(elf32_phdr_t));
}
}
/** /**
* @brief Print section header description information of ELF. * @brief Print section header description information of ELF.
* *
@ -420,21 +610,21 @@ void esp_elf_print_hdr(const uint8_t *pbuf)
*/ */
void esp_elf_print_shdr(const uint8_t *pbuf) void esp_elf_print_shdr(const uint8_t *pbuf)
{ {
const elf32_hdr_t *phdr = (const elf32_hdr_t *)pbuf; const elf32_hdr_t *ehdr = (const elf32_hdr_t *)pbuf;
const elf32_shdr_t *pshdr = (const elf32_shdr_t *)((size_t)pbuf + phdr->shoff); const elf32_shdr_t *shdr = (const elf32_shdr_t *)((size_t)pbuf + ehdr->shoff);
for (int i = 0; i < phdr->shnum; i++) { for (int i = 0; i < ehdr->shnum; i++) {
ESP_LOGI(TAG, "%-40s %d", "name:", pshdr->name); ESP_LOGI(TAG, "%-40s %d", "name:", shdr->name);
ESP_LOGI(TAG, "%-40s %d", "type:", pshdr->type); ESP_LOGI(TAG, "%-40s %d", "type:", shdr->type);
ESP_LOGI(TAG, "%-40s 0x%x", "flags:", pshdr->flags); ESP_LOGI(TAG, "%-40s 0x%x", "flags:", shdr->flags);
ESP_LOGI(TAG, "%-40s %x", "addr", pshdr->addr); ESP_LOGI(TAG, "%-40s %x", "addr", shdr->addr);
ESP_LOGI(TAG, "%-40s %x", "offset:", pshdr->offset); ESP_LOGI(TAG, "%-40s %x", "offset:", shdr->offset);
ESP_LOGI(TAG, "%-40s %d", "size", pshdr->size); ESP_LOGI(TAG, "%-40s %d", "size", shdr->size);
ESP_LOGI(TAG, "%-40s 0x%x", "link", pshdr->link); ESP_LOGI(TAG, "%-40s 0x%x", "link", shdr->link);
ESP_LOGI(TAG, "%-40s %d", "addralign", pshdr->addralign); ESP_LOGI(TAG, "%-40s %d", "addralign", shdr->addralign);
ESP_LOGI(TAG, "%-40s %d", "entsize", pshdr->entsize); ESP_LOGI(TAG, "%-40s %d", "entsize", shdr->entsize);
pshdr = (const elf32_shdr_t *)((size_t)pshdr + sizeof(elf32_shdr_t)); shdr = (const elf32_shdr_t *)((size_t)shdr + sizeof(elf32_shdr_t));
} }
} }

View File

@ -28,10 +28,23 @@
*/ */
void *esp_elf_malloc(uint32_t n, bool exec) void *esp_elf_malloc(uint32_t n, bool exec)
{ {
uint32_t caps;
#if CONFIG_ELF_LOADER_BUS_ADDRESS_MIRROR
#ifdef CONFIG_ELF_LOADER_LOAD_PSRAM #ifdef CONFIG_ELF_LOADER_LOAD_PSRAM
uint32_t caps = MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT; caps = MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT;
#else #else
uint32_t caps = exec ? MALLOC_CAP_EXEC : MALLOC_CAP_8BIT; caps = exec ? MALLOC_CAP_EXEC : MALLOC_CAP_8BIT;
#endif
#else
#ifdef CONFIG_ELF_LOADER_LOAD_PSRAM
caps = MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT;
#else
caps = MALLOC_CAP_8BIT;
#endif
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0)
caps |= MALLOC_CAP_CACHE_ALIGNED;
#endif
#endif #endif
return heap_caps_malloc(n, caps); return heap_caps_malloc(n, caps);
@ -105,4 +118,3 @@ void IRAM_ATTR esp_elf_arch_flush(void)
spi_flash_enable_interrupts_caches_and_other_cpu(); spi_flash_enable_interrupts_caches_and_other_cpu();
} }
#endif #endif

View File

@ -19,8 +19,7 @@
#include "rom/ets_sys.h" #include "rom/ets_sys.h"
#include "elf_symbol.h" #include "private/elf_symbol.h"
extern int __ltdf2(double a, double b); extern int __ltdf2(double a, double b);
extern unsigned int __fixunsdfsi(double a); extern unsigned int __fixunsdfsi(double a);
@ -28,6 +27,13 @@ extern int __gtdf2 (double a, double b);
extern double __floatunsidf(unsigned int i); extern double __floatunsidf(unsigned int i);
extern double __divdf3(double a, double b); extern double __divdf3(double a, double b);
// Tactility custom -->
static const struct esp_elfsym* custom_symbols = NULL;
void elf_set_custom_symbols(const struct esp_elfsym* symbols) {
custom_symbols = symbols;
}
// <-- Tactility custom
/** @brief Libc public functions symbols look-up table */ /** @brief Libc public functions symbols look-up table */
static const struct esp_elfsym g_esp_libc_elfsyms[] = { static const struct esp_elfsym g_esp_libc_elfsyms[] = {
@ -150,14 +156,6 @@ static const struct esp_elfsym g_esp_espidf_elfsyms[] = {
ESP_ELFSYM_END ESP_ELFSYM_END
}; };
#ifdef CONFIG_ELF_LOADER_CUSTOMER_SYMBOLS
static const struct esp_elfsym* custom_symbols = NULL;
void elf_set_custom_symbols(const struct esp_elfsym* symbols) {
custom_symbols = symbols;
}
#endif
/** /**
* @brief Find symbol address by name. * @brief Find symbol address by name.
* *
@ -198,8 +196,9 @@ uintptr_t elf_find_sym(const char *sym_name)
#endif #endif
#ifdef CONFIG_ELF_LOADER_CUSTOMER_SYMBOLS #ifdef CONFIG_ELF_LOADER_CUSTOMER_SYMBOLS
syms = custom_symbols; extern const struct esp_elfsym g_customer_elfsyms[];
if (syms != NULL) {
syms = g_customer_elfsyms;
while (syms->name) { while (syms->name) {
if (!strcmp(syms->name, sym_name)) { if (!strcmp(syms->name, sym_name)) {
return (uintptr_t)syms->sym; return (uintptr_t)syms->sym;
@ -207,10 +206,18 @@ uintptr_t elf_find_sym(const char *sym_name)
syms++; syms++;
} }
#endif
// Tactility custom -->
syms = custom_symbols;
while (syms->name) {
if (!strcmp(syms->name, sym_name)) {
return (uintptr_t)syms->sym;
} }
#endif syms++;
}
// <-- Tactility custom
return 0; return 0;
} }

View File

@ -26,6 +26,12 @@
#define MMU_UNIT_SIZE 0x10000 #define MMU_UNIT_SIZE 0x10000
#define MMU_REG ((volatile uint32_t *)DR_REG_MMU_TABLE) #define MMU_REG ((volatile uint32_t *)DR_REG_MMU_TABLE)
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0)
#define IRAM0_ADDRESS_LOW SOC_IRAM0_ADDRESS_LOW
#define IRAM0_ADDRESS_HIGH SOC_IRAM0_ADDRESS_HIGH
#define MMU_ACCESS_SPIRAM SOC_MMU_ACCESS_SPIRAM
#endif
#define ESP_MMU_IBUS_BASE IRAM0_ADDRESS_LOW #define ESP_MMU_IBUS_BASE IRAM0_ADDRESS_LOW
#define ESP_MMU_IBUS_MAX ((IRAM0_ADDRESS_HIGH - IRAM0_ADDRESS_LOW) / \ #define ESP_MMU_IBUS_MAX ((IRAM0_ADDRESS_HIGH - IRAM0_ADDRESS_LOW) / \
MMU_UNIT_SIZE) MMU_UNIT_SIZE)

View File

@ -1,7 +1,5 @@
#ifdef ESP_PLATFORM #ifdef ESP_PLATFORM
#include "elf_symbol.h"
#include "tt_app.h" #include "tt_app.h"
#include "tt_app_alertdialog.h" #include "tt_app_alertdialog.h"
#include "tt_app_manifest.h" #include "tt_app_manifest.h"
@ -16,6 +14,8 @@
#include "tt_thread.h" #include "tt_thread.h"
#include "tt_timer.h" #include "tt_timer.h"
#include <private/elf_symbol.h>
#include <lvgl.h> #include <lvgl.h>
extern "C" { extern "C" {

View File

@ -24,7 +24,6 @@ CONFIG_FREERTOS_USE_TRACE_FACILITY=y
CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
CONFIG_ELF_LOADER_CUSTOMER_SYMBOLS=y
CONFIG_FATFS_LFN_HEAP=y CONFIG_FATFS_LFN_HEAP=y
CONFIG_FATFS_VOLUME_COUNT=3 CONFIG_FATFS_VOLUME_COUNT=3

View File

@ -24,7 +24,6 @@ CONFIG_FREERTOS_USE_TRACE_FACILITY=y
CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
CONFIG_ELF_LOADER_CUSTOMER_SYMBOLS=y
CONFIG_FATFS_LFN_HEAP=y CONFIG_FATFS_LFN_HEAP=y
CONFIG_FATFS_VOLUME_COUNT=3 CONFIG_FATFS_VOLUME_COUNT=3

View File

@ -24,7 +24,6 @@ CONFIG_FREERTOS_USE_TRACE_FACILITY=y
CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
CONFIG_ELF_LOADER_CUSTOMER_SYMBOLS=y
CONFIG_FATFS_LFN_HEAP=y CONFIG_FATFS_LFN_HEAP=y
CONFIG_FATFS_VOLUME_COUNT=3 CONFIG_FATFS_VOLUME_COUNT=3

View File

@ -24,7 +24,6 @@ CONFIG_FREERTOS_USE_TRACE_FACILITY=y
CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
CONFIG_ELF_LOADER_CUSTOMER_SYMBOLS=y
CONFIG_FATFS_LFN_HEAP=y CONFIG_FATFS_LFN_HEAP=y
CONFIG_FATFS_VOLUME_COUNT=3 CONFIG_FATFS_VOLUME_COUNT=3

View File

@ -24,7 +24,6 @@ CONFIG_FREERTOS_USE_TRACE_FACILITY=y
CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
CONFIG_ELF_LOADER_CUSTOMER_SYMBOLS=y
CONFIG_FATFS_LFN_HEAP=y CONFIG_FATFS_LFN_HEAP=y
CONFIG_FATFS_VOLUME_COUNT=3 CONFIG_FATFS_VOLUME_COUNT=3

View File

@ -24,7 +24,6 @@ CONFIG_FREERTOS_USE_TRACE_FACILITY=y
CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
CONFIG_ELF_LOADER_CUSTOMER_SYMBOLS=y
CONFIG_FATFS_LFN_HEAP=y CONFIG_FATFS_LFN_HEAP=y
CONFIG_FATFS_VOLUME_COUNT=3 CONFIG_FATFS_VOLUME_COUNT=3

View File

@ -24,7 +24,6 @@ CONFIG_FREERTOS_USE_TRACE_FACILITY=y
CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
CONFIG_ELF_LOADER_CUSTOMER_SYMBOLS=y
CONFIG_FATFS_LFN_HEAP=y CONFIG_FATFS_LFN_HEAP=y
CONFIG_FATFS_VOLUME_COUNT=3 CONFIG_FATFS_VOLUME_COUNT=3

View File

@ -24,7 +24,6 @@ CONFIG_FREERTOS_USE_TRACE_FACILITY=y
CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
CONFIG_ELF_LOADER_CUSTOMER_SYMBOLS=y
CONFIG_FATFS_LFN_HEAP=y CONFIG_FATFS_LFN_HEAP=y
CONFIG_FATFS_VOLUME_COUNT=3 CONFIG_FATFS_VOLUME_COUNT=3

View File

@ -24,7 +24,6 @@ CONFIG_FREERTOS_USE_TRACE_FACILITY=y
CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
CONFIG_ELF_LOADER_CUSTOMER_SYMBOLS=y
CONFIG_FATFS_LFN_HEAP=y CONFIG_FATFS_LFN_HEAP=y
CONFIG_FATFS_VOLUME_COUNT=3 CONFIG_FATFS_VOLUME_COUNT=3

View File

@ -24,7 +24,6 @@ CONFIG_FREERTOS_USE_TRACE_FACILITY=y
CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
CONFIG_ELF_LOADER_CUSTOMER_SYMBOLS=y
CONFIG_FATFS_LFN_HEAP=y CONFIG_FATFS_LFN_HEAP=y
CONFIG_FATFS_VOLUME_COUNT=3 CONFIG_FATFS_VOLUME_COUNT=3