forked from rehius/usk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathglitch.c
213 lines (190 loc) · 6.52 KB
/
glitch.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#include "pico/stdlib.h"
#include "hardware/pio.h"
#include "emmc.pio.h"
#include "pins.h"
#include "glitch.h"
#include <stdio.h>
#include "misc.h"
#include "board_detect.h"
#include "hardware/structs/rosc.h"
extern uint32_t gsniff_pio_offset;
extern uint32_t dsniff_pio_offset;
extern uint32_t gtrig_pio_offset;
void init_gsniff_pio() {
pio_sm_config c = glitch_sniff_cmd_program_get_default_config(gsniff_pio_offset);
sm_config_set_in_pins(&c, PIN_CMD);
sm_config_set_jmp_pin(&c, PIN_CMD);
sm_config_set_in_shift(&c, false, true, 32);
sm_config_set_out_shift(&c, false, false, 32);
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX);
pio_sm_init(pio1, G_SNIFF_SM, gsniff_pio_offset, &c);
pio_sm_set_enabled(pio1, G_SNIFF_SM, true);
}
void init_dat0_pio() {
pio_sm_config c = glitch_dat_waiter_program_get_default_config(dsniff_pio_offset);
sm_config_set_in_pins(&c, PIN_DAT);
sm_config_set_jmp_pin(&c, PIN_DAT);
sm_config_set_in_shift(&c, false, true, 32);
sm_config_set_out_shift(&c, false, false, 32);
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX);
pio_sm_init(pio1, G_DAT0_SM, dsniff_pio_offset, &c);
pio_sm_set_enabled(pio1, G_DAT0_SM, true);
}
extern bool mariko;
void init_trigger_pio() {
uint offset = gtrig_pio_offset;
pio_sm_config c = glitch_trigger_program_get_default_config(offset);
sm_config_set_sideset_pins (&c, gli_pin());
sm_config_set_out_shift(&c, false, true, 32);
pio_sm_set_consecutive_pindirs(pio1, G_TRIG_SM, gli_pin(), 1, true);
pio_sm_init(pio1, G_TRIG_SM, offset, &c);
pio_sm_set_enabled(pio1, G_TRIG_SM, true);
pio_gpio_init(pio1, gli_pin());
gpio_set_slew_rate(gli_pin(), GPIO_SLEW_RATE_FAST);
}
void init_glitch_pio() {
for (int i = PIN_CLK; i <= PIN_DAT; i++)
{
gpio_init(i);
gpio_enable_input_output(i);
gpio_pull_up(i);
}
gpio_init(gli_pin());
init_gsniff_pio();
init_dat0_pio();
init_trigger_pio();
}
void deinit_glitch_pio() {
pio_set_sm_mask_enabled(pio1, 0x3, false);
for (int i = PIN_CLK; i <= PIN_DAT; i++)
{
gpio_deinit(i);
gpio_disable_pulls(i);
gpio_disable_input_output(i);
}
gpio_deinit(gli_pin());
}
int do_glitch(int delay, int width, int total_ms, int after_ms) {
// at this point CPU must be reset
init_glitch_pio();
pio_sm_put_blocking(pio1, G_TRIG_SM, delay);
pio_sm_put_blocking(pio1, G_TRIG_SM, width);
bool glitch_started = false;
uint32_t last_word = 0;
uint32_t data_count = 0;
int result = GLITCH_RESULT_MISSING;
bool detected = false;
absolute_time_t detect_time = make_timeout_time_ms(20);
absolute_time_t full_time = make_timeout_time_ms(total_ms);
absolute_time_t tio_time = detect_time;
while (!time_reached(tio_time)) {
if (!pio_sm_is_rx_fifo_empty(pio1, G_DAT0_SM)) {
uint32_t temp = pio_sm_get(pio1, G_DAT0_SM);
}
if (!pio_sm_is_rx_fifo_empty(pio1, G_SNIFF_SM)) {
uint32_t cur_word = pio_sm_get(pio1, G_SNIFF_SM);
if (!detected && (cur_word >> 24) == 0x3F) {
tio_time = full_time;
detected = true;
}
if (glitch_started)
data_count += 1;
if (last_word == 0x51000000 && cur_word == 0x1351) {
if (!glitch_started)
tio_time = make_timeout_time_ms(after_ms);
glitch_started = true;
}
if (last_word == 0x51000000 && cur_word == 0x142F) {
result = GLITCH_RESULT_FAILURE;
break;
}
if (last_word == 0x40aa5458 && cur_word == 0xba3b) {
result = GLITCH_RESULT_SUCCESS;
break;
}
if (data_count == 10) {
tio_time = full_time;
}
last_word = cur_word;
}
}
deinit_glitch_pio();
if (result == GLITCH_RESULT_MISSING && glitch_started) {
result = GLITCH_RESULT_TIMEOUT;
}
return result;
}
int tries = 0;
// Green pulsing implementation.
void inc_tries()
{
tries += 1;
if(tries & 1)
put_pixel(PIX_g);
else
put_pixel(PIX_gre);
}
// random() for glitch offset array generation
static uint32_t get_random_word(int cycles) {
uint32_t byte;
assert(rosc_hw->status & ROSC_STATUS_ENABLED_BITS);
for(int i=0; i < cycles; i++) {
busy_wait_at_least_cycles(100);
byte = ((byte << 1) | rosc_hw->randombit);
}
return byte;
}
int offsets_array[OFFSET_CNT];
void prepare_random_array()
{
for(int i = 0; i < OFFSET_CNT; i++)
offsets_array[i] = OFFSET_MIN + OFFSET_DIV*i;
for (int i = OFFSET_CNT - 1; i > 0; i--) {
size_t j = get_random_word(32) % (i+1);
int t = offsets_array[j];
offsets_array[j] = offsets_array[i];
offsets_array[i] = t;
}
}
bool glitch_try_offset(int offset, int * width, int edge_limit) {
int last_res = GLITCH_RESULT_SUCCESS;
int edges = 0;
int step = tries == 0 ? 32 : 8; // first ever edge search should be faster
int missing_count = 0;
inc_tries();
while (1) {
reset_cpu();
int gres = do_glitch(offset + get_random_word(3), *width, 300, 6);
if (gres == GLITCH_RESULT_MISSING)
missing_count +=1; // MMC has failed to initialize
else
missing_count = 0;
if (missing_count >= 5)
halt_with_error(4, 3); // something wrong with eMMC, cannot init properly
if (*width == 1) {
halt_with_error(5, 3);
}
if (*width >= 1000) { // no reaction to the glitch, hardware failure or bad mosfet wire
halt_with_error(6, 3);
}
if ((last_res == GLITCH_RESULT_TIMEOUT && gres == GLITCH_RESULT_FAILURE)
|| (gres == GLITCH_RESULT_TIMEOUT && last_res == GLITCH_RESULT_FAILURE)) {
if (step != 1)
step /= 2; // we have found the edge, now increase search presicion
else
edges += 1; // max precision, start walking around the edge
}
last_res = gres;
if (gres == GLITCH_RESULT_FAILURE) // not enough glitch, need more width
*width += step;
if (gres == GLITCH_RESULT_TIMEOUT) { // too much glitch, need less width
*width -= step;
if (*width <= 1)
*width = 1;
}
if (gres == GLITCH_RESULT_SUCCESS)
return true;
if (edges > edge_limit) // this offset did not work
return false;
}
}