@@ -0,0 +1,16 @@
#ifndef _ELF_LOADER_H
#define _ELF_LOADER_H

#include <stdint.h>

typedef enum {
ELF_OK,
ELF_ERR_INVALID_HEADER,
ELF_ERR_INVALID_PROGRAM_HEADER
} elf_err;

elf_err load_elf(void *elf_data, uint32_t *entry);

void run_elf(uint32_t arg0, void *stack, uint32_t entry);

#endif
@@ -0,0 +1,8 @@
.arm
.section .text

.globl run_elf

run_elf:
mov sp, r1
mov pc, r2
@@ -1,28 +1,41 @@
STARTUP(ripem/startup.o)
ENTRY(_entry)

MEMORY
{
dram : ORIGIN = 0x30000020, LENGTH = 33554400
sram : ORIGIN = 0x40000000, LENGTH = 64K
sram : ORIGIN = 0x00002000, LENGTH = 57344
dram_startup : ORIGIN = 0x30000020, LENGTH = 8160
dram : ORIGIN = 0x30002000, LENGTH = 33546240
}

PHDRS {
load PT_LOAD;
}

SECTIONS
{
.text.start : ALIGN(8) {
*(.start*);
} >dram_startup :load

.text : ALIGN(8) {
*(.text.startup*);
_rel_start = .;

*(.text*);
} > dram
} >sram AT>dram :load

.data : ALIGN(8) {
*(.data*);
} > dram
} >sram AT>dram :load

.rodata : ALIGN(8) {
*(.rodata*);
} > dram
} >sram AT>dram :load

.bss : ALIGN(8) {
.bss : ALIGN(8) {
*(.bss*);
} > dram

_rel_end = .;
} >sram AT>dram :load

.payload : ALIGN(8) {
*(.payload*);
} >dram :load
}
@@ -1,24 +1,35 @@
#include "defs.h"
#include "elf_loader.h"
#include "keypad.h"
#include "led.h"
#include "serial.h"
#include "syscon.h"
#include "rtc.h"

#include "gdb_stub.h"

const char *ripem_version = "0.0.0";

#define PAYLOAD_STAGING_AREA 0x31000000

extern uint32_t _binary_payload_start;
extern uint32_t _binary_payload_size;

void announce_time() {
int year, month, day, hour, min, sec;
char buffer[32];

rtc_get_time(&year, &month, &day, &hour, &min, &sec);

/* Print date with the american style. */
serial_puts(itoa(year, buffer, 10));
serial_putc('/');
serial_puts(itoa(day, buffer, 10));
serial_putc('/');
serial_puts(itoa(month, buffer, 10));
serial_putc(' ');

/* Print time. */
if (hour < 10)
serial_putc('0');
serial_puts(itoa(hour, buffer, 10));
@@ -36,16 +47,99 @@ void announce_time() {
serial_putc('\n');
}

void main(void) {
void launch_payload(unsigned r0, void *initial_stack) {
void *payload_ptr = &_binary_payload_start;
uint32_t payload_size = (uint32_t)&_binary_payload_size;

uint32_t entry;
char buffer[32];

serial_puts("Payload address : 0x");
serial_puts(itoa((uint32_t)payload_ptr, buffer, 16));
serial_putc('\n');

serial_puts("Payload size : ");
serial_puts(itoa((uint32_t)payload_size, buffer, 10));
serial_puts(" bytes\n");

serial_puts("Payload stack : 0x");
serial_puts(itoa((uint32_t)initial_stack, buffer, 16));
serial_putc('\n');

serial_puts("Payload staging area : 0x");
serial_puts(itoa(PAYLOAD_STAGING_AREA, buffer, 16));
serial_putc('\n');

/* Move payload out of the way. */
memcpy((char*)PAYLOAD_STAGING_AREA, payload_ptr, payload_size);

/* Load payload. */
switch (load_elf((char*)PAYLOAD_STAGING_AREA, &entry)) {
case ELF_OK:
serial_puts("Payload entry : 0x");
serial_puts(itoa(entry, buffer, 16));
serial_puts("\nLoading successful, jumping into payload...\n");

void (*entry_fct)(uint32_t arg0) = (void (*)(uint32_t))entry;
(*entry_fct)(r0);
// run_elf(r0, initial_stack, entry);

case ELF_ERR_INVALID_HEADER:
serial_puts("Invalid ELF header! Aborting.\n");
led_set(LED_RED);

/* Reboot when ON is pressed. */
while (!keypad_get(KEY_ON));
syscon_reset();

case ELF_ERR_INVALID_PROGRAM_HEADER:
serial_puts("Invalid ELF program header! Aborting.\n");
led_set(LED_RED);

/* Reboot when ON is pressed. */
while (!keypad_get(KEY_ON));
syscon_reset();
}

}

void main(unsigned r0, void *initial_stack) {
int sec, prev_sec;

led_init();
keypad_init();
serial_init(115200);
rtc_init();

serial_puts("Hello world!\n");
serial_puts("\nRip'Em version ");
serial_puts(ripem_version);
serial_putc('\n');

serial_puts("Current time : ");
announce_time();
serial_putc('\n');

/*
* Align ourselves on the next second, then wait one second.
* If the ON key is kept pressed during all that time, run the GDB stub.
* Otherwise, run the payload.
*/
for (int delay = 0; delay < 2; delay++) {
rtc_get_time(NULL, NULL, NULL, NULL, NULL, &sec);
prev_sec = sec;
do {
rtc_get_time(NULL, NULL, NULL, NULL, NULL, &sec);
if (keypad_get(KEY_ON) == 0)
goto launch_payload;
} while (prev_sec == sec);
}

serial_puts("Launching GDB stub...\n");
gdb_mainloop();

launch_payload:
serial_puts("Loading payload...\n");
launch_payload(r0, initial_stack);

__builtin_unreachable();
}
@@ -1,9 +1,27 @@
.arm
.pushsection .text.startup
.section .startup, "ax"

.extern _rel_start
.extern _rel_end

_entry:
bl main
_hang:
b _hang
#
# Relocate from DRAM to SRAM
#
ldr r2, =0x2000
ldr r3, =_rel_start
ldr r4, =_rel_end
add r3, #0x30000000
add r4, #0x30000000

_copy_loop:
ldr r1, [r3], #4
str r1, [r2], #4
cmp r3, r4
bne _copy_loop

.popsection
mov r1, sp
ldr r2, =main
ldr lr, =0
ldr sp, =0xFFFC
mov pc, r2