diff --git a/README.md b/README.md index 1d84e13..2d93d3a 100644 --- a/README.md +++ b/README.md @@ -104,6 +104,15 @@ described near the end, the article is quite large. 1. ~~The BSL sets up Timer A, while the datasheet only mentions Timer B usage in *other* BSLs, and nothing about this one.~~ This is wrong, it changes the clock settings, which has an influence on which clock source a timer uses. +1. The BSL communication method does not depend on the part number (eg. 5994 vs + 59941), only the values in TLV are checked. +1. While the code has paths for other UART baudrate settings for the + communication interface, only one is available. +1. The memory area from `0x1b00` to `0x1bff` also contains ROM code, with its + own Z-area (also at the beginning, also 8 bytes in size). It has three + entrypoints, the fourth is an infinite loop. (`0x3c00..0x3fff` looks like + the same type of execute-only memory at first, but actually contains nothing, + at least not according to the techniques used here.) ## What has not been checked @@ -113,6 +122,7 @@ described near the end, the article is quite large. [MerryMage's GBA BIOS dump](https://mary.rs/lab/gbabios/)) 1. DMA: can a DMA transfer be used to change the stack contents during BSL execution? (Most likely, just like interrupts can, I simply haven't checked.) +1. Dumping of the `0x1b00`..`0x1bff` region still needs to happen. ## Hashes @@ -126,6 +136,15 @@ with BSL 00.08.35.B3: | SHA-256 | `e4d0d171013f847a357eebe5467bcd413ecb41dc01424b7e4ee636538d820766` | | SHA-512 | `fed28a7e9643a551789075b79d9b04fa6e8cdca74d783c1c3830ece07e5c9141dda9532b3c442416a1ddab90d752e679c6918c0d5333ac6da9fd23ab6c33d1bb` | +## Region 2 WIP stuff + +* `0x1b00` entrypoint: basically halts the CPU. Not very useful. +* `0x1b02` jumps to `0x1bc2` which almost immediately disables interrupts. +* `0x1b04` jumps to `0x1bd6` which almost immediately disables interrupts. + +Haven't been able to get around the IRQ disable thing yet... TODO: try NMI? Or +some timer IRQ sneakiness to get around the IRQ disable code. + ## Proof of concept The code in `src/main.c` will dump the content of the BSL to `eUSCI_A0` in UART diff --git a/logtracer.py b/logtracer.py index 01af7b4..1754bc3 100755 --- a/logtracer.py +++ b/logtracer.py @@ -72,7 +72,7 @@ with serial.Serial(sys.argv[1] if len(sys.argv) > 1 else "/dev/ttyACM1", 9600, t stack = [int(x,16) for x in stack] delta = -1 - if len(recs) > 1: + if len(recs) > 0: rec_ = Rec(ticks, delta, pc, sp, sr, gp, stack) for i in range(2, min(15, len(recs))): if recs[-i] == recs[-1]: diff --git a/src/main.c b/src/main.c index 6cf707d..675d399 100644 --- a/src/main.c +++ b/src/main.c @@ -40,6 +40,10 @@ static uint8_t stackbak[16]={0}; __attribute__((__persistent__)) static uint16_t curticks = 1; +extern uint16_t done_irq; +__attribute__((__persistent__, __used__)) +uint16_t done_irq = 0; + extern uint16_t curaddr; __attribute__((__persistent__)) @@ -56,7 +60,7 @@ typedef void (*bsl_fn)(void); #define END_CYC 0xffffu // DUMP_MODE == 0 => insn trace mode -#define DUMP_MODE 1 +#define DUMP_MODE 0 #define DUMP_CYC_OFF 14 void do_trace(void); @@ -67,10 +71,11 @@ __attribute__((__no_inline__)) void do_trace(void) { // init timer TA0 __bic_SR_register(GIE); -#ifdef DUMP_MODE +#if DUMP_MODE traceaddr = 0x1002; TA1CCR0 = DUMP_CYC_OFF; #else + done_irq = 0; TA1CCR0 = curticks; #endif TA1CCTL0 = CCIE; @@ -90,7 +95,7 @@ __attribute__((__no_inline__)) void do_trace(void) { "mov.w #0xbeef, r14\n" "mov.w #0xaaaa, r15\n" -#ifdef DUMP_MODE +#if DUMP_MODE // extra 0x1002 magic "mov.w curaddr, sp\n" #endif @@ -106,9 +111,15 @@ __attribute__((__no_inline__)) void do_trace(void) { void do_collect(uint16_t* sp); __attribute__((__used__, __no_inline__)) - void do_collect(uint16_t* sp) { +void do_collect(uint16_t* sp) { TA1CTL &= ~(uint16_t)(TAIE|MC__UP); + // 0x1bc2/4 and 0x1bd6/8 contain a bic #GIE, sr instruction! these should be 2 bytes in size + /*if (pc16 == 0x1bc2 || pc16 == 0x1bc4 || pc16 == 0x1bd6 || pc16 == 0x1bd8) { + sp[24] |= + }*/ + // 0x1b96 does a jump to ???? (probably from a memory location?) + #if DUMP_MODE uint16_t v1 = sp[2*(12-4)]; uint16_t v2 = sp[2*(13-4)]; @@ -128,14 +139,16 @@ __attribute__((__used__, __no_inline__)) if (curticks < START_SOFT) goto next_iter; #endif + uint16_t sr = sp[24]; + uint32_t pc = sp[25]; + //uint16_t pc16 = pc; + // general purpose registers for (int i = 0; i < 12; ++i) { uint32_t v = sp[(i*2)+0] | ((uint32_t)sp[(i*2)+1] << 16); regbak[i+4] = v; } - uint16_t sr = sp[24]; - uint32_t pc = sp[25]; pc |= ((uint32_t)(sr & 0xf000) << (16-12)); sr &= 0xfff; @@ -178,11 +191,36 @@ __attribute__((__interrupt__(TIMER1_A0_VECTOR), __naked__)) void Timer_A1_ISR(void) { asm volatile( ".extern do_collect\n" + ".extern done_irq\n" + ".extern curticks\n" //"bis #0x3, P1OUT\n" #if DUMP_MODE + // get a stack we can do stuff with + // (sp is currently in bsl space) "mov.a #(__stack-8), sp\n" #endif + +/*#if !DUMP_MODE + // do some hackery + "bit.w #0, done_irq\n" + "jnz .Lregular\n" + + // skip pc forward by 4 + "add.w #4, 2(sp)\n" + // set GIE in sr + "bis.w #8, 0(sp)\n" + // set timer counter for next IRQ for trace + "mov.w #1, TA1CCR0\n" + // restart timer + "bis.w #4, TA1CTL\n" + // done it now + "mov.w #1, done_irq\n" + // continue as usual + "reti\n" +#endif*/ + + ".Lregular:\n" "pushm.a #12, r15\n" "mov.a sp, r12\n" "call #do_collect\n" @@ -215,6 +253,7 @@ int main(void) { puts("hello world!\r\n"); + done_irq = 0; do_trace(); __builtin_unreachable(); }