Compare commits

...

4 Commits
master ... fdma

Author SHA1 Message Date
imi415 650049d060
Updated FDMA related files. 2022-09-04 19:43:35 +08:00
imi415 029f336438
Updated FDMA structs. 2022-08-14 12:47:48 +08:00
imi415 d82bb3fb7e
Added FDMA firmware and try to enable FDMA0 (not successful). 2022-08-12 09:36:54 +08:00
imi415 3d407c43f2
Play with FDMA. 2022-08-11 23:54:50 +08:00
10 changed files with 2918 additions and 70 deletions

12
.clang-format Normal file
View File

@ -0,0 +1,12 @@
BasedOnStyle: Google
IndentWidth: 4
AlignConsecutiveMacros: Consecutive
AlignConsecutiveDeclarations: true
AlignConsecutiveAssignments: true
AllowShortFunctionsOnASingleLine: false
BreakBeforeBraces: Custom
BraceWrapping:
AfterEnum: false
AfterStruct: false
SplitEmptyFunction: false
ColumnLimit: 120

View File

@ -10,6 +10,7 @@ set(TARGET_SOURCES
"src/main.c"
"src/stx7105_exc.c"
"src/stx7105_utils.c"
"src/stx7105_fdma_fw.c"
"src/syscalls.c"
"startup_stx7105.S"
)

View File

