diff --git a/Makefile b/Makefile index b650197..342f969 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ PREFIX ?= arm-none-eabi- CC = $(PREFIX)gcc GDB ?= $(PREFIX)gdb -CGENFLAGS = -mcpu=arm926ej-s -mthumb-interwork -fno-pie +CGENFLAGS = -mcpu=arm926ej-s -mthumb-interwork -fno-pie -DARM9 WARN = -Wall -Wextra -Werror=return-type -Werror=implicit-function-declaration OPTIMIZE = -g -Og INCLUDE = -I. diff --git a/jazelle.c b/jazelle.c index 0e1c70c..c9a8f87 100644 --- a/jazelle.c +++ b/jazelle.c @@ -8,38 +8,100 @@ // known ID table: // Chip name | ARM core | ARM CPUID | JTAG IDCODE | Jazelle ID // ------------+------------+------------+-------------+----------- Jazelle DBX: -// ??? | ARM7EJ-S | ??? | ??? | ??? +// ??? TODO | ARM7EJ-S | ??? | ??? | ??? // Cypress FX3 | ARM926EJ-S | 0x41069265 | 0x07926069 | 0x64100004 -// TI Nspire | ARM926EJ-S?| 0x41069265?| ??? | 0x64100004? -// RPi v1.?? | ARM11??? | ??? | ??? | ??? -// Ninty ?3DS | ARM11MPCore| 0x410FB025?| ??? | 0x74100064? +// TI Nspire | ARM926EJ-S?| 0x41069265?| ??? | 0x64100004? // TODO +// Wii Starlet | ARM926EJ-S?| ??? | ??? | ??? // TODO +// RPi v1.2 B+ |ARM1176JZF-S| 0x410FB767 | 0x07B7617F | 0x74100064 +// Ninty .3DS | ARM11MPCore| 0x410FB025?| ??? | 0x74100064? // TODO +// ??? TODO | Cortex-A8 | ??? | ??? | ??? // Xilinx Zynq7| Cortex-A9MP| 0x413FC090 | 0x4BA00477 | 0xF4100168 // ------------+------------+------------+-------------+----------- Jazelle RCT: // Xilinx Zynq7| Cortex-A9MP| 0x413FC090 | 0x4BA00477 | 0xF4100168 -// -// TODO: others (BeagleBoard Cortex-A8? Other A9s?) +// ------------+------------+------------+-------------+----------- Nothing: +// Qcom MSM8255| S2 Scorpion| 0x517100F2 | ??? | 0x00000000 // TODO: immediate next steps: // * check if we can override jazelle insn execution with custom handlers // * check what the control registers actually do // * enumerate what all insns do -__attribute__((__naked__)) +/* + +Cypress FX3: + +bytecode IDs that use a handler: + 0x0f, 0x12, 0x13, 0x14, 0x53, 0x62, 0x63, 0x66, 0x67, 0x6a, 0x6b, 0x6c, + 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x77, 0x79, 0x7b, 0x7d, 0x86, + 0x87, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x95, 0x96, 0x97, + 0x98, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, + 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbf, 0xc0, 0xc1, + 0xc2, 0xc3, 0xc4, 0xc5, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, + 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, + 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe +0xff is hardwired to bkpt #0 + +*/ + +#if !defined(__linux__) || defined(_LINUX_KERNEL_H) +inline +#endif static uint32_t arm_get_id(void) { - asm volatile( - "mrc p15, 0, r0, c0, c0, 0\n" - "bx lr\n" - ); +#if defined(__linux__) && !defined(_LINUX_KERNEL_H) + // TODO: read out /sys/devices/system/cpu/cpu*/regs/identification/midr_el1 or /proc/cpuinfo +#else + // NOTE: requires kernel mode execution level to read + uint32_t res; + asm volatile("mrc p15, 0, %0, c0, c0, 0\n":"=r"(res)); + return res; +#endif } -__attribute__((__naked__)) -static uint32_t jazelle_get_id(void) { - asm volatile( - "mrc p14, 7, r0, c0, c0, 0\n" - "bx lr\n" - ); +inline static uint32_t jazelle_get_id(void) { + uint32_t res; + asm volatile("mrc p14, 7, %0, c0, c0, 0\n":"=r"(res)); + return res; } +// TODO: use different implementations when porting to other stuff +#if defined(__linux__) && !defined(_LINUX_KERNEL_H) +#error "TODO: implement cache flushes for Linux userspace" +#elif defined(ARM9) +__attribute__((__naked__)) +static void DC_FlushAll() { + asm volatile( +" mov r1, #0\n" +"outer_loop:\n" +" mov r0, #0\n" +"inner_loop:\n" +" orr r2, r1, r0 @ generate segment and line address\n" +" mcr p15, 0, r2, c7, c14, 2 @ clean and flush the line\n" +" add r0, r0, #32\n" +" cmp r0, #0x1000/4\n" +" bne inner_loop\n" +" add r1, r1, #0x40000000\n" +" cmp r1, #0\n" +" bne outer_loop\n" + +" mov r0, #0\n" +" mcr p15, 0, r0, c7, c10, 4 @ drain write buffer\n" +" bx lr\n" + :::"memory"); +} +static inline void DC_InvalidateAll() { + asm volatile("mcr p15, 0, %0, c7, c6, 0" : : "r"(0)); +} +static inline void IC_InvalidateAll() { + asm volatile("mcr p15, 0, %0, c7, c5, 0" : : "r"(0)); +} +#else +// TODO: ARM11 +// TODO: Cortex-A[89] +#error "TODO: define data and instruction cache functions for your target!" +#endif + __attribute__((__aligned__(1024))) static struct { void* handlers[512]; @@ -98,7 +160,6 @@ static int jazelle_exec_native(const void* bytecode, const void* block) { "ldr r12, =jazelle_exit_save\n" "adr r0, .Ljazend\n" "str r0, [r12]\n" - //"bkpt #0\n" // switch to jazelle mode "adr r12, .Lno_jazelle\n" @@ -152,7 +213,6 @@ static void handler_idiv(void) { // reads instead! asm volatile( - //"bkpt #3\n" // FIXME: read out stack contents in a better way "add r1, r2\n" "str r1, [r6,#-8]\n" @@ -169,7 +229,6 @@ __attribute__((__naked__)) static void handler_ireturn(void) { int result; asm volatile( - //"bkpt #4\n" "ldr %[res], [r6, #-4]!\n" :[res]"=r"(result) ); @@ -187,6 +246,121 @@ static void handler_ireturn(void) { __builtin_unreachable(); } + + + + + +static int was_exec = -1; + +__attribute__((__naked__)) +static void handler_wasexec() { + asm volatile( + // set was_exec flag + "mov r0, #1\n" + "str r0, %[we]\n" + // get back to original stuff + "ldr r12, %[exsav]\n" + "bx r12" + : + :[exsav]"m"(jazelle_exit_save) + ,[we]"m"(was_exec) + :"r0","r12" + ); + __builtin_unreachable(); +} + +__attribute__((__naked__)) +static void handler_noexec() { + asm volatile( + // get back to original stuff + "ldr r12, %[exsav]\n" + "bx r12" + : + :[exsav]"m"(jazelle_exit_save) + :"r0","r12" + ); + __builtin_unreachable(); +} + +static uint8_t bytecode_testh[] = { + 0x06, 0x06, + 0x07, 0x07, + 0x05, 0x05, + 0x04, 0x04, + 0x6C, // +8 + 0x00, 0x00, 0x00, 0x00, // up to 4 nops of argument bytes eg for invokeXYZ + 0x00, 0x00, 0x00, 0x00, // except 2nd byte is 3 for goto offset (BE) (3 aka iconst_0) + 0xBA, // +17 // invokedynamic, complex enough to never be implemented in hw + 0x00, 0x00, 0x00, 0x00, // up to 4 nops of argument bytes eg for invokeXYZ +}; + +static void jazelle_test_handlers(uint8_t hflags[256/8]) { + memset(hflags, 0, 256/8); + for (int i = 0x00; i < 0xff /* bytecode 0xff is hardwired to bkpt #0 */; ++i) { + if (i == 0xba) { + hflags[i>>3]|=(1<<(i&7)); + continue; // yeah + } + + bytecode_testh[8] = i; + memset(&bytecode_testh[9], 0, 8); + switch (i) { // need offset fixups for some instructions + case 0xa7: // goto + case 0xa8: // jsr + bytecode_testh[10] = 3; + break; + case 0xa9: // ret + bytecode_testh[9] = 1; + break; + case 0xc8: // goto_w + case 0xc9: // jsr_w + bytecode_testh[12] = 3; + break; + default: break; + } + memset(&jazelle_block, 0, sizeof jazelle_block); + // initialize local 1 for a return address for the 'ret' opcode + uint32_t retval = &bytecode_testh[17]; + jazelle_block.locals[4] = retval >> 0; + jazelle_block.locals[5] = retval >> 8; + jazelle_block.locals[6] = retval >>16; + jazelle_block.locals[7] = retval >>24; + + DC_FlushAll(); + DC_InvalidateAll(); + IC_InvalidateAll(); + + jazelle_block.handlers[i] = handler_wasexec; + jazelle_block.handlers[0xba] = handler_noexec; + + was_exec = 0; + jazelle_exec_native(bytecode_testh, &jazelle_block); + + if (was_exec == 1) { + hflags[i>>3]|=(1<<(i&7)); + //iprintf("bytecode 0x%02x: uses handler\r\n", i); + } else { + //iprintf("bytecode 0x%02x: hw\r\n", i); + } + + jazelle_block.handlers[i] = NULL; + } +} + +// https://github.com/SonoSooS/libjz/wiki/Java-instruction-set +static uint8_t bytecode_test1[] = { + 0x06, // iconst_3 + 0x07, // iconst_4 + 0x05, // iconst_2 + 0x6C, // idiv + 0x04, // iconst_1 + 0x60, // iadd + 0x60, // iadd + 0xAC, // ireturn +}; + +// returns 6 if idiv implemented natively, else 10 static int jazelle_exec(const uint8_t* bytecode) { jazelle_block.handlers[0x6C] = handler_idiv; jazelle_block.handlers[0xAC] = handler_ireturn; @@ -206,108 +380,6 @@ static int jazelle_exec(const uint8_t* bytecode) { return jazelle_exec_native(bytecode, block); } - - - - - -static int was_exec = -1; - -__attribute__((__naked__)) -static void handler_wasexec() { - asm volatile( - //"bkpt #1\n" - // set was_exec flag - "mov r0, #1\n" - "str r0, %[we]\n" - // get back to original stuff - "ldr r12, %[exsav]\n" - "bx r12" - : - :[exsav]"m"(jazelle_exit_save) - ,[we]"m"(was_exec) - :"r0","r12" - ); - __builtin_unreachable(); -} - -__attribute__((__naked__)) -static void handler_noexec() { - asm volatile( - //"bkpt #2\n" - // clear was_exec flag - //"mov r0, #0\n" - //"str r0, %[we]\n" - // get back to original stuff - "ldr r12, %[exsav]\n" - "bx r12" - : - :[exsav]"m"(jazelle_exit_save) - //,[we]"m"(was_exec) - :"r0","r12" - ); - __builtin_unreachable(); -} - -static uint8_t bytecode_testh[] = { - 0x06, - 0x07, - 0x05, - 0x6C, - 0x00, 0x00, 0x00, 0x00, // up to 4 nops of argument bytes eg for invokeXYZ - 0xBA, - 0x00, 0x00, 0x00, 0x00, // up to 4 nops of argument bytes eg for invokeXYZ - - /*0x06, 0x06, 0x06, 0x06, // pre-fill the stack a bit - 0x00, // target instruction to test - 0x00, 0x00, 0x00, 0x00, // up to 4 nops of argument bytes eg for invokeXYZ - 0xba, // invokedynamic, this one is complex enough that it'll reliably - // never be implemented in hardware*/ -}; - -static void jazelle_test_handlers(uint8_t hflags[256/8]) { - memset(hflags, 0, 256/8); - for (int i = 0x6C; i < 0x100; ++i) { - if (i == 0xba) { - hflags[i>>3]|=(1<<(i&7)); - continue; // yeah - } - - //iprintf("bc 0x%02x\r\n", i); - bytecode_testh[3] = i; - //memset(&jazelle_block, 0, sizeof jazelle_block); - jazelle_block.handlers[i] = handler_wasexec; - jazelle_block.handlers[0xba] = handler_noexec; - - was_exec = 0; - jazelle_exec_native(bytecode_testh, &jazelle_block); - - if (was_exec == 1) { - hflags[i>>3]|=(1<<(i&7)); - iprintf("bytecode 0x%02x: uses handler\r\n", i); - } else if (was_exec != 0) { // unchanged - iprintf("bytecode 0x%02x: wut?\r\n", i); - } else { - //iprintf("bytecode 0x%02x: hw\r\n", i); - } - - jazelle_block.handlers[i] = NULL; - //asm volatile("bkpt #7\n"); - } -} - -// https://github.com/SonoSooS/libjz/wiki/Java-instruction-set -static uint8_t bytecode_test1[] = { - 0x06, // iconst_3 - 0x07, // iconst_4 - 0x05, // iconst_2 - 0x6C, // idiv - 0x04, // iconst_1 - 0x60, // iadd - 0x60, // iadd - 0xAC, // ireturn -}; - void jazelle_main(void) { uint32_t aid = arm_get_id(); uint32_t jid = jazelle_get_id(); @@ -318,17 +390,18 @@ void jazelle_main(void) { iprintf("retcode=%d\r\n", r); if (r == 0) { - //r = jazelle_exec(bytecode_test1); - //iprintf("retcode=%d\r\n", r); - - uint8_t hflags[256/8]; + static uint8_t hflags[256/8]; jazelle_test_handlers(hflags); - for (int i = 0; i < 0x100; ++i) { + iprintf("bytecode IDs that use a handler:\r\n\t"); + for (int i = 0, has = 0; i < 0x100; ++i) { if (hflags[i>>3]&(1<<(i&7))) { - iprintf("bytecode 0x%02x: uses handler\r\n", i); + iprintf("%s0x%02x", ((has&15) ? ", " : ""), i); + ++has; + if ((has & 15) == 0) iprintf("\r\n\t"); } } + printf("\r\n"); } while (true) ; diff --git a/rpi/Makefile b/rpi/Makefile new file mode 100644 index 0000000..e867269 --- /dev/null +++ b/rpi/Makefile @@ -0,0 +1,42 @@ + +OPENOCD_HOST ?= localhost +OPENOCD_PORT_GDB ?= 3333 +OPENOCD_PORT_TELNET ?= 4444 +PREFIX ?= arm-none-eabi- + +CC = $(PREFIX)gcc +CFLAGS = -mcpu=arm1176jzf-s +LDFLAGS = -T rpi.ld -nostartfiles -nostdlib +GDB ?= $(PREFIX)gdb +PYTHON3 ?= python3 +NC ?= nc + +default: all + +all: rpi.elf + +rpi.o: rpi.c + $(CC) $(CFLAGS) -c -o "$@" "$<" + +rpi.elf: rpi.o + $(CC) $(CFLAGS) $(LDFLAGS) -o "$@" $^ + +openocd-launch: + openocd -f interface/cmsis-dap.cfg -c "transport select jtag" \ + -c "adapter speed 50" -f target/bcm2835.cfg \ + -c init -c scan_chain + +openocd-load: rpi.elf + printf 'halt\nload_image rpi.elf\nexit\n' \ + | nc $(OPENOCD_HOST) $(OPENOCD_PORT_TELNET) + +gdb: + $(GDB) -ex 'target extended-remote $(OPENOCD_HOST):$(OPENOCD_PORT_GDB)' \ + -ex 'set $$pc=_start' \ + $(GDB_EXTRA_CMDS) \ + rpi.elf + +clean: + @$(RM) -v rpi.o rpi.elf + +.PHONY: all clean openocd-launch openocd-load gdb diff --git a/rpi/rpi.c b/rpi/rpi.c new file mode 100644 index 0000000..e70cd36 --- /dev/null +++ b/rpi/rpi.c @@ -0,0 +1,249 @@ + +#include +#include +#include +#include +#include + +// known ID table: +// Chip name | ARM core | ARM CPUID | JTAG IDCODE | Jazelle ID +// ------------+------------+------------+-------------+----------- Jazelle DBX: +// ??? | ARM7EJ-S | ??? | ??? | ??? +// Cypress FX3 | ARM926EJ-S | 0x41069265 | 0x07926069 | 0x64100004 +// TI Nspire | ARM926EJ-S?| 0x41069265?| ??? | 0x64100004? +// RPi v1.?? | ARM11??? | ??? | ??? | ??? +// Ninty ?3DS | ARM11MPCore| 0x410FB025?| ??? | 0x74100064? +// Xilinx Zynq7| Cortex-A9MP| 0x413FC090 | 0x4BA00477 | 0xF4100168 +// ------------+------------+------------+-------------+----------- Jazelle RCT: +// Xilinx Zynq7| Cortex-A9MP| 0x413FC090 | 0x4BA00477 | 0xF4100168 +// TODO: others (BeagleBoard Cortex-A8? Other A9s?) + +// TODO: immediate next steps: +// * check if we can override jazelle insn execution with custom handlers +// * check what the control registers actually do +// * enumerate what all insns do + +__attribute__((__naked__)) +static uint32_t arm_get_id(void) { + asm volatile( + "mrc p15, 0, r0, c0, c0, 0\n" + "bkpt #4\n" + "bx lr\n" + ); +} + +__attribute__((__naked__)) +static uint32_t jazelle_get_id(void) { + asm volatile( + "mrc p14, 7, r0, c0, c0, 0\n" + "bkpt #5\n" + "bx lr\n" + ); +} + +__attribute__((__aligned__(1024))) +static struct { + void* handlers[512]; + uint8_t stack[256]; + uint8_t locals[256]; +} jazelle_block; + +/* + * c0: Jazelle Identity register (read-only) + Bits 0-11: Subarchitecture-defined bits (reads as 4, meaning unknown) + Bits 12-19: Subarchitecture (reads as 0, Jazelle V1 according to documentation) + Bits 20-27: Implementor (reads as 0x41, ARM Limited according to documentation) + Bits 28-31: Architecture (reads as 6, ARMv5TEJ according to documentation) + c1: Operating System Control register + Bit 0: Configuration Disabled (CD) (documented) + Bit 1: Configuration Valid (CV) (documented) + c2: Main Configuration register + Bit 0: Jazelle Enable (JE) (documented) + Bits 26-28: Unknown + Bit 29: If set, array object contains its elements directly, otherwise it contains a pointer to its elements + Bit 31: Disable array instructions if set? + c3: Array object layout register + Bits 0-7: Unknown + Bits 8-11: Offset (in words) within array object of first element or of pointer to first element + Bits 12-15: Offset (in words) within array object of length + Bit 16: If set, offset to length is subtracted, otherwise added + Bits 17-19: Array length shift value (number of elements = stored length >> this) + Bits 20-21: Disable array instructions if set? + */ + +static uint32_t jazelle_exit_save; + +__attribute__((__naked__)) +static int jazelle_exec_native(const void* bytecode, const void* block) { + // inline asm parameters seems to be borking in GCC sooooo lets do it this way + (void)bytecode; (void)block; (void)&jazelle_exit_save; + asm volatile( + "push {r4-r12,lr}\n" + + "mov lr, r0\n" + + // init handler table pointer and stack pointer + "mov r5, r1\n" + "add r6, r5, #0x800\n" + "add r7, r5, #0x900\n" + // "r8: Pointer to constant pool? (haven't checked this yet)" -Hackspire + + // set configuration valid & jazelle enable bits + "mov r0, #2\n" + "mcr p14, 7, r0, c1, c0, 0\n" + "mov r0, #1\n" + "mcr p14, 7, r0, c2, c0, 0\n" + + // apparently there's no good way to find the exit point from jazelle, + // so we're going to hack that into the stuff now + "ldr r12, =jazelle_exit_save\n" + "adr r0, .Ljazend\n" + "str r0, [r12]\n" + + // switch to jazelle mode + "adr r12, .Lno_jazelle\n" + "bxj r12\n" + + ".Ljazend:\n" + "mov r0, #0\n" + "b .Lend\n" + + ".Lno_jazelle:\n" + "bkpt #1\n" + "mov r0, #1\n" + + ".Lend:\n" + "mov r5, #0\n" + "mcr p14, 7, %r5, c1, c0, 0\n" + "mcr p14, 7, %r5, c2, c0, 0\n" + + "pop {r4-r12,lr}\n" + "bx lr\n" + + ".pool\n" + ); +} + + + +__attribute__((__naked__)) +static void handler_idiv(void) { + // r0 = 3 + // r1 = 4 + // r2 = 2 + // editing the above has no effect + // NOTE: these depend on the stack content, i.e. it's not a moving register + // window. pushes happen in the following order: r0,r1,r2,r3 + // TODO: when the 'register stack cache' is full, what happens? does + // it loop or does it act in a FIFO way, moving r0<-r1<-r2<-r3? + // how can the fillrate be known??? (libjz says r5 & 3 but i + // dont see anything like that, maybe its an ARM11 thing?) + // "r4: Copy of local variable 0. Only valid when local variable 0 is a + // single word (i.e. int, float, or Object; not long or double)" + // -Hackspire + // + // [r6-4] is stack top (2) + // [r6-8] is 4 + // etc + // use the above to manipulate the stack, eg. "iadd" is implemented as: + // - add r1, r2 // or equivalently, read from stack i guess + // - str r1, [r6, #-8] // store to the place where it will be read + // - sub r6, #4 // pop off & discard stack top element + // NOTE: this input usage (with r1 and r2) is NOT robust at all, use memory + // reads instead! + + asm volatile( + "bkpt #3\n" + // FIXME: read out stack contents in a better way + "add r1, r2\n" + "str r1, [r6,#-8]\n" + "sub r6, #4\n" + + // return to jazelle (yes lr has to be incremented otherwise the + // current instruction keeps getting executed in a loop) + "add lr, #1\n" + "bxj r12\n" // FIXME: r12 can be modified by jazelle so it should be restored to something + ); +} + +__attribute__((__naked__)) +static void handler_ireturn(void) { + int result; + asm volatile( + "bkpt #2\n" + "ldr %[res], [r6, #-4]!\n" + :[res]"=r"(result) + ); + //iprintf("result=%d\r\n", result); // FIXME: save & restore r0-r3 if ret implemented properly + + // get back to original code + // TODO: later stage: get back to previous bytecode stuff + asm volatile( + "ldr r12, %[exsav]\n" + "bx r12\n" + : + :[exsav]"m"(jazelle_exit_save) + :"r12" + ); + __builtin_unreachable(); +} + +static int jazelle_exec(const uint8_t* bytecode) { + jazelle_block.handlers[0x6C] = handler_idiv; + jazelle_block.handlers[0xAC] = handler_ireturn; +/* + * +000-3FF: Unhandled bytecodes + The stack is flushed to memory before calling any of these handlers, so they may modify r0-r3 freely + +400: Null pointer exception + +404: Array index out of bounds exception + +40C: Jazelle mode entered with JE = 0 + +410: Configuration invalid (Jazelle mode entered with CV = 0) + CV is automatically set to 1 on entering this handler + +414: Prefetch abort occurred in middle of instruction + -Hackspire + */ + const void* block = &jazelle_block; + + return jazelle_exec_native(bytecode, block); +} + + +// https://github.com/SonoSooS/libjz/wiki/Java-instruction-set +static uint8_t bytecode_test1[] = { + 0x06, // iconst_3 + 0x07, // iconst_4 + 0x05, // iconst_2 + 0x6C, // idiv + 0x04, // iconst_1 + 0x60, // iadd + 0x60, // iadd + 0xAC, // ireturn +}; + +void jazelle_main(void) { + uint32_t aid = arm_get_id(); + uint32_t jid = jazelle_get_id(); + asm volatile("bkpt #0\n"); + //iprintf("hello world! ARM coreID=0x%lx jazelle ID=0x%lx\r\n", aid, jid); + while (jid == 0) ; + + int r = jazelle_exec(bytecode_test1); + //iprintf("retcode=%d\r\n", r); + + while (true) ; +} + +void main(void) { + jazelle_main(); +} + +__attribute__((__naked__, __section__(".entry"))) +void _start(void) { + asm volatile( + "ldr sp, =0x00010000\n" + "bl main\n" + "1: b 1b\n" + ".pool\n" + ); +} + diff --git a/rpi/rpi.ld b/rpi/rpi.ld new file mode 100644 index 0000000..986f714 --- /dev/null +++ b/rpi/rpi.ld @@ -0,0 +1,35 @@ + +ENTRY(_start) + +SECTIONS +{ + . = 0x00001000; + + .text : + { + *(.entry*) + *(.text*) + *(.rodata*) + } + .data : + { + *(.data*) + } + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } + __exidx_end = .; + + .bss : + { + *(.bss*) + } +} +