Skip to content

Commit df76c29

Browse files
committed
feat(elf_loader): Add ESP32-P4 support
1 parent 6f426e5 commit df76c29

File tree

24 files changed

+549
-127
lines changed

24 files changed

+549
-127
lines changed

.gitlab/ci/build.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,6 +1325,10 @@ build_example_elf_loader_elf_loader_example:
13251325
matrix:
13261326
- IMAGE: espressif/idf:release-v4.4
13271327
- IMAGE: espressif/idf:release-v5.0
1328+
- IMAGE: espressif/idf:release-v5.1
1329+
- IMAGE: espressif/idf:release-v5.2
1330+
- IMAGE: espressif/idf:release-v5.3
1331+
- IMAGE: espressif/idf:release-v5.4
13281332
EXAMPLE_CONFIG: "sdkconfig.ci=default"
13291333
variables:
13301334
EXAMPLE_DIR: examples/elf_loader/elf_loader_example
@@ -1337,6 +1341,9 @@ build_example_elf_loader_build_elf_file_example:
13371341
matrix:
13381342
- IMAGE: espressif/idf:release-v4.4
13391343
- IMAGE: espressif/idf:release-v5.0
1344+
- IMAGE: espressif/idf:release-v5.1
1345+
- IMAGE: espressif/idf:release-v5.2
1346+
- IMAGE: espressif/idf:release-v5.3
13401347
variables:
13411348
EXAMPLE_DIR: examples/elf_loader/build_elf_file_example
13421349

components/elf_loader/CMakeLists.txt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,22 @@ if(CONFIG_ELF_LOADER)
1111
if(CONFIG_IDF_TARGET_ESP32S2 AND (CONFIG_ELF_LOADER_LOAD_PSRAM))
1212
list(APPEND srcs "src/soc/esp_elf_esp32s2.c")
1313
endif()
14+
elseif(CONFIG_IDF_TARGET_ARCH_RISCV)
15+
list(APPEND srcs "src/arch/esp_elf_riscv.c")
1416
endif()
1517

1618
set(include_dirs "include")
1719
endif()
1820

21+
if(CONFIG_IDF_TARGET_ESP32P4)
22+
set(priv_req spi_flash esp_mm)
23+
else()
24+
set(priv_req spi_flash)
25+
endif()
26+
1927
idf_component_register(SRCS ${srcs}
2028
INCLUDE_DIRS ${include_dirs}
21-
PRIV_REQUIRES spi_flash)
29+
PRIV_REQUIRES spi_flash ${priv_req})
2230

2331
include(package_manager)
2432
if(CONFIG_ELF_LOADER)

components/elf_loader/Kconfig

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
menu "Espressif ELF Loader Configuration"
2-
visible if (IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3)
2+
visible if (IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4)
3+
4+
config ELF_LOADER_BUS_ADDRESS_MIRROR
5+
bool
6+
default y if (IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3)
7+
default n if IDF_TARGET_ESP32P4
38

49
config ELF_LOADER
510
bool "Enable Espressif ELF Loader"
611
default y
7-
depends on (IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3)
12+
depends on (IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4)
813
help
914
Select this option to enable ELF Loader and show the submenu with ELF Loader configuration choices.
1015

@@ -24,7 +29,7 @@ menu "Espressif ELF Loader Configuration"
2429
config ELF_LOADER_LOAD_PSRAM
2530
bool "Load ELF to PSRAM"
2631
default y
27-
depends on (IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3) && SPIRAM
32+
depends on (IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4) && SPIRAM
2833
select ELF_LOADER_CACHE_OFFSET if (IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3)
2934
select ELF_LOADER_SET_MMU if IDF_TARGET_ESP32S2
3035
help

components/elf_loader/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ This ELF loader supports following SoCs:
1111
- ESP32
1212
- ESP32-S2, support running ELF in PSRAM
1313
- ESP32-S3, support running ELF in PSRAM
14+
- ESP32-P4, support running ELF in PSRAM
1415