@ -129,46 +129,92 @@ typedef struct {
__IO uint32_t BDMRB; /* Offset: 0x2001C, Break data mask register B */
__IO uint16_t BRCR; /* Offset: 0x20020, Break control register */
uint8_t UNUSED9[2]; /* Offset: 0x20022 */
} CSR_TypeDef;
} CSP_TypeDef;
/* drivers/stm/stx7105.c */
typedef struct {
__IO uint32_t SLIM_ID; /* Offset: 0x0000, SLIM CPU ID register */
__IO uint32_t SLIM_VER; /* Offset: 0x0004, SLIM CPU version register */
__IO uint32_t SLIM_EN; /* Offset: 0x0008, SLIM CPU enable control register */
__IO uint32_t SLIM_CLK_GATE; /* Offset: 0x000C, SLIM CPU clock gate register */
__IO uint32_t SLIM_ID; /* Offset: 0x0000, SLIM CPU ID register */
__IO uint32_t SLIM_VER; /* Offset: 0x0004, SLIM CPU version register */
__IO uint32_t SLIM_EN; /* Offset: 0x0008, SLIM CPU enable control register */
__IO uint32_t SLIM_CLK_GATE; /* Offset: 0x000C, SLIM CPU clock gate register */
uint32_t UNUSED0[8188]; /* Offset: 0x0010 */
__IO uint8_t SLIM_DMEM[8192]; /* Offset: 0x8000, SLIM CPU data memory */
uint32_t UNUSED1[2018]; /* Offset: 0xA000 */
__IO uint32_t PERIPH_STBUS_SYNC; /* Offset: 0xBF88, STBus sync control register */
uint32_t UNUSED2[13]; /* Offset: 0xBF8C */
__IO uint32_t PERIPH_CMD_STA; /* Offset: 0xBFC0, Command mailbox */
__IO uint32_t PERIPH_CMD_SET; /* Offset: 0xBFC4, Command mailbox */
__IO uint32_t PERIPH_CMD_CLR; /* Offset: 0xBFC8, Command mailbox */
__IO uint32_t PERIPH_CMD_MASK; /* Offset: 0xBFCC, Command mailbox */
__IO uint32_t PERIPH_INT_STA; /* Offset: 0xBFD0, Interrupt mailbox */
__IO uint32_t PERIPH_INT_SET; /* Offset: 0xBFD4, Interrupt mailbox */
__IO uint32_t PERIPH_INT_CLR; /* Offset: 0xBFD8, Interrupt mailbox */
__IO uint32_t PERIPH_INT_MASK; /* Offset: 0xBFDC, Interrupt mailbox */
uint32_t UNUSED3[8]; /* Offset: 0xBFE0 */
__IO uint8_t SLIM_IMEM[16384]; /* Offset: 0xC000, SLIM CPU instruction memory */
} FDMA_TypeDef;
#define PIO0_BASE (0xFD020000U)
#define PIO1_BASE (0xFD021000U)
#define PIO2_BASE (0xFD022000U)
#define PIO3_BASE (0xFD023000U)
#define PIO4_BASE (0xFD024000U)
#define PIO5_BASE (0xFD025000U)
#define PIO6_BASE (0xFD026000U)
#define ASC0_BASE (0xFD030000U)
#define ASC1_BASE (0xFD031000U)
#define ASC2_BASE (0xFD032000U)
#define ASC3_BASE (0xFD033000U)
#define FDMA0_BASE (0xFE220000U)
#define CSR_BASE (0xFF000000U)
#define INTC_BASE (0xFFD00000U)
#define TMU_BASE (0xFFD80000U)
/* WARNING: THE CLKGENA is different from other ST40s' */
typedef struct {
__IO uint32_t PLL0_CFG; /* Offset: 0x0000 */
__IO uint32_t PLL1_CFG; /* Offset: 0x0004 */
uint32_t UNUSED0[2]; /* Offset: 0x0008 */
__IO uint32_t POWER_CFG; /* Offset: 0x0010 */
__IO uint32_t CLKOPSRC_SWITCH_CFG; /* Offset: 0x0014 */
uint32_t UNUSED1[4]; /* Offset: 0x0018 */
__IO uint32_t CLKOPSRC_SWITCH_CFG2; /* Offset: 0x0024 */
uint32_t UNUSED2[2]; /* Offset: 0x0028 */
__IO uint32_t CLKOBS_MUX1_CFG; /* Offset: 0x0030 */
__IO uint32_t CLKOBS_MASTER_MAXCOUNT; /* Offset: 0x0034 */
__IO uint32_t CLKOBS_CMD; /* Offset: 0x0038 */
__IO uint32_t CLKOBS_STATUS; /* Offset: 0x003C */
__IO uint32_t CLKOBS_SLAVE0_COUNT; /* Offset: 0x0040 */
__IO uint32_t OSCMUX_DEBUG; /* Offset: 0x0044 */
__IO uint32_t CLKOBS_MUX2_CFG; /* Offset: 0x0048 */
__IO uint32_t LOW_POWER_CTRL; /* Offset: 0x004C */
} CKGA_TypeDef;
#define PIO0 ((PIO_TypeDef *)PIO0_BASE)
#define PIO1 ((PIO_TypeDef *)PIO1_BASE)
#define PIO2 ((PIO_TypeDef *)PIO2_BASE)
#define PIO3 ((PIO_TypeDef *)PIO3_BASE)
#define PIO4 ((PIO_TypeDef *)PIO4_BASE)
#define PIO5 ((PIO_TypeDef *)PIO5_BASE)
#define PIO6 ((PIO_TypeDef *)PIO6_BASE)
#define ASC0 ((ASC_TypeDef *)ASC0_BASE)
#define ASC1 ((ASC_TypeDef *)ASC1_BASE)
#define ASC2 ((ASC_TypeDef *)ASC2_BASE)
#define ASC3 ((ASC_TypeDef *)ASC3_BASE)
#define CSR ((CSR_TypeDef *)CSR_BASE)
#define PIO0_BASE (0xFD020000U)
#define PIO1_BASE (0xFD021000U)
#define PIO2_BASE (0xFD022000U)
#define PIO3_BASE (0xFD023000U)
#define PIO4_BASE (0xFD024000U)
#define PIO5_BASE (0xFD025000U)
#define PIO6_BASE (0xFD026000U)
#define ASC0_BASE (0xFD030000U)
#define ASC1_BASE (0xFD031000U)
#define ASC2_BASE (0xFD032000U)
#define ASC3_BASE (0xFD033000U)
#define CKGA_BASE (0xFE213000U)
#define FDMA0_BASE (0xFE220000U)
#define FDMA1_BASE (0xFE410000U)
#define CSP_BASE (0xFF000000U)
#define INTC_BASE (0xFFD00000U)
#define TMU_BASE (0xFFD80000U)
#define PIO0 ((PIO_TypeDef *)PIO0_BASE)
#define PIO1 ((PIO_TypeDef *)PIO1_BASE)
#define PIO2 ((PIO_TypeDef *)PIO2_BASE)
#define PIO3 ((PIO_TypeDef *)PIO3_BASE)
#define PIO4 ((PIO_TypeDef *)PIO4_BASE)
#define PIO5 ((PIO_TypeDef *)PIO5_BASE)
#define PIO6 ((PIO_TypeDef *)PIO6_BASE)
#define ASC0 ((ASC_TypeDef *)ASC0_BASE)
#define ASC1 ((ASC_TypeDef *)ASC1_BASE)
#define ASC2 ((ASC_TypeDef *)ASC2_BASE)
#define ASC3 ((ASC_TypeDef *)ASC3_BASE)
#define CKGA ((CKGA_TypeDef *)CKGA_BASE)
#define FDMA0 ((FDMA_TypeDef *)FDMA0_BASE)
#define INTC ((INTC_TypeDef *)INTC_BASE)
#define TMU ((TMU_TypeDef *)TMU_BASE)
#define FDMA1 ((FDMA_TypeDef *)FDMA1_BASE)
#define CSP ((CSP_TypeDef *)CSP_BASE)
#define INTC ((INTC_TypeDef *)INTC_BASE)
#define TMU ((TMU_TypeDef *)TMU_BASE)
#define TMU_TSTR_STR0_Pos 0
#define TMU_TSTR_STR0_Msk (1U << TMU_TSTR_STR0_Pos)
@ -188,4 +234,16 @@ typedef struct {
#define INTC_IPRA_IPR_TMU0_Pos 12
#define INTC_IPRA_IPR_TMU0_Msk (0x0FU << INTC_IPRA_IPR_TMU0_Pos)
#define FDMA_SLIM_EN_RUN_Pos 0
#define FDMA_SLIM_EN_RUN_Msk (1U << FDMA_SLIM_EN_RUN_Pos)
#define FDMA_SLIM_CLK_GATE_DIS_Pos 0
#define FDMA_SLIM_CLK_GATE_DIS_Msk (1U << FDMA_SLIM_CLK_GATE_DIS_Pos)
#define FDMA_SLIM_CLK_GATE_RESET_Pos 2
#define FDMA_SLIM_CLK_GATE_RESET_Msk (1U << FDMA_SLIM_CLK_GATE_RESET_Pos)
#define FDMA_PERIPH_STBUS_SYNC_DIS_Pos 0
#define FDMA_PERIPH_STBUS_SYNC_DIS_Msk (1U << FDMA_PERIPH_STBUS_SYNC_DIS_Pos)
#endif

69
include/stx7105_fdma.h Normal file
View File

@ -0,0 +1,69 @@
#ifndef STX7105_FDMA_H
#define STX7105_FDMA_H
#include "stx7105.h"
typedef enum {
FDMA_CMD_START_CHANNEL = 1U,
FDMA_CMD_PAUSE_CHANNEL = 2U,
FDMA_CMD_FLUSH_CHANNEL = 3U,
} FDMA_Command_TypeDef;
typedef enum {
FDMA_STAT_CHANNEL_IDLE = 0U,
FDMA_STAT_CHANNEL_RUNNING = 2U,
FDMA_STAT_CHANNEL_PAUSED = 3U,
} FDMA_Status_TypeDef;
typedef enum {
FDMA_REQ_CTL_OP_LDST1 = 0U,
FDMA_REQ_CTL_OP_LDST2 = 1U,
FDMA_REQ_CTL_OP_LDST4 = 2U,
FDMA_REQ_CTL_OP_LDST8 = 3U,
FDMA_REQ_CTL_OP_LDST16 = 4U,
FDMA_REQ_CTL_OP_LDST32 = 5U,
} FDMA_ReqCtl_Opcode_TypeDef;
typedef struct {
__IO uint32_t NEXT; /* Offset: 0x0000, Next node in the list */
__IO uint32_t CTRL; /* Offset: 0x0004, Control register */
__IO uint32_t NBYTES; /* Offset: 0x0008, Number of bytes */
__IO uint32_t SADDR; /* Offset: 0x000C, Source address */
__IO uint32_t DADDR; /* Offset: 0x0010, Destination address */
__IO uint32_t LENGTH; /* Offset: 0x0014, Burst length */
__IO uint32_t S_STRIDE; /* Offset: 0x0018, Source stride */
__IO uint32_t D_STRIDE; /* Offset: 0x001C, Destination stride */
} FDMA_FwRegs_Channel_TypeDef;
/* Firmware regs, implemented on the base of DMEM */
typedef struct {
__IO uint32_t REVID; /* Offset: 0x8000 */
uint32_t UNUSED0[1103]; /* Offset: 0x8004 */
__IO uint32_t CMD_STAT[16]; /* Offset: 0x9140 */
__IO uint32_t REQ_CTRL[16]; /* Offset: 0x9180 */
uint32_t UNUSED1[240]; /* Offset: 0x91C0 */
FDMA_FwRegs_Channel_TypeDef CHANNEL[16]; /* Offset: 0x9580 */
} FDMA_FWRegs_TypeDef;
#define FDMA_FwRegs_REQ_CTLN_HOLDOFF_Pos 0U
#define FDMA_FwRegs_REQ_CTLN_HOLDOFF_
#define FDMA_FwRegs_REQ_CTLN_OPCODE_Pos 4U
#define FDMA_FwRegs_REQ_CTLN_OPCODE_Msk (0x0FU << FDMA_FwRegs_REQ_CTLN_OPCODE_Pos)
#define FDMA_FwRegs_REQ_CTLN_WNR_Pos 14U
#define FDMA_FwRegs_REQ_CTLN_WNR_Msk (1U << FDMA_FwRegs_REQ_CTLN_INC_ADDR_Pos)
#define FDMA_FwRegs_REQ_CTLN_DATA_SWAP_Pos 17U
#define FDMA_FwRegs_REQ_CTLN_DATA_SWAP_Msk (1U << FDMA_FwRegs_REQ_CTLN_INC_ADDR_Pos)
#define FDMA_FwRegs_REQ_CTLN_INC_ADDR_Pos 21U
#define FDMA_FwRegs_REQ_CTLN_INC_ADDR_Msk (1U << FDMA_FwRegs_REQ_CTLN_INC_ADDR_Pos)
#define FDMA_FwRegs_REQ_CTLN_INITIATOR_Pos 22U
#define FDMA_FwRegs_REQ_CTLN_INITIATOR_Msk (1U << FDMA_FwRegs_REQ_CTLN_INITIATOR_Pos)
#define FDMA_FwRegs_REQ_CTLN_NUM_OPS_Pos 24U
#define FDMA_FwRegs_REQ_CTLN_NUM_OPS_Msk (0xFFU << FDMA_FwRegs_REQ_CTLN_INC_ADDR_Pos)
#endif

17
include/stx7105_fdma_fw.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef STX7105_FDMA_FW_H
#define STX7105_FDMA_FW_H
#include <stdint.h>
typedef struct {
uint32_t entry_point;
uint32_t text_size;
uint32_t data_size;
uint8_t *text;
uint8_t *data;
} stx7105_fdma_fw_t;
extern stx7105_fdma_fw_t stx7105_fdma0_fw;
extern stx7105_fdma_fw_t stx7105_fdma1_fw;
#endif

View File

@ -1,7 +1,10 @@
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "stx7105.h"
#include "stx7105_fdma.h"
#include "stx7105_fdma_fw.h"
#include "stx7105_utils.h"
#define LED_RED_GPIO PIO0
@ -18,6 +21,9 @@
#define MEMTEST_START 0x82000000
#define MEMTEST_END 0x8F000000
#define DMA_BUFFER_SIZE 16
uint8_t src_buffer[DMA_BUFFER_SIZE];
void uart_init(void) {
PIO4->CLR_PC0 = 1U; /* PC = 110, AFOUT, PP */
PIO4->SET_PC1 = 1U;
@ -33,52 +39,80 @@ void uart_init(void) {
CONSOLE_ASC->CTRL = 0x1589UL; /* 8N1, RX enable, FIFO enable, Baud mode 1 */
}
static void memory_test(void) {
for (uint32_t i = MEMTEST_START; i < MEMTEST_END; i += 4) {
*(uint32_t *)i = i;
static void configure_fdma0(void) {
FDMA0->SLIM_CLK_GATE |= (FDMA_SLIM_CLK_GATE_DIS_Msk | FDMA_SLIM_CLK_GATE_RESET_Msk);
FDMA0->PERIPH_STBUS_SYNC |= FDMA_PERIPH_STBUS_SYNC_DIS_Msk;
if (i % 0x10000 == 0U) {
printf("Write to 0x%08lx...\r\n", i);
}
for (uint32_t i = 0; i < stx7105_fdma0_fw.text_size; i++) {
FDMA0->SLIM_IMEM[i] = stx7105_fdma0_fw.text[i];
}
for (uint32_t i = MEMTEST_START; i < MEMTEST_END; i += 4) {
if (*(uint32_t *)i != i) {
printf("Read back error at 0x%08lx\r\n", i);
return;
}
if (i % 0x10000 == 0U) {
printf("Read from 0x%08lx...\r\n", i);
}
for (uint32_t i = 0; i < stx7105_fdma0_fw.data_size; i++) {
FDMA0->SLIM_DMEM[i] = stx7105_fdma0_fw.data[i];
}
FDMA0->SLIM_CLK_GATE &= ~FDMA_SLIM_CLK_GATE_DIS_Msk;
FDMA0->PERIPH_INT_CLR = 0xFFFFFFFFU;
FDMA0->PERIPH_CMD_CLR = 0xFFFFFFFFU;
FDMA0->SLIM_EN |= FDMA_SLIM_EN_RUN_Msk;
printf("FDMA0 SLIM ID: 0x%08lx\r\n", FDMA0->SLIM_ID);
printf("FDMA0 SLIM Version: 0x%08lx\r\n", FDMA0->SLIM_VER);
}
static void configure_fdma1(void) {
FDMA1->SLIM_CLK_GATE |= (FDMA_SLIM_CLK_GATE_DIS_Msk | FDMA_SLIM_CLK_GATE_RESET_Msk);
FDMA1->PERIPH_STBUS_SYNC |= FDMA_PERIPH_STBUS_SYNC_DIS_Msk;
for (uint32_t i = 0; i < stx7105_fdma1_fw.text_size; i++) {
FDMA1->SLIM_IMEM[i] = stx7105_fdma1_fw.text[i];
}
for (uint32_t i = 0; i < stx7105_fdma1_fw.data_size; i++) {
FDMA1->SLIM_DMEM[i] = stx7105_fdma1_fw.data[i];
}
FDMA1->SLIM_CLK_GATE &= ~FDMA_SLIM_CLK_GATE_DIS_Msk;
FDMA1->PERIPH_INT_CLR = 0xFFFFFFFFU;
FDMA1->PERIPH_CMD_CLR = 0xFFFFFFFFU;
FDMA1->SLIM_EN |= FDMA_SLIM_EN_RUN_Msk;
printf("FDMA1 SLIM ID: 0x%08lx\r\n", FDMA1->SLIM_ID);
printf("FDMA1 SLIM Version: 0x%08lx\r\n", FDMA1->SLIM_VER);
}
int main(void) {
init_led(LED_RED_GPIO, LED_RED_PIN, 0U);
init_led(LED_BLUE_GPIO, LED_BLUE_PIN, 0U);
setbuf(stdout,NULL);
setbuf(stderr,NULL);
setbuf(stdout, NULL);
setbuf(stderr, NULL);
uart_init();
printf("Hello world\r\n");
printf("Size of int: %d\r\n", sizeof(int));
printf("Size of short: %d\r\n", sizeof(short));
printf("Size of char: %d\r\n", sizeof(char));
printf("Size of long: %d\r\n", sizeof(long));
printf("Size of pointer: %d\r\n", sizeof(uint8_t *));
printf("Size of uint8_t: %d\r\n", sizeof(uint8_t));
printf("Size of uint16_t: %d\r\n", sizeof(uint16_t));
printf("Size of uint32_t: %d\r\n", sizeof(uint32_t));
printf("CKGA Opts 1: 0x%08lx\r\n", CKGA->CLKOPSRC_SWITCH_CFG);
printf("CKGA Opts 2: 0x%08lx\r\n", CKGA->CLKOPSRC_SWITCH_CFG2);
configure_fdma0();
configure_fdma1();
FDMA_FWRegs_TypeDef *fdma0_fwregs = (FDMA_FWRegs_TypeDef *)(FDMA0->SLIM_DMEM);
fdma0_fwregs->CHANNEL[0].NEXT = (uint32_t)NULL;
fdma0_fwregs->CHANNEL[0].NBYTES = DMA_BUFFER_SIZE;
fdma0_fwregs->CHANNEL[0].LENGTH = DMA_BUFFER_SIZE;
fdma0_fwregs->CHANNEL[0].SADDR = (uint32_t)src_buffer;
fdma0_fwregs->CHANNEL[0].DADDR = CONSOLE_ASC->TX_BUF;
fdma0_fwregs->CHANNEL[0].S_STRIDE = 0U;
fdma0_fwregs->CHANNEL[0].D_STRIDE = 0U;
fdma0_fwregs->REQ_CTRL[0] = (1U << FDMA_FwRegs_REQ_CTLN_NUM_OPS_Pos) | FDMA_FwRegs_REQ_CTLN_INC_ADDR_Msk;
delay_ms(5000);
memory_test();
for (;;) {
set_led(LED_BLUE_GPIO, LED_BLUE_PIN, 1U);
delay_ms(500);

View File

@ -9,28 +9,39 @@ typedef enum {
} expevt_type_t;
typedef enum {
INT_TYPE_TMU_TNUI0 = 0x400,
INT_TYPE_TMU_TNUI1 = 0x420,
INT_TYPE_TMU_TNUI2 = 0x440,
INT_TYPE_TMU_TICPI2 = 0x460,
INT_TYPE_TMU_TNUI0 = 0x400,
INT_TYPE_TMU_TNUI1 = 0x420,
INT_TYPE_TMU_TNUI2 = 0x440,
INT_TYPE_TMU_TICPI2 = 0x460,
INT_TYPE_FDMA_0_MBOX = 0x1380,
INT_TYPE_FDMA_1_MBOX = 0x13A0,
} intevt_type_t;
typedef enum {
TRA_TYPE_SYSCALL = 34,
} tra_type_t;
__WEAK int tuni0_handler(void) {
/* Does nothing */
return 0;
}
__WEAK int fdma0_mbox_handler(void) {
/* Does nothing */
return 0;
}
__WEAK int fdma1_mbox_handler(void) {
/* Does nothing */
return 0;
}
__WEAK int syscall_handler(uint32_t p1, uint32_t p2, uint32_t p3, uint32_t p4) {
return 0;
}
__WEAK int trap_handler(uint32_t p1, uint32_t p2, uint32_t p3, uint32_t p4) {
tra_type_t tra = CSR->TRA;
tra_type_t tra = CSP->TRA;
switch (tra) {
case TRA_TYPE_SYSCALL:
@ -44,7 +55,7 @@ __WEAK int trap_handler(uint32_t p1, uint32_t p2, uint32_t p3, uint32_t p4) {
}
__WEAK_IRQ int general_exc_handler(uint32_t p1, uint32_t p2, uint32_t p3, uint32_t p4) {
expevt_type_t expevt = CSR->EXPEVT;
expevt_type_t expevt = CSP->EXPEVT;
switch (expevt) {
case EXP_TYPE_TRAP:
return trap_handler(p1, p2, p3, p4);
@ -57,11 +68,17 @@ __WEAK_IRQ int general_exc_handler(uint32_t p1, uint32_t p2, uint32_t p3, uint32
}
__WEAK_IRQ int general_int_handler(void) {
intevt_type_t intevt = CSR->INTEVT;
intevt_type_t intevt = CSP->INTEVT;
switch (intevt) {
case INT_TYPE_TMU_TNUI0:
return tuni0_handler();
break;
case INT_TYPE_FDMA_0_MBOX:
return fdma0_mbox_handler();
break;
case INT_TYPE_FDMA_1_MBOX:
return fdma1_mbox_handler();
break;
default:
break;
}

2473
src/stx7105_fdma_fw.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,3 @@
# FDMAFWExtract
This tool can be used to extract firmware data from ELF files.

View File

@ -0,0 +1,164 @@
#include <errno.h>
#include <fcntl.h>
#include <gelf.h>
#include <libelf.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
static void print_usage(void) {
fprintf(stderr, "Usage: fdmafwextract ELF_FILENAME\n");
}
static int get_section_idx_by_name(Elf *handle, char *name) {
/* Get total section counts. */
size_t e_nsections;
if (elf_getshdrnum(handle, &e_nsections) < 0) {
int errsv = elf_errno();
fprintf(stderr, "Failed to retrieve section counts, %s\n", elf_errmsg(errsv));
return -1;
}
/* Get string table index. */
size_t e_stridx;
if (elf_getshdrstrndx(handle, &e_stridx) < 0) {
int errsv = elf_errno();
fprintf(stderr, "Failed to get string table index, %s\n", elf_errmsg(errsv));
return -2;
}
/* Search sections for specific name */
for (size_t i = 0; i < e_nsections; i++) {
Elf_Scn *scn = elf_getscn(handle, i);
if (scn == NULL) {
int errsv = elf_errno();
fprintf(stderr, "Failed to get section ID: %d, %s\n", i, elf_errmsg(errsv));
return -3;
}
/* Get section header */
GElf_Shdr shdr_mem;
GElf_Shdr *shdr = gelf_getshdr(scn, &shdr_mem);
if (shdr == NULL) {
int errsv = elf_errno();
fprintf(stderr, "Failed to get section header ID: %d, %s\n", i, elf_errmsg(errsv));
return -4;
}
/* Get section name string from table */
const char *s_name = elf_strptr(handle, e_stridx, shdr->sh_name);
if (s_name == NULL) {
int errsv = elf_errno();
fprintf(stderr, "Failed to get section name for ID: %d, %s\n", i, elf_errmsg(errsv));
return -5;
}
/* Found a match */
if (strcmp(s_name, name) == 0) {
fprintf(stderr, "Found a match for section %s at ID: %d\n", s_name, i);
return i;
}
}
/* Loop completed with no matching sections found. */
fprintf(stderr, "No section named %s found.\n", name);
return -1;
}
static int dump_section_as_c_array(Elf *handle, int idx, bool pad_32) {
Elf_Scn *scn = elf_getscn(handle, idx);
if (scn == NULL) {
int es = elf_errno();
fprintf(stderr, "Failed to get section %d: %s\n", idx, elf_errmsg(es));
return -1;
}
Elf_Data *data = elf_rawdata(scn, NULL);
if (data == NULL) {
int es = elf_errno();
fprintf(stderr, "Failed to get section data %d: %s\n", idx, elf_errmsg(es));
return -2;
}
fprintf(stderr, "Section %d size: 0x%x, offset: 0x%x\n", idx, data->d_size, data->d_off);
fprintf(stdout, "\n{\n");
for(int i = 0; i < data->d_size; i++) {
fprintf(stdout, "0x%02x, ", ((uint8_t *)data->d_buf)[i]);
if(i % 16 == 15) {
fprintf(stdout, "\n");
}
}
fprintf(stdout, "};\n");
return 0;
}
int main(int argc, const char *argv[]) {
int ret = 0;
if (argc < 2) {
print_usage();
ret = -1;
return ret;
}
int elf_fd = open(argv[1], O_RDONLY);
if (elf_fd < 0) {
int es = errno;
fprintf(stderr, "Failed to open ELF file: %s\n", strerror(es));
ret = -2;
return ret;
}
elf_version(EV_CURRENT);
Elf *e_handle = elf_begin(elf_fd, ELF_C_READ, NULL);
if (e_handle == NULL) {
int es = elf_errno();
fprintf(stderr, "ELF begin failed: %s\n", elf_errmsg(es));
ret = -3;
goto err_out;
}
ret = get_section_idx_by_name(e_handle, ".text");
if (ret < 0) {
fprintf(stderr, "Failed to find text section.\n");
ret = -4;
goto elf_out;
}
ret = dump_section_as_c_array(e_handle, ret, true);
ret = get_section_idx_by_name(e_handle, ".data");
if (ret < 0) {
fprintf(stderr, "Failed to find data section.\n");
ret = -5;
goto elf_out;
}
ret = dump_section_as_c_array(e_handle, ret, false);
elf_out:
elf_end(e_handle);
err_out:
close(elf_fd);
return ret;
}