rl78/g23 probe and glitching routines

This commit is contained in:
Triss 2022-07-18 11:38:06 +02:00
parent 8fab6d984c
commit 8820a9b40e
12 changed files with 801 additions and 174 deletions

View File

@ -11,7 +11,7 @@
#define TRIGGER_IN_PIN ZAP_TRIG_IN #define TRIGGER_IN_PIN ZAP_TRIG_IN
// use CROWBAR_1 / CROWBAR_2 / GLITCH_OUT to select glitching method // use CROWBAR_1 / CROWBAR_2 / GLITCH_OUT to select glitching method
#define GLITCH_OUT_PIN ZAP_CROWBAR_1 #define GLITCH_OUT_PIN ZAP_GLITCH_OUT/*ZAP_CROWBAR_1*/
#define PINOUT_SBW_PIO BREADBOARD_SBW_PIO #define PINOUT_SBW_PIO BREADBOARD_SBW_PIO
#define PINOUT_SBW_TCK (ZAP_GPIO_BASE+0) #define PINOUT_SBW_TCK (ZAP_GPIO_BASE+0)
@ -33,7 +33,7 @@
#define PINOUT_TOOL78_78K0R_FLMD0 (ZAP_GPIO_BASE+1) #define PINOUT_TOOL78_78K0R_FLMD0 (ZAP_GPIO_BASE+1)
#define PINOUT_TOOL78_78K0R_TOOL0 (ZAP_GPIO_BASE+2) #define PINOUT_TOOL78_78K0R_TOOL0 (ZAP_GPIO_BASE+2)
#define PINOUT_TOOL78_RL78_TOOL0 (ZAP_GPIO_BASE+1) #define PINOUT_TOOL78_RL78_TOOL0 (ZAP_GPIO_BASE+1) /* welp, lvl shifter pin2 is dead(?) */
#define PINOUT_TOOL78_RL78_TX (ZAP_GPIO_BASE+2) #define PINOUT_TOOL78_RL78_TX (ZAP_GPIO_BASE+2)
#define PINOUT_TOOL78_RL78_RX (ZAP_GPIO_BASE+3) #define PINOUT_TOOL78_RL78_RX (ZAP_GPIO_BASE+3)

View File