1516
### Usage
1617

components/elf_loader/elf_loader.cmake

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,18 @@ macro(project_elf project_name)
3535
# Remove more unused sections
3636
string(REPLACE "-elf-gcc" "-elf-strip" ${CMAKE_STRIP} ${CMAKE_C_COMPILER})
3737
set(strip_flags --strip-unneeded
38-
--remove-section=.xt.lit
39-
--remove-section=.xt.prop
4038
--remove-section=.comment
41-
--remove-section=.xtensa.info
4239
--remove-section=.got.loc
43-
--remove-section=.got)
40+
--remove-section=.got
41+
--remove-section=.dynamic)
42+
43+
if(CONFIG_IDF_TARGET_ARCH_XTENSA)
44+
list(APPEND strip_flags --remove-section=.xt.lit
45+
--remove-section=.xt.prop
46+
--remove-section=.xtensa.info)
47+
elseif(CONFIG_IDF_TARGET_ARCH_RISCV)
48+
list(APPEND strip_flags --remove-section=.riscv.attributes)
49+
endif()
4450

4551
# Link input list of libraries to ELF
4652
if(ELF_COMPONENTS)

components/elf_loader/include/esp_elf.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,16 @@ void esp_elf_deinit(esp_elf_t *elf);
6969
*
7070
* @return None
7171
*/
72-
void esp_elf_print_hdr(const uint8_t *pbuf);
72+
void esp_elf_print_ehdr(const uint8_t *pbuf);
73+
74+
/**
75+
* @brief Print program header description information of ELF.
76+
*
77+
* @param pbuf - ELF data buffer
78+
*
79+
* @return None
80+
*/
81+
void esp_elf_print_phdr(const uint8_t *pbuf);
7382

7483
/**
7584
* @brief Print section header description information of ELF.

components/elf_loader/include/private/elf_platform.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,10 @@
1212
extern "C" {
1313
#endif
1414

15-
#ifndef ELF_ALIGN_SIZE
16-
#define ELF_ALIGN_SIZE 4
17-
#endif
15+
/* Notes: align_size needs to be a power of 2 */
1816

19-
#define ELF_ALIGN(_a) (((_a) + (ELF_ALIGN_SIZE - 1)) & \
20-
(~(ELF_ALIGN_SIZE - 1)))
17+
#define ELF_ALIGN(_a, align_size) (((_a) + (align_size - 1)) & \
18+
~(align_size - 1))
2119

2220
/**
2321
* @brief Allocate block of memory.

components/elf_loader/include/private/elf_types.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,29 @@ extern "C" {
1818

1919
#define EI_NIDENT 16 /*!< Magic number and other information length */
2020

21+
/** @brief Type of segment */
22+
23+
#define PT_NULL 0 /*!< Program header table entry unused */
24+
#define PT_LOAD 1 /*!< Loadable program segment */
25+
#define PT_DYNAMIC 2 /*!< Dynamic linking information */
26+
#define PT_INTERP 3 /*!< Program interpreter */
27+
#define PT_NOTE 4 /*!< Auxiliary information */
28+
#define PT_SHLIB 5 /*!< Reserved */
29+
#define PT_PHDR 6 /*!< Entry for header table itself */
30+
#define PT_TLS 7 /*!< Thread-local storage segment */
31+
#define PT_NUM 8 /*!< Number of defined types */
32+
#define PT_LOOS 0x60000000 /*!< Start of OS-specific */
33+
#define PT_GNU_EH_FRAME 0x6474e550 /*!< GCC .eh_frame_hdr segment */
34+
#define PT_GNU_STACK 0x6474e551 /*!< Indicates stack executability */
35+
#define PT_GNU_RELRO 0x6474e552 /*!< Read-only after relocation */
36+
#define PT_LOSUNW 0x6ffffffa
37+
#define PT_SUNWBSS 0x6ffffffa /*!< Sun Specific segment */
38+
#define PT_SUNWSTACK 0x6ffffffb /*!< Stack segment */
39+
#define PT_HISUNW 0x6fffffff
40+
#define PT_HIOS 0x6fffffff /*!< End of OS-specific */
41+
#define PT_LOPROC 0x70000000 /*!< Start of processor-specific */
42+
#define PT_HIPROC 0x7fffffff /*!< End of processor-specific */
43+
2144
/** @brief Section Type */
2245

