-
Notifications
You must be signed in to change notification settings - Fork 12
Expand file tree
/
Copy pathmain.c
More file actions
330 lines (269 loc) · 10.1 KB
/
Copy pathmain.c
File metadata and controls
330 lines (269 loc) · 10.1 KB
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
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
#include <inttypes.h>
#include <stdbool.h>
#include "libc.h"
#include "common.h"
//#define RELOAD_LK
void low_uart_put(int ch) {
volatile uint32_t *uart_reg0 = (volatile uint32_t*)0x11009014;
volatile uint32_t *uart_reg1 = (volatile uint32_t*)0x11009000;
while ( !((*uart_reg0) & 0x20) )
{}
*uart_reg1 = ch;
}
void _putchar(char character)
{
if (character == '\n')
low_uart_put('\r');
low_uart_put(character);
}
void hex_dump(const void* data, size_t size) {
char ascii[17];
size_t i, j;
ascii[16] = '\0';
for (i = 0; i < size; ++i) {
printf("%02X ", ((unsigned char*)data)[i]);
if (((unsigned char*)data)[i] >= ' ' && ((unsigned char*)data)[i] <= '~') {
ascii[i % 16] = ((unsigned char*)data)[i];
} else {
ascii[i % 16] = '.';
}
if ((i+1) % 8 == 0 || i+1 == size) {
printf(" ");
if ((i+1) % 16 == 0) {
printf("\n");
// printf("| %s \n", ascii);
} else if (i+1 == size) {
ascii[(i+1) % 16] = '\0';
if ((i+1) % 16 <= 8) {
printf(" ");
}
for (j = (i+1) % 16; j < 16; ++j) {
printf(" ");
}
// printf("| %s \n", ascii);
printf("\n");
}
}
}
}
uint32_t pmic_read_interface(uint32_t RegNum, uint32_t *val, uint32_t MASK, uint32_t SHIFT) {
uint32_t ret = 0;
uint32_t reg = 0;
uint32_t rdata;
ret = pwrap_wacs2(0, (RegNum), 0, &rdata);
reg = rdata;
if (ret != 0) {
printf("Reg[0x%08X] = pmic_wrap read data fail\n", RegNum);
return ret;
}
reg &= (MASK << SHIFT);
*val = (reg >> SHIFT);
return ret;
}
uint32_t is_usb_cable_in(void) {
uint32_t nRet = 0;
uint32_t nRegValue = 0;
nRet = pmic_read_interface((uint32_t)(0x0000),
(&nRegValue),
(uint32_t)(0x1),
(uint32_t)(5));
nRet = nRegValue;
return nRet == 1;
}
bool is_power_key_pressed(void) {
uint32_t nRet = 0;
uint32_t nRegValue = 0;
nRet = pmic_read_interface((uint32_t)(0x0144),
(&nRegValue),
(uint32_t)(0x1),
(uint32_t)(3));
nRet = nRegValue;
return nRet == 0;
}
int (*original_read)(part_dev_t *dev, uint64_t dev_addr, void *dst, uint32_t size) = (void*)(0x81e0a2d0|1);
int (*app)() = (void*)(0x81e3cb98|1);
void (*fastboot_info)(const char *reason) = (void *)(0x81e3d064 | 1);
void (*fastboot_fail)(const char *reason) = (void *)(0x81e3d0a8 | 1);
void (*fastboot_okay)(const char *reason) = (void *)(0x81e3d0c8 | 1);
void (*fastboot_register)(const char *prefix,
void (*handle)(const char *arg, void *data, unsigned sz),
unsigned char security_enabled) = (void *)(0x81e3cccc | 1);
void (*mtk_arch_reset)(char mode) = (void *)(0x81e17fe4 | 1);
uint64_t g_boot, g_boot_x, g_lk, g_misc, g_recovery, g_recovery_x;
int read_func(part_dev_t *dev, uint64_t block_off, void *dst, uint32_t sz) {
printf("read_func hook\n");
printf("block_off 0x%08X 0x%08X\n", block_off, *(&(block_off)+4));
printf("dev 0x%08X dst 0x%08X sz 0x%08X\n", dev, dst, sz);
int ret = 0;
if (block_off == (g_boot * 0x200) + 0x1000000) {
block_off = (g_boot_x * 0x200) + 0x1000000;
} else if (block_off == ((g_boot * 0x200) + 0x800) + 0x1000000) {
block_off = ((g_boot_x * 0x200) + 0x800) + 0x1000000;
} else if (block_off == (g_recovery * 0x200) + 0x1000000) {
block_off = (g_recovery_x * 0x200) + 0x1000000;
} else if (block_off == ((g_recovery * 0x200) + 0x800) + 0x1000000) {
block_off = ((g_recovery_x * 0x200) + 0x800) + 0x1000000;
}
return original_read(dev, block_off, dst, sz);
}
static void parse_gpt() {
uint8_t raw[0x1000] = { 0 };
part_dev_t *dev = get_device();
dev->read(dev, 0x400 + 0x1000000, raw, sizeof(raw));
for (int i = 0; i < sizeof(raw) / 0x80; ++i) {
uint8_t *ptr = &raw[i * 0x80];
uint8_t *name = ptr + 0x38;
uint32_t start;
memcpy(&start, ptr + 0x20, 4);
if (memcmp(name, "b\x00o\x00o\x00t\x00\x00\x00", 10) == 0) {
g_boot = start;
printf("found boot at 0x%08X\n", start);
} else if (memcmp(name, "b\x00o\x00o\x00t\x00_\x00x\x00\x00\x00", 14) == 0) {
g_boot_x = start;
printf("found boot_x at 0x%08X\n", start);
} else if (memcmp(name, "U\x00\x42\x00O\x00O\x00T\x00\x00\x00", 12) == 0) {
g_lk = start ;
printf("found lk at 0x%08X\n", start);
} else if (memcmp(name, "M\x00I\x00S\x00\x43\x00\x00\x00", 10) == 0) {
g_misc = start;
printf("found misc at 0x%08X\n", start);
} else if (memcmp(name, "r\x00\x65\x00\x63\x00o\x00v\x00\x65\x00r\x00y\x00\x00\x00", 18) == 0) {
g_recovery = start;
printf("found recovery at 0x%08X\n", start);
} else if (memcmp(name, "r\x00\x65\x00\x63\x00o\x00v\x00\x65\x00r\x00y\x00_\x00x\x00\x00\x00", 22) == 0) {
g_recovery_x = start;
printf("found recovery_x at 0x%08X\n", start);
}
}
}
void cmd_reboot_recovery(const char *arg, void *data, unsigned sz) {
part_dev_t *dev = get_device();
uint8_t bootloader_msg[0x20] = { 0 };
memcpy(bootloader_msg, "boot-recovery", 13);
dev->write(dev, bootloader_msg, (g_misc * 0x200) + 0x1000000, 0x50);
fastboot_info("Rebooting device into recovery mode...");
fastboot_okay("");
mtk_arch_reset(1); // bypass power key (1)
}
__attribute__((section(".text.start"))) int main() {
int ret = 0;
printf("This is LK-payload by xyz. Copyright 2019\n");
printf("Original version for sloane by k4y0z and t0x1cSH. Copyright 2020\n");
printf("Ported to ariel ariel by R0rt1z2. Copyright 2024\n");
// We need to clean the cache first, since we jumped straight to the payload
cache_clean((void *)PAYLOAD_DST, PAYLOAD_SIZE);
int fastboot = 0;
parse_gpt();
if (!g_boot_x || !g_recovery_x || !g_lk) {
printf("failed to find boot, recovery or lk\n");
printf("falling back to fastboot mode\n");
fastboot = 1;
}
uint8_t bootloader_msg[0x20] = { 0 };
part_dev_t *dev = get_device();
// Restore the 0x81E00000-0x81E50000 range, a part of it was overwritten
// this is way more than we actually need to restore, but it shouldn't hurt
dev->read(dev, ((g_lk * 0x200) + 0x200) + 0x1000000, (char*)LK_BASE, 0x50000); // +0x200 to skip lk header
// Restore argptr
uint32_t **argptr = (void*)0x81e00020;
*argptr = (void*)0x81E8549C; // there's also a copy at 0x81E80044?
printf("g_boot_mode %u\n", *g_boot_mode);
printf("f_boot_mode %u\n", *f_boot_mode);
// factory and factory advanced boot
if(*g_boot_mode == 4 ) {
fastboot = 1;
}
// use advanced factory mode to boot recovery
else if(*g_boot_mode == 6) {
*g_boot_mode = 2;
}
else if(g_misc) {
// Read amonet-flag from MISC partition
dev->read(dev, (g_misc * 0x200) + 0x1000000, bootloader_msg, 0x50);
printf("bootloader_msg: %s\n", bootloader_msg);
// temp flag on MISC
if(strncmp(bootloader_msg, "boot-amonet", 11) == 0) {
fastboot = 1;
// reset flag
memset(bootloader_msg, 0, 0x10);
dev->write(dev, bootloader_msg, (g_misc * 0x200) + 0x1000000, 0x10);
}
// recovery flag on MISC
else if(strncmp(bootloader_msg, "boot-recovery", 13) == 0) {
*g_boot_mode = 2;
// reset flag
memset(bootloader_msg, 0, 0x10);
dev->write(dev, bootloader_msg, (g_misc * 0x200) + 0x1000000, 0x10);
}
// perm flag on MISC
else if(strncmp(bootloader_msg, "FASTBOOT_PLEASE", 15) == 0) {
// only reset flag in recovery-boot
if(*g_boot_mode == 2) {
memset(bootloader_msg, 0, 0x10);
dev->write(dev, bootloader_msg, (g_misc * 0x200) + 0x1000000, 0x50);
}
else {
fastboot = 1;
}
}
// UART flag on MISC
if(strncmp(bootloader_msg + 0x10, "UART_PLEASE", 11) == 0) {
// Force uart enable
char* disable_uart = (char*)0x81e612d8;
strcpy(disable_uart, " printk.disable_uart=0");
char* disable_uart2 = (char*)0x81e619a4;
strcpy(disable_uart2, "printk.disable_uart=0");
}
}
#ifdef RELOAD_LK
printf("Disable interrupts\n");
asm volatile ("cpsid if");
#endif
uint16_t *patch;
if (is_usb_cable_in() && is_power_key_pressed()) {
printf("USB cable is connected and power key is pressed\n");
fastboot = 1;
}
// force fastboot mode
if (fastboot) {
printf("well since you're asking so nicely...\n");
video_printf("=> HACKED FASTBOOT mode: (%d) - xyz, k4y0z, t0x1cSH, R0rt1z2\n", *g_boot_mode);
*g_boot_mode = 99;
}
else if(*g_boot_mode == 2) {
video_printf("=> RECOVERY mode...");
}
// device is unlocked
uint8_t **unlocked = (uint8_t**)0x81e81258;
(*unlocked)[0x16] = 0x1;
// remove broken oem reboot-recovery
patch = (void*)0x81e3d3a4;
*patch = 0x46c0;
*(patch + 1) = 0x46c0;
// register an actual working implementation
fastboot_register("oem reboot-recovery", cmd_reboot_recovery, 1);
// printf("(void*)dev->read 0x%08X\n", (void*)dev->read);
// printf("(void*)&dev->read 0x%08X\n", (void*)&dev->read);
uint32_t *patch32;
// hook bootimg read function
original_read = (void*)dev->read;
// patch32 = (void*)0x81E6C7C0;
// *patch32 = (uint32_t)read_func;
patch32 = (void*)&dev->read;
*patch32 = (uint32_t)read_func;
printf("Clean lk\n");
cache_clean((void *)LK_BASE, LK_SIZE);
#ifdef RELOAD_LK
printf("About to jump to LK\n");
asm volatile (
"mov r4, %0\n"
"mov r3, %1\n"
"blx r3\n"
: : "r" (arg), "r" (LK_BASE) : "r3", "r4");
printf("Failure\n");
#else
app();
#endif
while (1) {
}
}