@ -33,8 +33,11 @@ void cli_tool78_g10_prototest(void);
void cli_tool78_g10_ocdtest(void); void cli_tool78_g10_ocdtest(void);
void cli_tool78_glitch_dump(void); void cli_tool78_glitch_dump(void);
void cli_tool78_glitch_dump_g23(void);
void cli_tool78_glitch_paramsearch(void); void cli_tool78_glitch_paramsearch(void);
void cli_tool78_glitch_param_g23(void);
void cli_tool78_glitch_ocd_dump(void); void cli_tool78_glitch_ocd_dump(void);
void cli_tool78_glitch_ocd_dump_g23(void);
void cli_tool78_glitch_param_g10(void); void cli_tool78_glitch_param_g10(void);
void cli_tool78_glitch_ocd_g10(void); void cli_tool78_glitch_ocd_g10(void);
@ -85,8 +88,11 @@ static struct cli_cmd cmds[] = {
{ "rl10ocd", cli_tool78_g10_ocdtest }, { "rl10ocd", cli_tool78_g10_ocdtest },
{ "g78dump", cli_tool78_glitch_dump }, { "g78dump", cli_tool78_glitch_dump },
{ "g23dump", cli_tool78_glitch_dump_g23 },
{ "g78param", cli_tool78_glitch_paramsearch }, { "g78param", cli_tool78_glitch_paramsearch },
{ "g23param", cli_tool78_glitch_param_g23 },
{ "g78ocd", cli_tool78_glitch_ocd_dump }, { "g78ocd", cli_tool78_glitch_ocd_dump },
{ "g23ocd", cli_tool78_glitch_ocd_dump_g23 },
{ "g10param", cli_tool78_glitch_param_g10 }, { "g10param", cli_tool78_glitch_param_g10 },
{ "g10ocd", cli_tool78_glitch_ocd_g10 }, { "g10ocd", cli_tool78_glitch_ocd_g10 },

View File

@ -16,13 +16,19 @@
#include "glitch.h" #include "glitch.h"
void cli_tool78_glitch_dump(void); void cli_tool78_glitch_dump(void);
void cli_tool78_glitch_dump_g23(void);
void cli_tool78_glitch_paramsearch(void); void cli_tool78_glitch_paramsearch(void);
void cli_tool78_glitch_param_g23(void);
void cli_tool78_glitch_ocd_dump(void); void cli_tool78_glitch_ocd_dump(void);
void cli_tool78_glitch_ocd_dump_g23(void);
void cli_tool78_glitch_param_g10(void); void cli_tool78_glitch_param_g10(void);
void cli_tool78_glitch_ocd_g10(void); void cli_tool78_glitch_ocd_g10(void);
#define DUMP_OFFSET 0xef000 #define USE_PICOEMP 0
#define DUMP_SIZE 4096/*65536*/ #define LEN_USE_ADC 0
#define DUMP_OFFSET /*0*//*0xee000*/
#define DUMP_SIZE /*0x100*/8192/*65536*/
// test with decoupling caps: length in 20..500(..1500) -> ok // test with decoupling caps: length in 20..500(..1500) -> ok
// testing on ocd lock: length: 5..35 // testing on ocd lock: length: 5..35
@ -45,25 +51,37 @@ sec: flg=fe bot=03 fsws=0000 fswe=003f
static uint8_t databuf[DUMP_SIZE]; static uint8_t databuf[DUMP_SIZE];
static struct glitch_param_randrange offset; static struct glitch_param_randrange offset;
static struct glitch_param_randrange/*adc*/ length; #if LEN_USE_ADC
static struct glitch_param_adc length;
#else
static struct glitch_param_randrange length;
#endif
//static struct glitch_param_const length; //static struct glitch_param_const length;
#define LENGTH_1 (50/*26*1000/3*/)
#define LENGTH_2 (40/*LENGTH_1/2*/)
static bool glitch_init_core1_stuff(bool exttrig, uint glitchpin) { static bool glitch_init_core1_stuff(bool exttrig, uint glitchpin) {
offset.min = 10*1000; offset.min = 10*1000;
offset.max = 35433*1000; offset.max = 35433*1000/25;
length.min = 100; length.min = 25;//100;
length.max = /*10*50*/26*1000; length.max = /*10*50*/LENGTH_1;
//length.value = 5*1000; // 5 us //length.value = 5*1000; // 5 us
#if LEN_USE_ADC
#if PINOUT_USE_DRAGONZAP #if PINOUT_USE_DRAGONZAP
//length.adc_index = 0;//999; length.adc_index = 0;//999;
#else #else
//length.adc_index = 999; length.adc_index = 999;
#endif
#endif #endif
glitch_param_randrange_init(&offset); glitch_param_randrange_init(&offset);
//glitch_param_const_init(&length); //glitch_param_const_init(&length);
#if LEN_USE_ADC
glitch_param_adc_init(&length);
#else
glitch_param_randrange_init(&length); glitch_param_randrange_init(&length);
//glitch_param_adc_init(&length); #endif
// REGC = 2.11V / 0.47..1 uF // WUFM: REGC = 1.80V // BUT: OCD mode: always 2.1! // 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){ static struct glitch_params gparam = (struct glitch_params){
@ -98,7 +116,11 @@ static bool glitch_init_core1_stuff(bool exttrig, uint glitchpin) {
}; };
gparam.length_ns = (struct glitch_param){ gparam.length_ns = (struct glitch_param){
.ud = &length, .ud = &length,
.getter = glitch_param_randrange_fn,//adc_fn #if LEN_USE_ADC
.getter = glitch_param_adc_fn
#else
.getter = glitch_param_randrange_fn
#endif
}; };
gparam.trigger_in_pin = exttrig ? TRIGGER_IN_PIN/*7*/ : (-1); gparam.trigger_in_pin = exttrig ? TRIGGER_IN_PIN/*7*/ : (-1);
return glitch_ready(&gparam); return glitch_ready(&gparam);
@ -137,13 +159,50 @@ static uint8_t DATA_test_dbg__paramtest[102] = {
0x0e, 0xd2, 0xdf, 0xf4, 0xef, 0xbf 0x0e, 0xd2, 0xdf, 0xf4, 0xef, 0xbf
}; };
static uint8_t DATA_test_dbg__paramtest_g23[] = {
0x71, 0x7b, 0xfa, 0xf5, 0xf0, 0x02, 0xf5, 0x78, 0x00, 0xce, 0x22, 0x00, 0xf5,
0x62, 0x00, 0xf5, 0x77, 0x00, 0xf5, 0x79, 0x00, 0xf5, 0x75, 0x00, 0xf5, 0x7c,
0x00, 0xf4, 0x02, 0xcb, 0xf8, 0x00, 0xfe, 0xce, 0x02, 0xff, 0xce, 0x02, 0xff,
0x30, 0x00, 0xc0, 0x30, 0x00, 0xc0, 0x16, 0x16, 0x52, 0x00, 0x53, 0xff, 0x51,
0x00, 0x81, 0x93, 0xdf, 0xfc, 0x92, 0x61, 0xf9, 0xdf, 0xf3, 0xf4, 0x02, 0xf4,
0x02, 0x52, 0x18, 0x53, 0xff, 0x93, 0xdf, 0xfd, 0x92, 0xdf, 0xf8, 0x51, 0x48,
0xfe, 0x16, 0x00, 0x51, 0x69, 0xfe, 0x11, 0x00, 0x50, 0xaa, 0x52, 0x00, 0x92,
0x61, 0xe9, 0x61, 0x78, 0xfe, 0x05, 0x00, 0xd2, 0xdf, 0xf5, 0xef, 0xba, 0x71,
0x7a, 0xaf, 0x00, 0x9e, 0xad, 0x31, 0xb4, 0xaf, 0xfc, 0x71, 0x3b, 0xaf, 0x71,
0x7b, 0xaf, 0xd7
};
static uint8_t dumper_shellcode[0x26] = { static uint8_t dumper_shellcode[0x26] = {
//0xe0, 0x07, 0x26, // 0xF07E0 location, 0x26 length of packet //0xe0, 0x07, 0x26, // 0xF07E0 location, 0x26 length of packet
0x41, 0x00, 0x34, 0x00, 0x00, 0x00, 0x11, 0x89, 0xFC, 0xA1, 0xFF, 0x0E, 0xA5, 0x41, 0x00, // mov es, #0
0x15, 0x44, 0x00, 0x00, 0xDF, 0xF3, 0xEF, 0x04, 0x55, 0x00, 0x00, 0x00, 0x8E, 0x34, 0x00, 0x00, // movw de, #0
0xFD, 0x81, 0x5C, 0x0F, 0x9E, 0xFD, 0x71, 0x00, 0x90, 0x00, 0xEF, 0xE0 // next:
0x00, 0x11, 0x89, // mov a, es:[de]
0xFC, 0xA1, 0xFF, 0x0E, // call !!0xeffa1
0xA5, // incw de
0x15, // movw ax, de
0x44, 0x00, 0x00, // cmpw ax, #0
0xDF, 0xF3, // bnz $next
0xEF, 0x04, // br $after_ocd_flag
0x55, // ocd_flag
// nop
// mov a, es
// inc a
// and a, #0xf
// mov es, a
0x00, 0x00, 0x00, 0x8E, 0xFD, 0x81, 0x5C, 0x0F, 0x9E, 0xFD, 0x71, 0x00, 0x90, 0x00,
0xEF, 0xE0 // br $next
}; };
static uint8_t dumper_g23[] = {
0x41, 0x00, 0x34, 0x00, 0x00, 0x11, 0x89, 0xef, 0x10, 0xa5, 0x15, 0x44, 0x00,
0x00, 0xdf, 0xf5, 0x8e, 0xfd, 0x81, 0x5c, 0x0f, 0x9e, 0xfd, 0xef, 0xec, 0x71,
0x7a, 0xaf, 0x00, 0x9e, 0xad, 0x31, 0xb4, 0xaf, 0xfc, 0x71, 0x3b, 0xaf, 0x71,
0x7b, 0xaf, 0xef, 0xde
};
static uint8_t G1M_payload_1[] = { static uint8_t G1M_payload_1[] = {
0xcb, 0xf8, 0xc0, 0xfe, // movw sp, #0xfea0 0xcb, 0xf8, 0xc0, 0xfe, // movw sp, #0xfea0
0xec, 0xba, 0xff, 0x0e, // br !!0xeffba 0xec, 0xba, 0xff, 0x0e, // br !!0xeffba
@ -166,7 +225,7 @@ static uint8_t G1M_paramtest[] = {
}; };
void cli_tool78_glitch_dump(void) { static void cli_tool78_glitch_dump_base(size_t pl_size, const uint8_t* payload) {
uint8_t passwd[10] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uint8_t passwd[10] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint16_t ver; uint16_t ver;
enum tool78_stat st; enum tool78_stat st;
@ -200,8 +259,7 @@ void cli_tool78_glitch_dump(void) {
goto deinit_bad; goto deinit_bad;
} }
st = tool78_ocd_write(&tool78_hw_rl78_uart1, 0xf900, st = tool78_ocd_write(&tool78_hw_rl78_uart1, 0xf900, pl_size, payload);
sizeof(dumper_shellcode), dumper_shellcode);
//printf("write shellcode res 0x%02x\n", st); //printf("write shellcode res 0x%02x\n", st);
if (st != 0) { if (st != 0) {
printf("shellcode write failed: %d\n", st); printf("shellcode write failed: %d\n", st);
@ -233,11 +291,20 @@ deinit_bad:
tool78_hw_rl78_uart1.deinit(); tool78_hw_rl78_uart1.deinit();
return; return;
} }
void cli_tool78_glitch_dump(void) {
cli_tool78_glitch_dump_base(sizeof(dumper_shellcode), dumper_shellcode);
}
void cli_tool78_glitch_dump_g23(void) {
cli_tool78_glitch_dump_base(sizeof(dumper_g23), dumper_g23);
}
void cli_tool78_glitch_paramsearch(void) { static void glitch_paramsearch_base(size_t pl_size, const uint8_t* payload) {
zap_gpio_set_en(true);
#if USE_PICOEMP
zap_picoemp_init(); zap_picoemp_init();
#endif
if (!glitch_init_core1_stuff(true, ZAP_GLITCH_OUT/*GLITCH_OUT_PIN*/)) { if (!glitch_init_core1_stuff(true, GLITCH_OUT_PIN)) {
printf("bad glitcher params!\n"); printf("bad glitcher params!\n");
return; return;
} }
@ -250,12 +317,15 @@ void cli_tool78_glitch_paramsearch(void) {
bool first = true; bool first = true;
restart: restart:
#if USE_PICOEMP
zap_picoemp_set_armed(false); zap_picoemp_set_armed(false);
#endif
glitch_disarm(); glitch_disarm();
/*busy_wait_ms(40);*/ /*busy_wait_ms(40);*/
#if USE_PICOEMP
zap_picoemp_set_armed(true); zap_picoemp_set_armed(true);
while (!zap_picoemp_has_hv()) ; #endif
ver=0; ver=0;
st = tool78_init_ocd(&tool78_hw_rl78_uart1, &ver, passwd); st = tool78_init_ocd(&tool78_hw_rl78_uart1, &ver, passwd);
@ -285,14 +355,17 @@ restart:
printf("trampoline write failed: %d\n", st); printf("trampoline write failed: %d\n", st);
goto deinit_bad; goto deinit_bad;
} }
st = tool78_ocd_write(&tool78_hw_rl78_uart1, 0xf900, st = tool78_ocd_write(&tool78_hw_rl78_uart1, 0xf900, pl_size, payload);
sizeof(DATA_test_dbg__paramtest), DATA_test_dbg__paramtest);
//printf("write code res 0x%02x\n", st); //printf("write code res 0x%02x\n", st);
if (st != 0) { if (st != 0) {
printf("code write failed: %d\n", st); printf("code write failed: %d\n", st);
goto deinit_bad; goto deinit_bad;
} }
#if USE_PICOEMP
while (!zap_picoemp_has_hv()) ;
#endif
st = tool78_ocd_exec(&tool78_hw_rl78_uart1); st = tool78_ocd_exec(&tool78_hw_rl78_uart1);
//printf("exec res 0x%02x\n", st); //printf("exec res 0x%02x\n", st);
if (st != 0) { if (st != 0) {
@ -370,19 +443,33 @@ restart:
} }
first_=false; first_=false;
if (!zap_picoemp_has_hv()) {
#if USE_PICOEMP
while (!zap_picoemp_has_hv()) {
rr = tool78_hw_rl78_uart1.recv(2, checkbuf, 150);
if (rr == 2 && (checkbuf[0] != 'H' || checkbuf[1] != 'i')) rr = 0;
if (rr == 2) {
rr = tool78_hw_rl78_uart1.recv(256, checkbuf, 120*1000);
}
}
#endif
glitch_arm();
rr = tool78_hw_rl78_uart1.recv(2, checkbuf, 150*1000); rr = tool78_hw_rl78_uart1.recv(2, checkbuf, 150*1000);
} else break; glitch_disarm();
} while (true); } while (true);
} }
deinit_bad: deinit_bad:
#if USE_PICOEMP
zap_picoemp_set_armed(false); zap_picoemp_set_armed(false);
#endif
tool78_hw_rl78_uart1.deinit(); tool78_hw_rl78_uart1.deinit();
return; return;
do_reset_stuff: do_reset_stuff:
#if USE_PICOEMP
zap_picoemp_set_armed(false); zap_picoemp_set_armed(false);
#endif
tool78_hw_rl78_uart1.deinit(); tool78_hw_rl78_uart1.deinit();
// glitch for way too long to power cycle // glitch for way too long to power cycle
@ -392,6 +479,13 @@ do_reset_stuff:
goto restart; goto restart;
} }
void cli_tool78_glitch_paramsearch(void) {
glitch_paramsearch_base(sizeof(DATA_test_dbg__paramtest), DATA_test_dbg__paramtest);
}
void cli_tool78_glitch_param_g23(void) {
glitch_paramsearch_base(sizeof(DATA_test_dbg__paramtest_g23), DATA_test_dbg__paramtest_g23);
}
void cli_tool78_glitch_ocd_dump(void) { void cli_tool78_glitch_ocd_dump(void) {
if (!glitch_init_core1_stuff(false, GLITCH_OUT_PIN)) { if (!glitch_init_core1_stuff(false, GLITCH_OUT_PIN)) {
@ -399,9 +493,9 @@ void cli_tool78_glitch_ocd_dump(void) {
return; return;
} }
/*gpio_set_function(2, GPIO_FUNC_SIO); gpio_set_function(11, GPIO_FUNC_SIO);
gpio_set_dir(2, GPIO_OUT); gpio_set_dir(11, GPIO_OUT);
gpio_put(2, false);*/ gpio_put(11, false);
//gpio_set_function(3, GPIO_FUNC_SIO); //gpio_set_function(3, GPIO_FUNC_SIO);
//gpio_set_dir(3, GPIO_OUT); //gpio_set_dir(3, GPIO_OUT);
@ -489,7 +583,7 @@ do_reset_stuff:
goto restart; goto restart;
success:; success:;
//gpio_put(2, true); gpio_put(11, true);
//busy_wait_ms(5); //busy_wait_ms(5);
// (02): read from above (checkbuf) code // (02): read from above (checkbuf) code
// 03 06 18 00 df 03 // 03 06 18 00 df 03
@ -567,6 +661,253 @@ deinit_bad:
return; return;
} }
void cli_tool78_glitch_ocd_dump_g23(void) {
zap_gpio_set_en(true);
#if USE_PICOEMP
zap_picoemp_init();
#endif
if (!glitch_init_core1_stuff(false, GLITCH_OUT_PIN)) {
printf("bad glitcher params!\n");
return;
}
gpio_set_function(14, GPIO_FUNC_SIO);
gpio_set_dir(14, GPIO_OUT);
//gpio_put(16, true);
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;
bool phase1;
restart:
#if USE_PICOEMP
zap_picoemp_set_armed(false);
#endif
glitch_disarm();
#if USE_PICOEMP
zap_picoemp_set_armed(true);
while (!zap_picoemp_has_hv()) ;
#endif
tool78_hw_rl78_uart1.flags &= ~tool78_hw_flag_done_reset;
phase1 = true;
((struct glitch_param_randrange*)glitch_param_cur.length_ns.ud)->max = LENGTH_1;
//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) {
//gpio_put(11, true);
printf("aaaa\n");
//printf("glitch len: %lu ns\n", *(volatile uint32_t*)&glitch_param_cur.length_ns.cur);
busy_wait_ms(1000);
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;
glitch_continue:
//tool78_hw_rl78_uart1.rx_set_stop_bit(false);
glitch_arm();
for (size_t i = 0; i < (phase1 ? 16 : 64); ++i) {
#if USE_PICOEMP
while (!zap_picoemp_has_hv()) {
rr = tool78_hw_rl78_uart1.recv(1, checkbuf, 150);
if (rr > 0) goto welp;
}
#endif
//glitch_trigger_sw_core1();
glitch_trigger_sw_pio();
rr = tool78_hw_rl78_uart1.recv(1, checkbuf, 12*1000);
welp:
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();
busy_wait_ms(15);
//gpio_put(16, false);
// glitch for way too long to power cycle
/*sio_hw->gpio_set = 1u << GLITCH_OUT_PIN;
sio_hw->gpio_clr = 1u << GLITCH_OUT_PIN;*/
//busy_wait_ms(15);
//gpio_put(16, true);
//busy_wait_ms(15);
goto restart;
success:;
//busy_wait_ms(5);
if (phase1) {
// (02): read from above (checkbuf) code
// 01 XX YY 03
// ^-- baud rate set response
// ^ XX is some err. code (variable, should be 0x23 but can vary due to glitch), YY is checksum
//gpio_put(11, true);
rr = tool78_hw_rl78_uart1.recv(4, &databuf[0], 10000);
if (rr != 4) {
printf("wut? rr=%d prev=%02x\n", rr, checkbuf[0]);
goto do_reset_stuff;
} else {
//gpio_put(14, true);
printf("glitch phase1 done: %02x %02x %02x %02x %02x\n", checkbuf[0],
databuf[0], databuf[1], databuf[2], databuf[3]);
printf("glitch len: %lu ns\n", *(volatile uint32_t*)&glitch_param_cur.length_ns.cur);
busy_wait_ms(1); // time to settle
phase1 = false;
((struct glitch_param_randrange*)glitch_param_cur.length_ns.ud)->max = LENGTH_2;
//gpio_put(14, false);
goto glitch_continue;
}
} else {
// (02): read from above (checkbuf) code
// 03 06 18 00 df 03
// 00
gpio_put(14, true);
rr = tool78_hw_rl78_uart1.recv(6, &databuf[0], 10000);
if (rr != 6) {
printf("wut? rr=%d prev=%02x\n", rr, checkbuf[0]);
restart_to_ph1:
phase1 = true;
((struct glitch_param_randrange*)glitch_param_cur.length_ns.ud)->max = LENGTH_1;
gpio_put(14, false);
goto do_reset_stuff;
} else {
printf("glitch phase2 done: %02x %02x %02x %02x %02x %02x %02x\n",
checkbuf[0], databuf[0], databuf[1], databuf[2],
databuf[3], databuf[4], databuf[5]);
printf("glitch len: %lu ns\n", *(volatile uint32_t*)&glitch_param_cur.length_ns.cur);
busy_wait_ms(1); // time to settle
rr = tool78_hw_rl78_uart1.recv(1, &checkbuf[0], 10000);
if (rr != 1) {
printf("wut? rr=%d no ack null byte\n", rr);
goto restart_to_ph1;
}
printf("got ack!\n");
}
}
#if USE_PICOEMP
zap_picoemp_set_armed(false);
#endif
glitch_disarm();
busy_wait_us_32(500);
gpio_put(14, false);
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);
/*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_g23), dumper_g23);
//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] = { /*static uint8_t DATA_G1M_paramtest[47] = {
0xcf, 0x77, 0x00, 0x00, 0xce, 0x00, 0x00, 0xcf, 0x30, 0x00, 0x00, 0xcf, 0x50, 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, 0x00, 0x00, 0xcf, 0x60, 0x00, 0x7f, 0xcf, 0x20, 0xff, 0x00, 0xcf, 0xf0, 0x00,

View File

@ -38,6 +38,17 @@ static uint8_t G1M_test_2[] = {
0xd7, // ret 0xd7, // ret
}; };
static uint8_t G23_test[19] = {
0x51, 0x61, // mov a, #'a'
0x71, 0x7a, 0xaf, // set1 ASIM.7
0x00, // nop
0x9e, 0xad, // mov TXS, a
0x31, 0xb4, 0xaf, 0xfc, // bf ASIM.3, $.
0x71, 0x3b, 0xaf, // clr1 ASIM.3
0x71, 0x7b, 0xaf, // clr1 ASIM.7
0xd7 // ret
};
//static uint8_t DATA_test_dbg[7/*85*/] = { //static uint8_t DATA_test_dbg[7/*85*/] = {
// /*0xe0, 0x07, 0x52,*/ 0x51, 0x61, 0xfc, 0xa1, 0xff, 0x0e, // /*0xe0, 0x07, 0x52,*/ 0x51, 0x61, 0xfc, 0xa1, 0xff, 0x0e,
@ -178,8 +189,13 @@ void cli_tool78_ocdtest(void) {
// can't write too much at 0xf07e0 as 0xf0800 and up contains OCD state, // can't write too much at 0xf07e0 as 0xf0800 and up contains OCD state,
// overwrite this and suddenly the OCD system resets itself // overwrite this and suddenly the OCD system resets itself
if (ver < 0x500) {
st = tool78_ocd_write(&tool78_hw_rl78_uart1, 0x07e0, st = tool78_ocd_write(&tool78_hw_rl78_uart1, 0x07e0,
sizeof(shellcode_test), shellcode_test); sizeof(shellcode_test), shellcode_test);
} else {
st = tool78_ocd_write(&tool78_hw_rl78_uart1, 0x07e0,
sizeof(G23_test), G23_test);
}
//printf("write shellcode res 0x%02x\n", st); //printf("write shellcode res 0x%02x\n", st);
if (st != 0) { if (st != 0) {
printf("shellcode write failed: %d\n", st); printf("shellcode write failed: %d\n", st);
@ -193,6 +209,21 @@ void cli_tool78_ocdtest(void) {
goto deinit_bad; goto deinit_bad;
} }
// wait for completion
rr = tool78_hw_rl78_uart1.recv(1, checkbuf, 120*1000*1000);
if (rr != 1) {
printf("exec code: no response :/ (%d)\n", rr);
goto deinit_bad;
}
printf("result: '%c' (0x%02x)\n", checkbuf[0], checkbuf[0]);
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;
}
// wait for completion // wait for completion
rr = tool78_hw_rl78_uart1.recv(1, checkbuf, 120*1000*1000); rr = tool78_hw_rl78_uart1.recv(1, checkbuf, 120*1000*1000);
if (rr != 1) { if (rr != 1) {

View File

@ -127,7 +127,7 @@ static void CORE1_FUNC(glitch_core1_thread_core1_fifoirq)(void) {
CORE1_DO_GLITCH(); CORE1_DO_GLITCH();
multicore_fifo_drain(); multicore_fifo_drain();
multicore_fifo_clear_irq(); multicore_fifo_clear_irq();
gpio_put(25, true); //gpio_put(25, true);
continue_: continue_:
irq_set_enabled(irq, true); irq_set_enabled(irq, true);
} }
@ -151,6 +151,7 @@ static void CORE1_FUNC(glitch_core1_thread_core1_gpio)(void) {
CORE1_PRE_CALC(); CORE1_PRE_CALC();
__WFI(); __WFI();
//while (!(sio_hw->gpio_in & (1u<<gpio))) ;
iobank0_hw->intr[gpio>>3] = event << 4*(gpio&7); // acknowledge irq iobank0_hw->intr[gpio>>3] = event << 4*(gpio&7); // acknowledge irq
bool arm = *(volatile bool*)&param_cur.armed; bool arm = *(volatile bool*)&param_cur.armed;
if (!arm) continue; if (!arm) continue;
@ -166,6 +167,7 @@ static void CORE1_FUNC(glitch_core1_thread_core1_gpio)(void) {
sio_hw->gpio_clr = iom; sio_hw->gpio_clr = iom;
cont: cont:
irq_set_enabled(irq, true); irq_set_enabled(irq, true);
//while ((sio_hw->gpio_in & (1u<<gpio))) ;
} }
} }
__attribute__((__noreturn__)) __attribute__((__noreturn__))
@ -178,6 +180,7 @@ static void CORE1_FUNC(glitch_core1_thread_pio)(void) {
irq_set_enabled(irq, true); irq_set_enabled(irq, true);
while (true) { while (true) {
//gpio_put(25, gpio_get(10));
CORE1_PRE_CALC(); CORE1_PRE_CALC();
(void)iom; (void)iom;
param_cur.offset_ns.cur = off; param_cur.offset_ns.cur = off;
@ -185,9 +188,8 @@ static void CORE1_FUNC(glitch_core1_thread_pio)(void) {
trigctl_push_off_len(trigctl_pio, trigctl_sm, off>>2, len>>2); trigctl_push_off_len(trigctl_pio, trigctl_sm, off>>2, len>>2);
trigctl_wait_glitch_irq(trigctl_pio, trigctl_sm, true); trigctl_wait_glitch_irq(trigctl_pio, trigctl_sm, true);
trigctl_ack_glitch_irq(trigctl_pio, trigctl_sm);
//gpio_put(25, true);
//sio_hw->gpio_togl = 1u<<25; //sio_hw->gpio_togl = 1u<<25;
trigctl_ack_glitch_irq(trigctl_pio, trigctl_sm);
} }
} }

View File

@ -252,7 +252,7 @@ inline static enum tool78_stat tool78_data_recv(struct tool78_hw* hw,
/*#define tool78_wait_status(hw, l, timeout_us, ...) \ /*#define tool78_wait_status(hw, l, timeout_us, ...) \
tool78_wait_status__impl(hw, l, timeout_us, __VA_OPT__(1 ? __VA_ARGS__ : ) -1) \ tool78_wait_status__impl(hw, l, timeout_us, __VA_OPT__(1 ? __VA_ARGS__ : ) -1) \
*/ */
static enum tool78_stat tool78_wait_status/*__impl*/(struct tool78_hw* hw, int l, int timeout_us/*, int minl*/) { static enum tool78_stat tool78_wait_status__impl(struct tool78_hw* hw, int l, int timeout_us/*, int minl*/, const char* fnname, int line) {
/*if (hw->target == tool78k0_spi && timeout_us >= 0) { /*if (hw->target == tool78k0_spi && timeout_us >= 0) {
busy_wait_us_32(timeout_us); busy_wait_us_32(timeout_us);
timeout_us *= 2; timeout_us *= 2;
@ -289,9 +289,10 @@ static enum tool78_stat tool78_wait_status/*__impl*/(struct tool78_hw* hw, int l
busy_wait_us_32(timeout_us/64); busy_wait_us_32(timeout_us/64);
} }
printf("wait t/o\n"); printf("wait t/o: %s:%d\n", fnname, line);
return tool78_stat_timeout_error; return tool78_stat_timeout_error;
} }
#define tool78_wait_status(hw, l, to) tool78_wait_status__impl(hw, l, to, __func__, __LINE__);
// ---- // ----
@ -1115,7 +1116,8 @@ int tool78_ocd_version(struct tool78_hw* hw, uint16_t* ver) {
return -1; return -1;
} }
*ver = bytes[0] | ((uint16_t)bytes[1] << 8); // BCD, so big-endian
*ver = bytes[1] | ((uint16_t)bytes[0] << 8);
return 0; return 0;
} }