2346
#define SHT_NULL 0 /*!< invalid section header */
@@ -82,6 +105,8 @@ extern "C" {
82105
#define ELF_SYMTAB ".symtab" /*!< symbol table */
83106
#define ELF_TEXT ".text" /*!< code */
84107
#define ELF_DATA_REL_RO ".data.rel.ro" /*!< dynamic read-only data */
108+
#define ELF_PLT ".plt" /*!< procedure linkage table. */
109+
#define ELF_GOT_PLT ".got.plt" /*!< a table where resolved addresses from external functions are stored */
85110

86111
/** @brief ELF section and symbol operation */
87112

@@ -130,6 +155,19 @@ typedef struct elf32_hdr {
130155
Elf32_Half shstrndx; /*!< section header table's "section header string table" entry offset */
131156
} elf32_hdr_t;
132157

158+
/** @brief Program Header */
159+
160+
typedef struct elf32_phdr {
161+
Elf32_Word type; /* segment type */
162+
Elf32_Off offset; /* segment offset */
163+
Elf32_Addr vaddr; /* virtual address of segment */
164+
Elf32_Addr paddr; /* physical address - ignored? */
165+
Elf32_Word filesz; /* number of bytes in file for seg. */
166+
Elf32_Word memsz; /* number of bytes in mem. for seg. */
167+
Elf32_Word flags; /* flags */
168+
Elf32_Word align; /* memory alignment */
169+
} elf32_phdr_t;
170+
133171
/** @brief Section Header */
134172

135173
typedef struct elf32_shdr {
@@ -184,6 +222,10 @@ typedef struct esp_elf_sec {
184222
/** @brief ELF object */
185223

186224
typedef struct esp_elf {
225+
unsigned char *psegment; /*!< segment buffer pointer */
226+
227+
uint32_t svaddr; /*!< start virtual address of segment */
228+
187229
unsigned char *ptext; /*!< instruction buffer pointer */
188230

189231
unsigned char *pdata; /*!< data buffer pointer */
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <assert.h>
8+
#include <sys/errno.h>
9+
#include "esp_elf.h"
10+
#include "esp_log.h"
11+
#include "private/elf_platform.h"
12+
13+
/** @brief RISC-V relocations defined by the ABIs */
14+
15+
#define R_RISCV_NONE 0
16+
#define R_RISCV_32 1
17+
#define R_RISCV_64 2
18+
#define R_RISCV_RELATIVE 3
19+
#define R_RISCV_COPY 4
20+
#define R_RISCV_JUMP_SLOT 5
21+
#define R_RISCV_TLS_DTPMOD32 6
22+
#define R_RISCV_TLS_DTPMOD64 7
23+
#define R_RISCV_TLS_DTPREL32 8
24+
#define R_RISCV_TLS_DTPREL64 9
25+
#define R_RISCV_TLS_TPREL32 10
26+
#define R_RISCV_TLS_TPREL64 11
27+
#define R_RISCV_TLS_DESC 12
28+
#define R_RISCV_BRANCH 16
29+
#define R_RISCV_JAL 17
30+
#define R_RISCV_CALL 18
31+
#define R_RISCV_CALL_PLT 19
32+
#define R_RISCV_GOT_HI20 20
33+
#define R_RISCV_TLS_GOT_HI20 21
34+
#define R_RISCV_TLS_GD_HI20 22
35+
#define R_RISCV_PCREL_HI20 23
36+
#define R_RISCV_PCREL_LO12_I 24
37+
#define R_RISCV_PCREL_LO12_S 25
38+
#define R_RISCV_HI20 26
39+
#define R_RISCV_LO12_I 27
40+
#define R_RISCV_LO12_S 28
41+
#define R_RISCV_TPREL_HI20 29
42+
#define R_RISCV_TPREL_LO12_I 30
43+
#define R_RISCV_TPREL_LO12_S 31
44+
#define R_RISCV_TPREL_ADD 32
45+
#define R_RISCV_ADD8 33
46+
#define R_RISCV_ADD16 34
47+
#define R_RISCV_ADD32 35
48+
#define R_RISCV_ADD64 36
49+
#define R_RISCV_SUB8 37
50+
#define R_RISCV_SUB16 38
51+
#define R_RISCV_SUB32 39
52+
#define R_RISCV_SUB64 40
53+
#define R_RISCV_GNU_VTINHERIT 41
54+
#define R_RISCV_GNU_VTENTRY 42
55+
#define R_RISCV_ALIGN 43
56+
#define R_RISCV_RVC_BRANCH 44
57+
#define R_RISCV_RVC_JUMP 45
58+
#define R_RISCV_RVC_LUI 46
59+
#define R_RISCV_RELAX 51
60+
#define R_RISCV_SUB6 52
61+
#define R_RISCV_SET6 53
62+
#define R_RISCV_SET8 54
63+
#define R_RISCV_SET16 55
64+
#define R_RISCV_SET32 56
65+
#define R_RISCV_32_PCREL 57
66+
#define R_RISCV_IRELATIVE 58
67+
#define R_RISCV_PLT32 59
68+
69+
static const char *TAG = "elf_arch";
70+
71+
/**
72+
* @brief Relocates target architecture symbol of ELF
73+
*
74+
* @param elf - ELF object pointer
75+
* @param rela - Relocated symbol data
76+
* @param sym - ELF symbol table
77+
* @param addr - Jumping target address
78+
*
79+
* @return ESP_OK if success or other if failed.
80+
*/
81+
int esp_elf_arch_relocate(esp_elf_t *elf, const elf32_rela_t *rela,
82+
const elf32_sym_t *sym, uint32_t addr)
83+
{
84+
uint32_t *where;
85+
86+
assert(elf && rela);
87+
88+
where = (uint32_t *)((uint8_t *)elf->psegment + rela->offset + elf->svaddr);
89+
ESP_LOGD(TAG, "where=%p addr=0x%x offset=0x%x",
90+
where, (int)elf->psegment, (int)rela->offset);
91+
92+
/* Do relocation based on relocation type */
93+
94+
switch (ELF_R_TYPE(rela->info)) {
95+
case R_RISCV_NONE:
96+
break;
97+
case R_RISCV_32:
98+
*where = addr + rela->addend;
99+
break;
100+
case R_RISCV_RELATIVE:
101+
*where = (Elf32_Addr)((uint8_t *)elf->psegment - elf->svaddr + rela->addend);
102+
break;
103+
case R_RISCV_JUMP_SLOT:
104+
*where = addr;
105+
break;
106+
default:
107+
ESP_LOGE(TAG, "info=%d is not supported\n", ELF_R_TYPE(rela->info));
108+
return -EINVAL;
109+
}
110+
111+
return 0;
112+
}

components/elf_loader/src/arch/esp_elf_xtensa.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ int esp_elf_arch_relocate(esp_elf_t *elf, const elf32_rela_t *rela,
8282

8383
where = (uint32_t *)esp_elf_map_sym(elf, rela->offset);
8484

85-
ESP_LOGD(TAG, "where=%p addr=%x offset=%x\n", where, (int)addr, (int)rela->offset);
85+
ESP_LOGD(TAG, "where=%p addr=0x%x offset=0x%x\n",
86+
where, (int)addr, (int)rela->offset);
8687

8788
switch (ELF_R_TYPE(rela->info)) {
8889
case R_XTENSA_RELATIVE:

0 commit comments

Comments
 (0)