View File

@ -5,6 +5,10 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
// NOTE:
// * RL78/x1y flash block size: 0x400
// * RL78/x2y flash block size: 0x800
enum tool78_target { enum tool78_target {
tool78k0_uart2 = 0x12, tool78k0_uart2 = 0x12,
tool78k0_spi = 0x13, tool78k0_spi = 0x13,
@ -44,7 +48,8 @@ enum tool78_entry {
// TOOL0 initial byte values // TOOL0 initial byte values
tool78_entry_rl78_uart1 = 0x3a, tool78_entry_rl78_uart1 = 0x3a,
tool78_entry_rl78_uart2 = 0x00, tool78_entry_rl78_uart2 = 0x00,
tool78_entry_rl78_ocd = 0xc5 tool78_entry_rl78_ocd = 0xc5,
tool78_entry_rl78_ocd2 = 0xca, // 2-wire OCD (RL78/G23 only)
}; };
// TODO: initial baudrates? 9600 for 78k, 115.2k for RL78 // TODO: initial baudrates? 9600 for 78k, 115.2k for RL78
@ -141,6 +146,7 @@ enum tool78ocd_cmd {
// execute code at 0xf07e0 (TODO: verify addr across versions) // execute code at 0xf07e0 (TODO: verify addr across versions)
tool78ocd_cmd_exec = 0x94, tool78ocd_cmd_exec = 0x94,
tool78ocd_cmd_exit_reti = 0x95, // TODO: what is this? tool78ocd_cmd_exit_reti = 0x95, // TODO: what is this?
// TODO: 96 too?
tool78ocd_cmd_exit_ram = 0x97, // TODO: what is this? tool78ocd_cmd_exit_ram = 0x97, // TODO: what is this?
tool78ocd_cmdg10_connect = 0x55, tool78ocd_cmdg10_connect = 0x55,

View File

@ -1,135 +0,0 @@
/*#include "romhdr.S"*/
#include "hw.S"
.global _start
_start:
;mov a, #'a'
;call !!0xeffa1
;ret
; call !hw_init
;1: call !glitch_mainloop
; br $1b
;1: br $1b
hw_init:
di
clrb !CRC0CTL
clrb !IAWCTL
;CRC0CTL = 0 ; f02f0
;IAWCTL = 0 ; f0078
; CSC=fffa1
; CKC=fffa4
;CMC = 0 ; 0xfffa0
;MSTOP = 1 ; CSC.7
;MCM0 = 0 ; CKC.4
;XTSTOP = 0 ; CSC.6
;OSMC = 0 ; f00f3
;CSS = 0 ; CKC.6 ;!
set1 CKC.6
;HIOSTOP = 0 ; CSC.0
mov !ADPC, #1
;ADPC = 1 ; f0076
mov PM2, #0
clrb !PMC2
clrb !PIOR0
clrb !PIOR1
clrb !PIOR2
clrb !PIOR3
mov P2, #0
; ret
/* DUMPS EVERYTHING */
/* LONG WAITCODE THAT DOESNT DO ANYTHING */
/* mov c, #0xff
mov b, #0xff
1: dec c
bnz $1b
mov c, #0xff
dec b
bnz $1b
xor P2, #0xff
br $1b*/
/* GLITCH TESTING CODE */
/* TODO: how many segments do we need? */
mov es, #0
call !dump_segment
1: br $1b
dump_segment:
movw hl, #0
1: mov a, es:[hl]
push hl
call !!tool_tx
pop hl
incw hl
movw ax, hl
cmpw ax, #0
bnz $1b
mov es, #0xf
ret
/*
glitch_mainloop:
mov P2, #0xff
movw ax, #0xfa00
movw hl, ax
mov c, #0
2: mov b, #0xff
mov a, #0
1: inc a
dec b
bnz $1b
dec c
mov [hl+c], a
bnz $2b
mov P2, #0
; wait a bit
mov c, #0x18
4: mov b, #0xff
5: dec b
bnz $5b
dec c
bnz $4b
mov a, #'H'
call !!tool_tx
mov a, #'i'
call !!tool_tx
mov x, #0xaa
mov c, #0
3: dec c
mov a, [hl+c]
xor a, x
call !!tool_tx
cmp0 c
bnz $3b
br $glitch_mainloop
;ret
;data:
*/

1
test/rl78/test.S Symbolic link
View File

@ -0,0 +1 @@
test_g13_param.S

View File

@ -0,0 +1,91 @@
/*#include "romhdr.S"*/
#include "hw.S"
.global _start
_start:
;mov a, #'a'
;call !!0xeffa1
;ret
di
clrb !CRC0CTL
clrb !IAWCTL
;CRC0CTL = 0 ; f02f0
;IAWCTL = 0 ; f0078
; CSC=fffa1
; CKC=fffa4
;CMC = 0 ; 0xfffa0
;MSTOP = 1 ; CSC.7
;MCM0 = 0 ; CKC.4
;XTSTOP = 0 ; CSC.6
;OSMC = 0 ; f00f3
;CSS = 0 ; CKC.6 ;!
set1 CKC.6
;HIOSTOP = 0 ; CSC.0
mov !ADPC, #1
;ADPC = 1 ; f0076
mov PM2, #0
clrb !PMC2
clrb !PIOR0
clrb !PIOR1
clrb !PIOR2
clrb !PIOR3
mov P2, #0
glitch_mainloop:
mov P2, #0xff
movw ax, #0xfa00
movw hl, ax
mov c, #0
2: mov b, #0xff
mov a, #0
1: inc a
dec b
bnz $1b
dec c
mov [hl+c], a
bnz $2b
mov P2, #0
; wait a bit
mov c, #0x18
4: mov b, #0xff
5: dec b
bnz $5b
dec c
bnz $4b
mov a, #'H'
call !!tool_tx
mov a, #'i'
call !!tool_tx
mov x, #0xaa
mov c, #0
3: dec c
mov a, [hl+c]
xor a, x
call !!tool_tx
cmp0 c
bnz $3b
; wait a bit
mov c, #0x30
4: mov b, #0xff
5: dec b
bnz $5b
dec c
bnz $4b
br $glitch_mainloop

41
test/rl78/test_g23_ocd.S Normal file
View File

@ -0,0 +1,41 @@
/*#include "romhdr.S"*/
#include "hw.S"
#define REG_ASIM 0xfffaf
#define REG_TXS 0xfffad
.global _start
_start:
/* ROM starts at 0xee000 on G23 */
mov es, #0
movw de, #0
/*mov a, es:[de]
mov a, #'a'*/
next:
mov a, es:[de]
br $tool_tx_fake
return_bleh:
incw de
movw ax, de
cmpw ax, #0
bnz $next
mov a, es
inc a
and a, #0xf
mov es, a
br $next
tool_tx_fake:
set1 REG_ASIM.7
nop
mov REG_TXS, a
wait_sent:
bf REG_ASIM.3, $wait_sent
clr1 REG_ASIM.3
clr1 REG_ASIM.7
br $return_bleh
/*ret*/

106
test/rl78/test_g23_param.S Normal file
View File

@ -0,0 +1,106 @@
/*#include "romhdr.S"*/
#include "hw.S"
#define REG_ASIM 0xfffaf
#define REG_TXS 0xfffad
#define tool_tx_g23 0xeeac0
/*#define TX_FUNC !!tool_tx_g23*/
#define TX_FUNC $!my_tool_tx
.global _start
_start:
;mov a, #'a'
;call !!0xeffa1
;ret
di
clrb !CRC0CTL
clrb !IAWCTL
;CRC0CTL = 0 ; f02f0
;IAWCTL = 0 ; f0078
; CSC=fffa1
; CKC=fffa4
;CMC = 0 ; 0xfffa0
;MSTOP = 1 ; CSC.7
;MCM0 = 0 ; CKC.4
;XTSTOP = 0 ; CSC.6
;OSMC = 0 ; f00f3
;CSS = 0 ; CKC.6 ;!
;set1 CKC.6
;HIOSTOP = 0 ; CSC.0
; mov !ADPC, #1
;ADPC = 1 ; f0076
mov PM2, #0
clrb !PMC2
clrb !PIOR0
clrb !PIOR1
clrb !PIOR2
clrb !PIOR3
clrb P2
movw sp, #0xfe00
glitch_mainloop:
mov P2, #0xff
mov P2, #0xff
movw ax, #0xc000
movw ax, #0xc000
movw hl, ax
movw hl, ax
mov c, #0
2: mov b, #0xff
mov a, #0
1: inc a
dec b
bnz $1b
dec c
mov [hl+c], a
bnz $2b
clrb P2
clrb P2
; wait a bit
mov c, #0x18
4: mov b, #0xff
5: dec b
bnz $5b
dec c
bnz $4b
mov a, #'H'
call TX_FUNC
mov a, #'i'
call TX_FUNC
mov x, #0xaa
mov c, #0
3: dec c
mov a, [hl+c]
xor a, x
call TX_FUNC
cmp0 c
bnz $3b
br $glitch_mainloop
my_tool_tx:
set1 REG_ASIM.7
nop
mov REG_TXS, a
wait_sent:
bf REG_ASIM.3, $wait_sent
clr1 REG_ASIM.3
clr1 REG_ASIM.7
ret

135
test/rl78/test_old.S Normal file
View File

@ -0,0 +1,135 @@
/*#include "romhdr.S"*/
#include "hw.S"
.global _start
_start:
;mov a, #'a'
;call !!0xeffa1
;ret
; call !hw_init
;1: call !glitch_mainloop
; br $1b
;1: br $1b
hw_init:
di
clrb !CRC0CTL
clrb !IAWCTL
;CRC0CTL = 0 ; f02f0
;IAWCTL = 0 ; f0078
; CSC=fffa1
; CKC=fffa4
;CMC = 0 ; 0xfffa0
;MSTOP = 1 ; CSC.7
;MCM0 = 0 ; CKC.4
;XTSTOP = 0 ; CSC.6
;OSMC = 0 ; f00f3
;CSS = 0 ; CKC.6 ;!
set1 CKC.6
;HIOSTOP = 0 ; CSC.0
mov !ADPC, #1
;ADPC = 1 ; f0076
mov PM2, #0
clrb !PMC2
clrb !PIOR0
clrb !PIOR1
clrb !PIOR2
clrb !PIOR3
mov P2, #0
; ret
/* DUMPS EVERYTHING */
/* LONG WAITCODE THAT DOESNT DO ANYTHING */
/* mov c, #0xff
mov b, #0xff
1: dec c
bnz $1b
mov c, #0xff
dec b
bnz $1b
xor P2, #0xff
br $1b*/
/* GLITCH TESTING CODE */
/* TODO: how many segments do we need? */
mov es, #0
call !dump_segment
1: br $1b
dump_segment:
movw hl, #0
1: mov a, es:[hl]
push hl
call !!tool_tx
pop hl
incw hl
movw ax, hl
cmpw ax, #0
bnz $1b
mov es, #0xf
ret
/*
glitch_mainloop:
mov P2, #0xff
movw ax, #0xfa00
movw hl, ax
mov c, #0
2: mov b, #0xff
mov a, #0
1: inc a
dec b
bnz $1b
dec c
mov [hl+c], a
bnz $2b
mov P2, #0
; wait a bit
mov c, #0x18
4: mov b, #0xff
5: dec b
bnz $5b
dec c
bnz $4b
mov a, #'H'
call !!tool_tx
mov a, #'i'
call !!tool_tx
mov x, #0xaa
mov c, #0
3: dec c
mov a, [hl+c]
xor a, x
call !!tool_tx
cmp0 c
bnz $3b
br $glitch_mainloop
;ret
;data:
*/