Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
CTCaer
GitHub Repository: CTCaer/hekate
Path: blob/master/nyx/nyx_gui/frontend/gui_info.c
1476 views
1
/*
2
* Copyright (c) 2018 naehrwert
3
* Copyright (c) 2018-2025 CTCaer
4
* Copyright (c) 2018 balika011
5
*
6
* This program is free software; you can redistribute it and/or modify it
7
* under the terms and conditions of the GNU General Public License,
8
* version 2, as published by the Free Software Foundation.
9
*
10
* This program is distributed in the hope it will be useful, but WITHOUT
11
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13
* more details.
14
*
15
* You should have received a copy of the GNU General Public License
16
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17
*/
18
19
#include <bdk.h>
20
21
#include "gui.h"
22
#include "../config.h"
23
#include "../hos/hos.h"
24
#include "../hos/pkg1.h"
25
#include <libs/fatfs/ff.h>
26
27
#include <stdlib.h>
28
29
#define SECTORS_TO_MIB_COEFF 11
30
31
extern hekate_config h_cfg;
32
extern volatile boot_cfg_t *b_cfg;
33
extern volatile nyx_storage_t *nyx_str;
34
35
extern lv_res_t launch_payload(lv_obj_t *list);
36
extern char *emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage);
37
38
static lv_res_t _create_window_dump_done(int error, char *dump_filenames)
39
{
40
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
41
lv_obj_set_style(dark_bg, &mbox_darken);
42
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
43
44
static const char * mbox_btn_map[] = { "\251", "\222OK", "\251", "" };
45
lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL);
46
lv_mbox_set_recolor_text(mbox, true);
47
lv_obj_set_width(mbox, LV_HOR_RES / 9 * 5);
48
49
char *txt_buf = (char *)malloc(SZ_4K);
50
51
if (error)
52
s_printf(txt_buf, "#FFDD00 Failed to dump to# %s#FFDD00 !#\nError: %d", dump_filenames, error);
53
else
54
{
55
char *sn = emmcsn_path_impl(NULL, NULL, NULL, NULL);
56
s_printf(txt_buf, "Dumping to SD card finished!\nFiles: #C7EA46 backup/%s/dumps/#\n%s", sn, dump_filenames);
57
}
58
lv_mbox_set_text(mbox, txt_buf);
59
free(txt_buf);
60
61
lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action); // Important. After set_text.
62
63
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
64
lv_obj_set_top(mbox, true);
65
66
return LV_RES_OK;
67
}
68
69
static lv_res_t _cal0_dump_window_action(lv_obj_t *btns, const char * txt)
70
{
71
int btn_idx = lv_btnm_get_pressed(btns);
72
73
mbox_action(btns, txt);
74
75
if (btn_idx == 1)
76
{
77
int error = !sd_mount();
78
79
if (!error)
80
{
81
char path[64];
82
emmcsn_path_impl(path, "/dumps", "cal0.bin", NULL);
83
error = sd_save_to_file((u8 *)cal0_buf, SZ_32K, path);
84
85
sd_unmount();
86
}
87
88
_create_window_dump_done(error, "cal0.bin");
89
}
90
91
return LV_RES_INV;
92
}
93
94
95
static lv_res_t _battery_dump_window_action(lv_obj_t * btn)
96
{
97
int error = !sd_mount();
98
99
if (!error)
100
{
101
char path[64];
102
void *buf = malloc(0x100 * 2);
103
104
max17050_dump_regs(buf);
105
106
emmcsn_path_impl(path, "/dumps", "fuel_gauge.bin", NULL);
107
error = sd_save_to_file((u8 *)buf, 0x200, path);
108
109
sd_unmount();
110
}
111
112
_create_window_dump_done(error, "fuel_gauge.bin");
113
114
return LV_RES_OK;
115
}
116
117
static lv_res_t _bootrom_dump_window_action(lv_obj_t * btn)
118
{
119
static const u32 BOOTROM_SIZE = 0x18000;
120
121
int error = !sd_mount();
122
if (!error)
123
{
124
char path[64];
125
u32 iram_evp_thunks[0x200];
126
u32 iram_evp_thunks_len = sizeof(iram_evp_thunks);
127
error = fuse_read_evp_thunk(iram_evp_thunks, &iram_evp_thunks_len);
128
if (!error)
129
{
130
emmcsn_path_impl(path, "/dumps", "evp_thunks.bin", NULL);
131
error = sd_save_to_file((u8 *)iram_evp_thunks, iram_evp_thunks_len, path);
132
}
133
else
134
error = 255;
135
136
emmcsn_path_impl(path, "/dumps", "bootrom_patched.bin", NULL);
137
int res = sd_save_to_file((u8 *)IROM_BASE, BOOTROM_SIZE, path);
138
if (!error)
139
error = res;
140
141
u32 ipatch_cam[IPATCH_CAM_ENTRIES + 1];
142
memcpy(ipatch_cam, (void *)IPATCH_BASE, sizeof(ipatch_cam));
143
memset((void*)IPATCH_BASE, 0, sizeof(ipatch_cam)); // Zeroing valid entries is enough but zero everything.
144
145
emmcsn_path_impl(path, "/dumps", "bootrom_unpatched.bin", NULL);
146
res = sd_save_to_file((u8 *)IROM_BASE, BOOTROM_SIZE, path);
147
if (!error)
148
error = res;
149
150
memcpy((void*)IPATCH_BASE, ipatch_cam, sizeof(ipatch_cam));
151
152
sd_unmount();
153
}
154
_create_window_dump_done(error, "evp_thunks.bin, bootrom_patched.bin, bootrom_unpatched.bin");
155
156
return LV_RES_OK;
157
}
158
159
static lv_res_t _fuse_dump_window_action(lv_obj_t * btn)
160
{
161
const u32 fuse_array_size = (h_cfg.t210b01 ? FUSE_ARRAY_WORDS_NUM_B01 : FUSE_ARRAY_WORDS_NUM) * sizeof(u32);
162
163
int error = !sd_mount();
164
if (!error)
165
{
166
char path[128];
167
if (!h_cfg.t210b01)
168
{
169
emmcsn_path_impl(path, "/dumps", "fuse_cached_t210.bin", NULL);
170
error = sd_save_to_file((u8 *)0x7000F900, 0x300, path);
171
}
172
else
173
{
174
emmcsn_path_impl(path, "/dumps", "fuse_cached_t210b01_x898.bin", NULL);
175
error = sd_save_to_file((u8 *)0x7000F898, 0x68, path);
176
emmcsn_path_impl(path, "/dumps", "fuse_cached_t210b01_x900.bin", NULL);
177
if (!error)
178
error = sd_save_to_file((u8 *)0x7000F900, 0x300, path);
179
}
180
181
u32 words[FUSE_ARRAY_WORDS_NUM_B01];
182
fuse_read_array(words);
183
if (!h_cfg.t210b01)
184
emmcsn_path_impl(path, "/dumps", "fuse_array_raw_t210.bin", NULL);
185
else
186
emmcsn_path_impl(path, "/dumps", "fuse_array_raw_t210b01.bin", NULL);
187
int res = sd_save_to_file((u8 *)words, fuse_array_size, path);
188
if (!error)
189
error = res;
190
191
sd_unmount();
192
}
193
194
if (!h_cfg.t210b01)
195
_create_window_dump_done(error, "fuse_cached_t210.bin, fuse_array_raw_t210.bin");
196
else
197
_create_window_dump_done(error, "fuse_cached_t210b01_x*.bin, fuse_array_raw_t210b01.bin");
198
199
return LV_RES_OK;
200
}
201
202
static lv_res_t _kfuse_dump_window_action(lv_obj_t * btn)
203
{
204
u32 buf[KFUSE_NUM_WORDS];
205
int error = !kfuse_read(buf);
206
207
if (!error)
208
error = !sd_mount();
209
210
if (!error)
211
{
212
char path[64];
213
emmcsn_path_impl(path, "/dumps", "kfuses.bin", NULL);
214
error = sd_save_to_file((u8 *)buf, KFUSE_NUM_WORDS * 4, path);
215
216
sd_unmount();
217
}
218
219
_create_window_dump_done(error, "kfuses.bin");
220
221
return LV_RES_OK;
222
}
223
224
static lv_res_t _create_mbox_cal0(lv_obj_t *btn)
225
{
226
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
227
lv_obj_set_style(dark_bg, &mbox_darken);
228
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
229
230
static const char * mbox_btn_map[] = { "\251", "\222Dump", "\222Close", "\251", "" };
231
lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL);
232
lv_mbox_set_recolor_text(mbox, true);
233
lv_obj_set_width(mbox, LV_HOR_RES / 9 * 5);
234
235
lv_mbox_set_text(mbox, "#C7EA46 CAL0 Info#");
236
237
char *txt_buf = (char *)malloc(SZ_16K);
238
txt_buf[0] = 0;
239
240
lv_obj_t * lb_desc = lv_label_create(mbox, NULL);
241
lv_label_set_long_mode(lb_desc, LV_LABEL_LONG_BREAK);
242
lv_label_set_recolor(lb_desc, true);
243
lv_label_set_style(lb_desc, &monospace_text);
244
lv_obj_set_width(lb_desc, LV_HOR_RES / 9 * 4);
245
246
sd_mount();
247
248
// Dump CAL0.
249
int cal0_res = hos_dump_cal0();
250
251
// Check result. Don't error if hash doesn't match.
252
if (cal0_res == 1)
253
{
254
lv_label_set_text(lb_desc, "#FFDD00 Failed to init eMMC!#");
255
256
goto out;
257
}
258
else if (cal0_res == 2)
259
{
260
lv_label_set_text(lb_desc, "#FFDD00 CAL0 is corrupt or wrong keys!#\n");
261
goto out;
262
}
263
264
nx_emmc_cal0_t *cal0 = (nx_emmc_cal0_t *)cal0_buf;
265
266
u32 hash[8];
267
se_calc_sha256_oneshot(hash, (u8 *)cal0 + 0x40, cal0->body_size);
268
269
s_printf(txt_buf,
270
"#FF8000 CAL0 Version:# %d\n"
271
"#FF8000 Update Count:# %d\n"
272
"#FF8000 Serial Number:# %s\n"
273
"#FF8000 WLAN MAC:# %02X:%02X:%02X:%02X:%02X:%02X\n"
274
"#FF8000 Bluetooth MAC:# %02X:%02X:%02X:%02X:%02X:%02X\n"
275
"#FF8000 Battery LOT:# %s (%d)\n"
276
"#FF8000 LCD Vendor:# ",
277
cal0->version, cal0->update_cnt, cal0->serial_number,
278
cal0->wlan_mac[0], cal0->wlan_mac[1], cal0->wlan_mac[2], cal0->wlan_mac[3], cal0->wlan_mac[4], cal0->wlan_mac[5],
279
cal0->bd_mac[0], cal0->bd_mac[1], cal0->bd_mac[2], cal0->bd_mac[3], cal0->bd_mac[4], cal0->bd_mac[5],
280
cal0->battery_lot, cal0->battery_ver);
281
282
// Prepare display info.
283
u32 display_id = (cal0->lcd_vendor & 0xFF) << 8 | (cal0->lcd_vendor & 0xFF0000) >> 16;
284
switch (display_id)
285
{
286
case PANEL_JDI_LAM062M109A:
287
strcat(txt_buf, "JDI LAM062M109A");
288
break;
289
case PANEL_JDI_LPM062M326A:
290
strcat(txt_buf, "JDI LPM062M326A");
291
break;
292
case PANEL_INL_P062CCA_AZ1:
293
strcat(txt_buf, "InnoLux P062CCA-AZX");
294
break;
295
case PANEL_AUO_A062TAN01:
296
strcat(txt_buf, "AUO A062TAN0X");
297
break;
298
case PANEL_INL_2J055IA_27A:
299
strcat(txt_buf, "InnoLux 2J055IA-27A");
300
break;
301
case PANEL_AUO_A055TAN01:
302
strcat(txt_buf, "AUO A055TAN0X");
303
break;
304
case PANEL_SHP_LQ055T1SW10:
305
strcat(txt_buf, "Sharp LQ055T1SW10");
306
break;
307
case PANEL_SAM_AMS699VC01:
308
strcat(txt_buf, "Samsung AMS699VC01");
309
break;
310
default:
311
switch (cal0->lcd_vendor & 0xFF)
312
{
313
case 0:
314
case PANEL_JDI_XXX062M:
315
strcat(txt_buf, "JDI ");
316
break;
317
case (PANEL_INL_P062CCA_AZ1 & 0xFF):
318
strcat(txt_buf, "InnoLux ");
319
break;
320
case (PANEL_AUO_A062TAN01 & 0xFF):
321
strcat(txt_buf, "AUO ");
322
break;
323
case (PANEL_SAM_AMS699VC01 & 0xFF):
324
strcat(txt_buf, "Samsung ");
325
break;
326
}
327
strcat(txt_buf, "Unknown");
328
break;
329
}
330
331
s_printf(txt_buf + strlen(txt_buf),
332
" (%06X)\n#FF8000 Touch Vendor:# %d\n"
333
"#FF8000 IMU Type/Mount:# %d / %d\n"
334
"#FF8000 Stick L/R Type:# %02X / %02X\n",
335
cal0->lcd_vendor, cal0->touch_ic_vendor_id,
336
cal0->console_6axis_sensor_type, cal0->console_6axis_sensor_mount_type,
337
cal0->analog_stick_type_l, cal0->analog_stick_type_r);
338
339
bool valid_cal0 = !memcmp(hash, cal0->body_sha256, 0x20);
340
s_printf(txt_buf + strlen(txt_buf), "#FF8000 SHA256 Hash Match:# %s", valid_cal0 ? "Pass" : "Failed");
341
342
lv_label_set_text(lb_desc, txt_buf);
343
344
out:
345
free(txt_buf);
346
sd_unmount();
347
348
lv_mbox_add_btns(mbox, mbox_btn_map, _cal0_dump_window_action);
349
350
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
351
lv_obj_set_top(mbox, true);
352
353
return LV_RES_OK;
354
}
355
356
static lv_obj_t *hw_info_ver = NULL;
357
static lv_res_t _action_win_hw_info_status_close(lv_obj_t *btn)
358
{
359
if (hw_info_ver)
360
{
361
lv_obj_del(hw_info_ver);
362
hw_info_ver = NULL;
363
}
364
365
return nyx_win_close_action_custom(btn);
366
}
367
368
static lv_res_t _create_window_hw_info_status(lv_obj_t *btn)
369
{
370
lv_obj_t *win = nyx_create_window_custom_close_btn(SYMBOL_CHIP" HW & Fuses Info", _action_win_hw_info_status_close);
371
lv_win_add_btn(win, NULL, SYMBOL_DOWNLOAD" Dump fuses", _fuse_dump_window_action);
372
lv_win_add_btn(win, NULL, SYMBOL_INFO" CAL0 Info", _create_mbox_cal0);
373
374
lv_obj_t *desc = lv_cont_create(win, NULL);
375
lv_obj_set_size(desc, LV_HOR_RES / 2 / 5 * 2, LV_VER_RES - (LV_DPI * 11 / 7) - 5);
376
377
lv_obj_t * lb_desc = lv_label_create(desc, NULL);
378
lv_label_set_long_mode(lb_desc, LV_LABEL_LONG_BREAK);
379
lv_label_set_recolor(lb_desc, true);
380
lv_label_set_style(lb_desc, &monospace_text);
381
382
char version[32];
383
s_printf(version, "%s%d.%d.%d%c", NYX_VER_RL ? "v" : "", NYX_VER_MJ, NYX_VER_MN, NYX_VER_HF, NYX_VER_RL > 'A' ? NYX_VER_RL : 0);
384
lv_obj_t * lbl_ver = lv_label_create(lv_scr_act(), NULL);
385
lv_label_set_style(lbl_ver, &hint_small_style_white);
386
lv_label_set_text(lbl_ver, version);
387
lv_obj_align(lbl_ver, status_bar.bar_bg, LV_ALIGN_OUT_TOP_RIGHT, -LV_DPI * 9 / 23, -LV_DPI * 2 / 13);
388
hw_info_ver = lbl_ver;
389
390
lv_label_set_static_text(lb_desc,
391
"#FF8000 SoC:#\n"
392
"#FF8000 SKU:#\n"
393
"#FF8000 DRAM ID:#\n"
394
"#FF8000 Burnt Fuses (ODM 7/6):#\n"
395
"ODM Fields (4, 6, 7):\n"
396
"Secure Boot Key (SBK):\n"
397
"Device Key (DK):\n"
398
"Public Key (PK SHA256):\n\n"
399
"HOS Keygen Revision:\n"
400
"USB Stack:\n"
401
"Final Test Revision:\n"
402
"Chip Probing Revision:\n"
403
"CPU Speedo 0 (CPU Val):\n"
404
"CPU Speedo 1:\n"
405
"CPU Speedo 2 (GPU Val):\n"
406
"SoC Speedo 0 (SoC Val):\n"
407
"SoC Speedo 1 (BROM rev):\n"
408
"SoC Speedo 2:\n"
409
"CPU IDDQ Val:\n"
410
"SoC IDDQ Val:\n"
411
"Gpu IDDQ Val:\n"
412
"Vendor Code:\n"
413
"FAB Code:\n"
414
"LOT Code 0:\n"
415
"Wafer ID:\n"
416
"X Coordinate:\n"
417
"Y Coordinate:"
418
);
419
lv_obj_set_width(lb_desc, lv_obj_get_width(desc));
420
421
lv_obj_t *val = lv_cont_create(win, NULL);
422
lv_obj_set_size(val, LV_HOR_RES / 7 * 2 + LV_DPI / 11, LV_VER_RES - (LV_DPI * 11 / 7) - 5);
423
424
lv_obj_t * lb_val = lv_label_create(val, lb_desc);
425
426
char *txt_buf = (char *)malloc(SZ_16K);
427
428
// Decode fuses.
429
char *sku;
430
char dram_man[64];
431
char fuses_hos_version[64];
432
u8 dram_id = fuse_read_dramid(true);
433
434
switch (fuse_read_hw_type())
435
{
436
case FUSE_NX_HW_TYPE_ICOSA:
437
sku = "Icosa - Odin";
438
break;
439
case FUSE_NX_HW_TYPE_IOWA:
440
sku = "Iowa - Modin";
441
break;
442
case FUSE_NX_HW_TYPE_HOAG:
443
sku = "Hoag - Vali";
444
break;
445
case FUSE_NX_HW_TYPE_AULA:
446
sku = "Aula - Fric";
447
break;
448
default:
449
sku = "#FF8000 Unknown#";
450
break;
451
}
452
453
// Prepare dram id info.
454
if (!h_cfg.t210b01)
455
{
456
switch (dram_id)
457
{
458
// LPDDR4 3200Mbps.
459
case LPDDR4_ICOSA_4GB_SAMSUNG_K4F6E304HB_MGCH:
460
strcpy(dram_man, "Samsung K4F6E304HB-MGCH 4GB");
461
break;
462
case LPDDR4_ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE:
463
strcpy(dram_man, "Hynix H9HCNNNBPUMLHR-NLE 4GB");
464
break;
465
case LPDDR4_ICOSA_4GB_MICRON_MT53B512M32D2NP_062_WTC:
466
strcpy(dram_man, "Micron MT53B512M32D2NP-062 WT:C");
467
break;
468
case LPDDR4_ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH:
469
strcpy(dram_man, "Samsung K4FHE3D4HM-MGCH 6GB");
470
break;
471
case LPDDR4_ICOSA_8GB_SAMSUNG_K4FBE3D4HM_MGXX:
472
strcpy(dram_man, "Samsung K4FBE3D4HM-MGXX 8GB");
473
break;
474
default:
475
strcpy(dram_man, "#FF8000 Unknown#");
476
break;
477
}
478
}
479
else
480
{
481
switch (dram_id)
482
{
483
// LPDDR4X 3733Mbps.
484
case LPDDR4X_IOWA_4GB_SAMSUNG_K4U6E3S4AM_MGCJ:
485
case LPDDR4X_HOAG_4GB_SAMSUNG_K4U6E3S4AM_MGCJ:
486
strcpy(dram_man, "Samsung K4U6E3S4AM-MGCJ 4GB");
487
break;
488
case LPDDR4X_IOWA_8GB_SAMSUNG_K4UBE3D4AM_MGCJ:
489
case LPDDR4X_HOAG_8GB_SAMSUNG_K4UBE3D4AM_MGCJ:
490
strcpy(dram_man, "Samsung K4UBE3D4AM-MGCJ 8GB");
491
break;
492
case LPDDR4X_IOWA_4GB_HYNIX_H9HCNNNBKMMLHR_NME:
493
case LPDDR4X_HOAG_4GB_HYNIX_H9HCNNNBKMMLHR_NME:
494
strcpy(dram_man, "Hynix H9HCNNNBKMMLHR-NME 4GB");
495
break;
496
case LPDDR4X_IOWA_4GB_MICRON_MT53E512M32D2NP_046_WTE: // 4266Mbps.
497
case LPDDR4X_HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTE: // 4266Mbps.
498
strcpy(dram_man, "Micron MT53E512M32D2NP-046 WT:E");
499
break;
500
501
// LPDDR4X 4266Mbps
502
case LPDDR4X_IOWA_4GB_SAMSUNG_K4U6E3S4AA_MGCL:
503
case LPDDR4X_HOAG_4GB_SAMSUNG_K4U6E3S4AA_MGCL:
504
case LPDDR4X_AULA_4GB_SAMSUNG_K4U6E3S4AA_MGCL:
505
strcpy(dram_man, "Samsung K4U6E3S4AA-MGCL 4GB");
506
break;
507
case LPDDR4X_IOWA_8GB_SAMSUNG_K4UBE3D4AA_MGCL:
508
case LPDDR4X_HOAG_8GB_SAMSUNG_K4UBE3D4AA_MGCL:
509
case LPDDR4X_AULA_8GB_SAMSUNG_K4UBE3D4AA_MGCL:
510
strcpy(dram_man, "Samsung K4UBE3D4AA-MGCL 8GB");
511
break;
512
case LPDDR4X_IOWA_4GB_SAMSUNG_K4U6E3S4AB_MGCL:
513
case LPDDR4X_HOAG_4GB_SAMSUNG_K4U6E3S4AB_MGCL:
514
case LPDDR4X_AULA_4GB_SAMSUNG_K4U6E3S4AB_MGCL:
515
strcpy(dram_man, "Samsung K4U6E3S4AB-MGCL 4GB");
516
break;
517
case LPDDR4X_IOWA_4GB_MICRON_MT53E512M32D2NP_046_WTF:
518
case LPDDR4X_HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTF:
519
case LPDDR4X_AULA_4GB_MICRON_MT53E512M32D2NP_046_WTF:
520
strcpy(dram_man, "Micron MT53E512M32D2NP-046 WT:F");
521
break;
522
case LPDDR4X_HOAG_4GB_HYNIX_H9HCNNNBKMMLXR_NEE: // Replaced from Copper.
523
case LPDDR4X_AULA_4GB_HYNIX_H9HCNNNBKMMLXR_NEE: // Replaced from Copper.
524
case LPDDR4X_IOWA_4GB_HYNIX_H9HCNNNBKMMLXR_NEE: // Replaced from Copper.
525
strcpy(dram_man, "Hynix H9HCNNNBKMMLXR-NEE 4GB");
526
break;
527
case LPDDR4X_IOWA_4GB_HYNIX_H54G46CYRBX267:
528
case LPDDR4X_HOAG_4GB_HYNIX_H54G46CYRBX267:
529
case LPDDR4X_AULA_4GB_HYNIX_H54G46CYRBX267:
530
strcpy(dram_man, "Hynix H54G46CYRBX267 4GB");
531
break;
532
case LPDDR4X_IOWA_4GB_MICRON_MT53E512M32D1NP_046_WTB:
533
case LPDDR4X_HOAG_4GB_MICRON_MT53E512M32D1NP_046_WTB:
534
case LPDDR4X_AULA_4GB_MICRON_MT53E512M32D1NP_046_WTB:
535
strcpy(dram_man, "Micron MT53E512M32D1NP-046 WT:B");
536
break;
537
538
default:
539
strcpy(dram_man, "#FF8000 Contact me!#");
540
break;
541
}
542
}
543
544
// Count burnt fuses.
545
u8 burnt_fuses_7 = bit_count(fuse_read_odm(7));
546
u8 burnt_fuses_6 = bit_count(fuse_read_odm(6));
547
548
// Check if overburnt.
549
u8 burnt_fuses_hos = (fuse_read_odm(7) & ~bit_count_mask(burnt_fuses_7)) ? 255 : burnt_fuses_7;
550
551
//! TODO: Update on anti-downgrade fuses change.
552
switch (burnt_fuses_hos)
553
{
554
case 0:
555
strcpy(fuses_hos_version, "#96FF00 Golden sample#");
556
break;
557
case 1:
558
strcpy(fuses_hos_version, "1.0.0");
559
break;
560
case 2:
561
strcpy(fuses_hos_version, "2.0.0 - 2.3.0");
562
break;
563
case 3:
564
strcpy(fuses_hos_version, "3.0.0");
565
break;
566
case 4:
567
strcpy(fuses_hos_version, "3.0.1 - 3.0.2");
568
break;
569
case 5:
570
strcpy(fuses_hos_version, "4.0.0 - 4.1.0");
571
break;
572
case 6:
573
strcpy(fuses_hos_version, "5.0.0 - 5.1.0");
574
break;
575
case 7:
576
strcpy(fuses_hos_version, "6.0.0 - 6.1.0");
577
break;
578
case 8:
579
strcpy(fuses_hos_version, "6.2.0");
580
break;
581
case 9:
582
strcpy(fuses_hos_version, "7.0.0 - 8.0.1");
583
break;
584
case 10:
585
strcpy(fuses_hos_version, "8.1.0 - 8.1.1");
586
break;
587
case 11:
588
strcpy(fuses_hos_version, "9.0.0 - 9.0.1");
589
break;
590
case 12:
591
strcpy(fuses_hos_version, "9.1.0 - 9.2.0");
592
break;
593
case 13:
594
strcpy(fuses_hos_version, "10.0.0 - 10.2.0");
595
break;
596
case 14:
597
strcpy(fuses_hos_version, "11.0.0 - 12.0.1");
598
break;
599
case 15:
600
strcpy(fuses_hos_version, "12.0.2 - 13.2.0");
601
break;
602
case 16:
603
strcpy(fuses_hos_version, "13.2.1 - 14.1.2");
604
break;
605
case 17:
606
strcpy(fuses_hos_version, "15.0.0 - 15.0.1");
607
break;
608
case 18:
609
strcpy(fuses_hos_version, "16.0.0 - 16.1.0");
610
break;
611
case 19:
612
strcpy(fuses_hos_version, "17.0.0 - 18.1.0");
613
break;
614
case 20:
615
strcpy(fuses_hos_version, "19.0.0 - 19.0.1");
616
break;
617
case 21:
618
strcpy(fuses_hos_version, "20.0.0+");
619
break;
620
case 255:
621
strcpy(fuses_hos_version, "#FFD000 Overburnt#");
622
break;
623
default:
624
strcpy(fuses_hos_version, "#FF8000 Unknown#");
625
break;
626
}
627
628
// Calculate LOT.
629
u32 lot_code0 = (FUSE(FUSE_OPT_LOT_CODE_0) & 0xFFFFFFF) << 2;
630
u32 lot_bin = 0;
631
for (int i = 0; i < 5; ++i)
632
{
633
u32 digit = (lot_code0 & 0xFC000000) >> 26;
634
lot_bin *= 36;
635
lot_bin += digit;
636
lot_code0 <<= 6;
637
}
638
639
u32 chip_id = APB_MISC(APB_MISC_GP_HIDREV);
640
// Parse fuses and display them.
641
s_printf(txt_buf,
642
"%02X - %s - M%d A%02d\n"
643
"%X - %s - %s\n%02d - %s\n%d | %d - HOS: %s\n%08X %08X %08X\n%08X%08X%08X%08X\n%08X\n%08X%08X%08X%08X\n%08X%08X%08X%08X\n%d\n"
644
"%s\n%d.%02d (0x%X)\n%d.%02d (0x%X)\n%d\n%d\n%d\n%d\n0x%X\n%d\n%d (%d)\n%d (%d)\n%d (%d)\n"
645
"%d\n%d\n%d (0x%X)\n%d\n%d\n%d",
646
(chip_id >> 8) & 0xFF,
647
hw_get_chip_id() == GP_HIDREV_MAJOR_T210 ? "T210 (Erista)" : "T210B01 (Mariko)",
648
(chip_id >> 4) & 0xF, (chip_id >> 16) & 0xF,
649
FUSE(FUSE_SKU_INFO), sku, fuse_read_hw_state() ? "Dev" : "Retail",
650
dram_id, dram_man, burnt_fuses_7, burnt_fuses_6, fuses_hos_version,
651
fuse_read_odm(4), fuse_read_odm(6), fuse_read_odm(7),
652
byte_swap_32(FUSE(FUSE_PRIVATE_KEY0)), byte_swap_32(FUSE(FUSE_PRIVATE_KEY1)),
653
byte_swap_32(FUSE(FUSE_PRIVATE_KEY2)), byte_swap_32(FUSE(FUSE_PRIVATE_KEY3)),
654
byte_swap_32(FUSE(FUSE_PRIVATE_KEY4)),
655
byte_swap_32(FUSE(FUSE_PUBLIC_KEY0)), byte_swap_32(FUSE(FUSE_PUBLIC_KEY1)),
656
byte_swap_32(FUSE(FUSE_PUBLIC_KEY2)), byte_swap_32(FUSE(FUSE_PUBLIC_KEY3)),
657
byte_swap_32(FUSE(FUSE_PUBLIC_KEY4)), byte_swap_32(FUSE(FUSE_PUBLIC_KEY5)),
658
byte_swap_32(FUSE(FUSE_PUBLIC_KEY6)), byte_swap_32(FUSE(FUSE_PUBLIC_KEY7)),
659
fuse_read_odm_keygen_rev(),
660
((FUSE(FUSE_RESERVED_SW) & 0x80) || h_cfg.t210b01) ? "XUSB" : "USB2",
661
(FUSE(FUSE_OPT_FT_REV) >> 5) & 0x3F, FUSE(FUSE_OPT_FT_REV) & 0x1F, FUSE(FUSE_OPT_FT_REV),
662
(FUSE(FUSE_OPT_CP_REV) >> 5) & 0x3F, FUSE(FUSE_OPT_CP_REV) & 0x1F, FUSE(FUSE_OPT_CP_REV),
663
FUSE(FUSE_CPU_SPEEDO_0_CALIB), FUSE(FUSE_CPU_SPEEDO_1_CALIB), FUSE(FUSE_CPU_SPEEDO_2_CALIB),
664
FUSE(FUSE_SOC_SPEEDO_0_CALIB), FUSE(FUSE_SOC_SPEEDO_1_CALIB), FUSE(FUSE_SOC_SPEEDO_2_CALIB),
665
FUSE(FUSE_CPU_IDDQ_CALIB), FUSE(FUSE_CPU_IDDQ_CALIB) * 4,
666
FUSE(FUSE_SOC_IDDQ_CALIB), FUSE(FUSE_SOC_IDDQ_CALIB) * 4,
667
FUSE(FUSE_GPU_IDDQ_CALIB), FUSE(FUSE_GPU_IDDQ_CALIB) * 5,
668
FUSE(FUSE_OPT_VENDOR_CODE), FUSE(FUSE_OPT_FAB_CODE), lot_bin, FUSE(FUSE_OPT_LOT_CODE_0),
669
FUSE(FUSE_OPT_WAFER_ID), FUSE(FUSE_OPT_X_COORDINATE), FUSE(FUSE_OPT_Y_COORDINATE));
670
671
lv_label_set_text(lb_val, txt_buf);
672
673
lv_obj_set_width(lb_val, lv_obj_get_width(val));
674
lv_obj_align(val, desc, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
675
676
lv_obj_t *desc2 = lv_cont_create(win, NULL);
677
lv_obj_set_size(desc2, LV_HOR_RES / 2 / 5 * 4, LV_VER_RES - (LV_DPI * 11 / 7) - 5);
678
679
lv_obj_t * lb_desc2 = lv_label_create(desc2, NULL);
680
lv_label_set_long_mode(lb_desc2, LV_LABEL_LONG_BREAK);
681
lv_label_set_recolor(lb_desc2, true);
682
683
// Prepare DRAM info.
684
emc_mr_data_t ram_vendor = sdram_read_mrx(MR5_MAN_ID);
685
emc_mr_data_t ram_rev0 = sdram_read_mrx(MR6_REV_ID1);
686
emc_mr_data_t ram_rev1 = sdram_read_mrx(MR7_REV_ID2);
687
emc_mr_data_t ram_density = sdram_read_mrx(MR8_DENSITY);
688
u32 ranks = EMC(EMC_ADR_CFG) + 1;
689
u32 channels = (EMC(EMC_FBIO_CFG7) >> 1) & 3;
690
channels = (channels & 1) + ((channels & 2) >> 1);
691
s_printf(txt_buf, "#00DDFF %s SDRAM ##FF8000 (Module 0 | 1):#\n#FF8000 Vendor:# ", h_cfg.t210b01 ? "LPDDR4X" : "LPDDR4");
692
switch (ram_vendor.chip0.rank0_ch0)
693
{
694
case 1:
695
strcat(txt_buf, "Samsung");
696
break;
697
/*
698
case 5:
699
strcat(txt_buf, "Nanya");
700
break;
701
*/
702
case 6:
703
strcat(txt_buf, "Hynix");
704
break;
705
/*
706
case 8:
707
strcat(txt_buf, "Winbond");
708
break;
709
case 9:
710
strcat(txt_buf, "ESMT");
711
break;
712
case 19:
713
strcat(txt_buf, "CXMT");
714
break;
715
case 26:
716
strcat(txt_buf, "Xi'an UniIC");
717
break;
718
case 27:
719
strcat(txt_buf, "ISSI");
720
break;
721
case 28:
722
strcat(txt_buf, "JSC");
723
break;
724
case 197:
725
strcat(txt_buf, "SINKER");
726
break;
727
case 229:
728
strcat(txt_buf, "Dosilicon");
729
break;
730
case 248:
731
strcat(txt_buf, "Fidelix");
732
break;
733
case 249:
734
strcat(txt_buf, "Ultra Memory");
735
break;
736
case 253:
737
strcat(txt_buf, "AP Memory");
738
break;
739
*/
740
case 255:
741
strcat(txt_buf, "Micron");
742
break;
743
default:
744
s_printf(txt_buf + strlen(txt_buf), "#FF8000 Unknown# (%d)", ram_vendor.chip0.rank0_ch0);
745
break;
746
}
747
strcat(txt_buf, " #FF8000 |# ");
748
switch (ram_vendor.chip1.rank0_ch0)
749
{
750
case 1:
751
strcat(txt_buf, "Samsung");
752
break;
753
case 6:
754
strcat(txt_buf, "Hynix");
755
break;
756
case 255:
757
strcat(txt_buf, "Micron");
758
break;
759
default:
760
s_printf(txt_buf + strlen(txt_buf), "#FF8000 Unknown# (%d)", ram_vendor.chip1.rank0_ch0);
761
break;
762
}
763
764
s_printf(txt_buf + strlen(txt_buf), "\n#FF8000 Rev ID:# %X.%02X #FF8000 |# %X.%02X\n#FF8000 Density:# ",
765
ram_rev0.chip0.rank0_ch0, ram_rev1.chip0.rank0_ch0, ram_rev0.chip1.rank0_ch0, ram_rev1.chip1.rank0_ch0);
766
767
u32 actual_ranks = (ram_vendor.chip0.rank0_ch0 == ram_vendor.chip0.rank1_ch0 &&
768
ram_vendor.chip0.rank0_ch1 == ram_vendor.chip0.rank1_ch1 &&
769
ram_rev0.chip0.rank0_ch0 == ram_rev0.chip0.rank1_ch0 &&
770
ram_rev0.chip0.rank0_ch1 == ram_rev0.chip0.rank1_ch1 &&
771
ram_rev1.chip0.rank0_ch0 == ram_rev1.chip0.rank1_ch0 &&
772
ram_rev1.chip0.rank0_ch1 == ram_rev1.chip0.rank1_ch1 &&
773
ram_density.chip0.rank0_ch0 == ram_density.chip0.rank1_ch0 &&
774
ram_density.chip0.rank0_ch1 == ram_density.chip0.rank1_ch1)
775
? 2 : 1;
776
bool rank_bad = ranks != actual_ranks;
777
s_printf(txt_buf + strlen(txt_buf), "%s %d x %s", rank_bad ? "#FFDD00" : "", actual_ranks * channels, rank_bad ? "#" : "");
778
779
switch ((ram_density.chip0.rank0_ch0 & 0x3C) >> 2)
780
{
781
case 2:
782
strcat(txt_buf, "512MB");
783
break;
784
case 3:
785
strcat(txt_buf, "768MB");
786
break;
787
case 4:
788
strcat(txt_buf, "1GB");
789
break;
790
case 5:
791
strcat(txt_buf, "1.5GB");
792
break;
793
case 6:
794
strcat(txt_buf, "2GB");
795
break;
796
default:
797
s_printf(txt_buf + strlen(txt_buf), "Unk (%d)", (ram_density.chip0.rank0_ch0 & 0x3C) >> 2);
798
break;
799
}
800
801
actual_ranks = (ram_vendor.chip1.rank0_ch0 == ram_vendor.chip1.rank1_ch0 &&
802
ram_vendor.chip1.rank0_ch1 == ram_vendor.chip1.rank1_ch1 &&
803
ram_rev0.chip1.rank0_ch0 == ram_rev0.chip1.rank1_ch0 &&
804
ram_rev0.chip1.rank0_ch1 == ram_rev0.chip1.rank1_ch1 &&
805
ram_rev1.chip1.rank0_ch0 == ram_rev1.chip1.rank1_ch0 &&
806
ram_rev1.chip1.rank0_ch1 == ram_rev1.chip1.rank1_ch1 &&
807
ram_density.chip1.rank0_ch0 == ram_density.chip1.rank1_ch0 &&
808
ram_density.chip1.rank0_ch1 == ram_density.chip1.rank1_ch1)
809
? 2 : 1;
810
rank_bad = ranks != actual_ranks;
811
812
s_printf(txt_buf + strlen(txt_buf), " #FF8000 |# %s %d x %s", rank_bad ? "#FFDD00" : "", actual_ranks * channels, rank_bad ? "#" : "");
813
814
switch ((ram_density.chip1.rank0_ch0 & 0x3C) >> 2)
815
{
816
case 2:
817
strcat(txt_buf, "512MB");
818
break;
819
case 3:
820
strcat(txt_buf, "768MB");
821
break;
822
case 4:
823
strcat(txt_buf, "1GB");
824
break;
825
case 5:
826
strcat(txt_buf, "1.5GB");
827
break;
828
case 6:
829
strcat(txt_buf, "2GB");
830
break;
831
default:
832
s_printf(txt_buf + strlen(txt_buf), "Unk (%d)", (ram_density.chip1.rank0_ch0 & 0x3C) >> 2);
833
break;
834
}
835
strcat(txt_buf, "\n\n");
836
837
// Prepare display info.
838
u8 display_rev = (nyx_str->info.disp_id >> 8) & 0xFF;
839
u32 display_id = ((nyx_str->info.disp_id >> 8) & 0xFF00) | (nyx_str->info.disp_id & 0xFF);
840
841
strcat(txt_buf, "#00DDFF Display Panel:#\n#FF8000 Model:# ");
842
843
switch (display_id)
844
{
845
case PANEL_JDI_LAM062M109A:
846
strcat(txt_buf, "JDI LAM062M109A");
847
break;
848
case PANEL_JDI_LPM062M326A:
849
strcat(txt_buf, "JDI LPM062M326A");
850
break;
851
case PANEL_INL_P062CCA_AZ1:
852
strcat(txt_buf, "InnoLux P062CCA");
853
switch (display_rev)
854
{
855
case 0x93:
856
strcat(txt_buf, "-AZ1");
857
break;
858
case 0x95:
859
strcat(txt_buf, "-AZ2");
860
break;
861
case 0x96:
862
strcat(txt_buf, "-AZ3");
863
break;
864
case 0x97:
865
strcat(txt_buf, "-???");
866
break;
867
case 0x98:
868
strcat(txt_buf, "-???");
869
break;
870
case 0x99:
871
strcat(txt_buf, "-???");
872
break;
873
default:
874
strcat(txt_buf, " #FFDD00 Contact me!#");
875
break;
876
}
877
break;
878
case PANEL_AUO_A062TAN01:
879
strcat(txt_buf, "AUO A062TAN");
880
switch (display_rev)
881
{
882
case 0x93:
883
strcat(txt_buf, "00");
884
break;
885
case 0x94:
886
strcat(txt_buf, "01");
887
break;
888
case 0x95:
889
strcat(txt_buf, "02");
890
break;
891
case 0x96:
892
strcat(txt_buf, "??");
893
break;
894
case 0x97:
895
strcat(txt_buf, "??");
896
break;
897
case 0x98:
898
strcat(txt_buf, "??");
899
break;
900
default:
901
strcat(txt_buf, " #FFDD00 Contact me!#");
902
break;
903
}
904
break;
905
case PANEL_INL_2J055IA_27A:
906
strcat(txt_buf, "InnoLux 2J055IA-27A");
907
break;
908
case PANEL_AUO_A055TAN01:
909
strcat(txt_buf, "AUO A055TAN");
910
s_printf(txt_buf + strlen(txt_buf), "%02d", display_rev - 0x92);
911
break;
912
case PANEL_SHP_LQ055T1SW10:
913
strcat(txt_buf, "Sharp LQ055T1SW10");
914
break;
915
case PANEL_SAM_AMS699VC01:
916
strcat(txt_buf, "Samsung AMS699VC01");
917
break;
918
case PANEL_OEM_CLONE_6_2:
919
strcat(txt_buf, "#FFDD00 OEM Clone 6.2\"#");
920
break;
921
case PANEL_OEM_CLONE_5_5:
922
strcat(txt_buf, "#FFDD00 OEM Clone 5.5\"#");
923
break;
924
case PANEL_OEM_CLONE:
925
strcat(txt_buf, "#FFDD00 OEM Clone#");
926
break;
927
case 0xCCCC:
928
strcat(txt_buf, "#FFDD00 Failed to get info!#");
929
break;
930
default:
931
switch (display_id & 0xFF)
932
{
933
case PANEL_JDI_XXX062M:
934
strcat(txt_buf, "JDI ");
935
break;
936
case (PANEL_INL_P062CCA_AZ1 & 0xFF):
937
strcat(txt_buf, "InnoLux ");
938
break;
939
case (PANEL_AUO_A062TAN01 & 0xFF):
940
strcat(txt_buf, "AUO ");
941
break;
942
case (PANEL_SAM_AMS699VC01 & 0xFF):
943
strcat(txt_buf, "Samsung ");
944
break;
945
}
946
strcat(txt_buf, "Unknown #FFDD00 Contact me!#");
947
break;
948
}
949
950
s_printf(txt_buf + strlen(txt_buf), "\n#FF8000 ID:# #96FF00 %02X# %02X #96FF00 %02X#",
951
nyx_str->info.disp_id & 0xFF, (nyx_str->info.disp_id >> 8) & 0xFF, (nyx_str->info.disp_id >> 16) & 0xFF);
952
953
touch_fw_info_t touch_fw;
954
touch_panel_info_t *touch_panel;
955
bool panel_ic_paired = false;
956
957
// Prepare touch panel/ic info.
958
if (!touch_get_fw_info(&touch_fw))
959
{
960
strcat(txt_buf, "\n\n#00DDFF Touch Panel:#\n#FF8000 Model:# ");
961
962
touch_panel = touch_get_panel_vendor();
963
if (touch_panel)
964
{
965
if ((u8)touch_panel->idx == (u8)-2) // Touch panel not found, print gpios.
966
{
967
s_printf(txt_buf + strlen(txt_buf), "%2X%2X%2X #FFDD00 Contact me!#",
968
touch_panel->gpio0, touch_panel->gpio1, touch_panel->gpio2);
969
touch_panel = NULL;
970
}
971
else
972
strcat(txt_buf, touch_panel->vendor);
973
}
974
else
975
strcat(txt_buf, "#FFDD00 Error!#");
976
977
s_printf(txt_buf + strlen(txt_buf), "\n#FF8000 ID:# %02X.%02X.%02X.%02X (",
978
(touch_fw.fw_id >> 24) & 0xFF, (touch_fw.fw_id >> 16) & 0xFF, (touch_fw.fw_id >> 8) & 0xFF, touch_fw.fw_id & 0xFF);
979
980
// Check panel pair info.
981
switch (touch_fw.fw_id)
982
{
983
case 0x00100100:
984
strcat(txt_buf, "4CD60D/0");
985
if (touch_panel)
986
panel_ic_paired = (u8)touch_panel->idx == (u8)-1;
987
break;
988
case 0x00100200: // 4CD 1602.
989
case 0x00120100:
990
case 0x32000001:
991
strcat(txt_buf, "4CD60D/1");
992
if (touch_panel)
993
panel_ic_paired = touch_panel->idx == 0; // NISSHA NFT-K12D.
994
break;
995
// case 0x98000004: // New 6.2" panel?
996
// case 0x50000001:
997
// case 0x50000002:
998
// strcat(txt_buf, "FST2 UNK");
999
// if (touch_panel)
1000
// panel_ic_paired = touch_panel->idx == 0;
1001
// break;
1002
case 0x001A0300:
1003
case 0x32000102:
1004
strcat(txt_buf, "4CD60D/2");
1005
if (touch_panel)
1006
panel_ic_paired = touch_panel->idx == 1; // GiS GGM6 B2X.
1007
break;
1008
case 0x00290100:
1009
case 0x32000302:
1010
strcat(txt_buf, "4CD60D/3");
1011
if (touch_panel)
1012
panel_ic_paired = touch_panel->idx == 2; // NISSHA NBF-K9A.
1013
break;
1014
case 0x31051820:
1015
case 0x32000402:
1016
strcat(txt_buf, "4CD60D/4");
1017
if (touch_panel)
1018
panel_ic_paired = touch_panel->idx == 3; // GiS 5.5".
1019
break;
1020
case 0x32000501:
1021
case 0x33000502:
1022
case 0x33000503:
1023
case 0x33000510:
1024
strcat(txt_buf, "4CD60D/5");
1025
if (touch_panel)
1026
panel_ic_paired = touch_panel->idx == 4; // Samsung BH2109.
1027
break;
1028
default:
1029
strcat(txt_buf, "#FF8000 Contact me#");
1030
break;
1031
}
1032
1033
s_printf(txt_buf + strlen(txt_buf), " - %s)\n#FF8000 FTB ver:# %04X\n#FF8000 FW rev:# %04X",
1034
panel_ic_paired ? "Paired" : "#FFDD00 Error#",
1035
touch_fw.ftb_ver,
1036
byte_swap_16(touch_fw.fw_rev)); // Byte swapping makes more sense here.
1037
}
1038
else
1039
strcat(txt_buf, "\n\n#FFDD00 Failed to get touch info!#");
1040
1041
// Check if patched unit.
1042
if (!fuse_check_patched_rcm())
1043
strcat(txt_buf, "\n\n#96FF00 This unit is exploitable#\n#96FF00 to the RCM bug!#");
1044
else
1045
strcat(txt_buf, "\n\n#FF8000 This unit is patched#\n#FF8000 to the RCM bug!#");
1046
1047
lv_label_set_text(lb_desc2, txt_buf);
1048
1049
free(txt_buf);
1050
1051
lv_obj_set_width(lb_desc2, lv_obj_get_width(desc2));
1052
lv_obj_align(desc2, val, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 4, 0);
1053
1054
return LV_RES_OK;
1055
}
1056
1057
static char *ipatches_txt;
1058
static void _ipatch_process(u32 offset, u32 value)
1059
{
1060
s_printf(ipatches_txt + strlen(ipatches_txt), "%6X %4X ", IROM_BASE + offset, value);
1061
u8 lo = value & 0xFF;
1062
switch (value >> 8)
1063
{
1064
case 0x20:
1065
s_printf(ipatches_txt + strlen(ipatches_txt), "MOVS R0, ##0x%02X", lo);
1066
break;
1067
case 0x21:
1068
s_printf(ipatches_txt + strlen(ipatches_txt), "MOVS R1, ##0x%02X", lo);
1069
break;
1070
case 0xDF:
1071
s_printf(ipatches_txt + strlen(ipatches_txt), "SVC ##0x%02X", lo);
1072
break;
1073
}
1074
strcat(ipatches_txt, "\n");
1075
}
1076
1077
static lv_res_t _create_window_bootrom_info_status(lv_obj_t *btn)
1078
{
1079
lv_obj_t *win = nyx_create_standard_window(SYMBOL_CHIP" Bootrom Info");
1080
lv_win_add_btn(win, NULL, SYMBOL_DOWNLOAD" Dump Bootrom", _bootrom_dump_window_action);
1081
1082
lv_obj_t *desc = lv_cont_create(win, NULL);
1083
lv_obj_set_size(desc, LV_HOR_RES / 2 / 3 * 2, LV_VER_RES - (LV_DPI * 11 / 7) - 5);
1084
1085
lv_obj_t * lb_desc = lv_label_create(desc, NULL);
1086
lv_label_set_long_mode(lb_desc, LV_LABEL_LONG_BREAK);
1087
lv_label_set_recolor(lb_desc, true);
1088
lv_label_set_style(lb_desc, &monospace_text);
1089
1090
char *txt_buf = (char *)malloc(SZ_4K);
1091
ipatches_txt = txt_buf;
1092
s_printf(txt_buf, "#00DDFF Ipatches:#\n#FF8000 Address "SYMBOL_DOT" Val "SYMBOL_DOT" Instruction#\n");
1093
1094
u32 res = fuse_read_ipatch(_ipatch_process);
1095
if (res != 0)
1096
s_printf(txt_buf + strlen(txt_buf), "#FFDD00 Failed to read ipatches. Error: %d#", res);
1097
1098
lv_label_set_text(lb_desc, txt_buf);
1099
1100
free(txt_buf);
1101
1102
lv_obj_set_width(lb_desc, lv_obj_get_width(desc));
1103
1104
return LV_RES_OK;
1105
}
1106
1107
static lv_res_t _launch_lockpick_action(lv_obj_t *btns, const char * txt)
1108
{
1109
int btn_idx = lv_btnm_get_pressed(btns);
1110
1111
mbox_action(btns, txt);
1112
1113
if (btn_idx == 1)
1114
{
1115
lv_obj_t *list = lv_list_create(NULL, NULL);
1116
lv_obj_set_size(list, 1, 1);
1117
lv_list_set_single_mode(list, true);
1118
lv_list_add(list, NULL, "Lockpick_RCM.bin", NULL);
1119
lv_obj_t *btn;
1120
btn = lv_list_get_prev_btn(list, NULL);
1121
launch_payload(btn);
1122
lv_obj_del(list);
1123
}
1124
1125
return LV_RES_INV;
1126
}
1127
1128
static lv_res_t _create_mbox_lockpick(lv_obj_t *btn)
1129
{
1130
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
1131
lv_obj_set_style(dark_bg, &mbox_darken);
1132
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
1133
1134
static const char * mbox_btn_map[] = { "\251", "\222Continue", "\222Close", "\251", "" };
1135
lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL);
1136
lv_mbox_set_recolor_text(mbox, true);
1137
1138
lv_mbox_set_text(mbox, "#FF8000 Lockpick RCM#\n\nThis will launch Lockpick RCM.\nDo you want to continue?\n\n"
1139
"To return back from lockpick use\n#96FF00 Reboot to hekate#.");
1140
1141
lv_mbox_add_btns(mbox, mbox_btn_map, _launch_lockpick_action);
1142
lv_obj_set_width(mbox, LV_HOR_RES / 9 * 5);
1143
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
1144
lv_obj_set_top(mbox, true);
1145
1146
return LV_RES_OK;
1147
}
1148
1149
static lv_res_t _create_mbox_emmc_sandisk_report(lv_obj_t * btn)
1150
{
1151
static lv_style_t h_style;
1152
lv_style_copy(&h_style, &lv_style_transp);
1153
h_style.body.padding.inner = 0;
1154
h_style.body.padding.hor = LV_DPI - (LV_DPI / 4);
1155
h_style.body.padding.ver = LV_DPI / 6;
1156
1157
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
1158
lv_obj_set_style(dark_bg, &mbox_darken);
1159
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
1160
1161
static const char * mbox_btn_map[] = { "\251", "\222Close", "\251", "" };
1162
lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL);
1163
lv_mbox_set_recolor_text(mbox, true);
1164
lv_obj_set_width(mbox, LV_HOR_RES / 9 * 8);
1165
1166
lv_mbox_set_text(mbox, "#C7EA46 Sandisk Device Report#");
1167
1168
u8 *buf = zalloc(EMMC_BLOCKSIZE);
1169
char *txt_buf = (char *)malloc(SZ_32K);
1170
char *txt_buf2 = (char *)malloc(SZ_32K);
1171
txt_buf[0] = 0;
1172
txt_buf2[0] = 0;
1173
1174
// Create SoC Info container.
1175
lv_obj_t *h1 = lv_cont_create(mbox, NULL);
1176
lv_cont_set_style(h1, &h_style);
1177
lv_cont_set_fit(h1, false, true);
1178
lv_obj_set_width(h1, (LV_HOR_RES / 9) * 7);
1179
lv_obj_set_click(h1, false);
1180
lv_cont_set_layout(h1, LV_LAYOUT_OFF);
1181
1182
lv_obj_t * lb_desc = lv_label_create(h1, NULL);
1183
lv_label_set_long_mode(lb_desc, LV_LABEL_LONG_BREAK);
1184
lv_label_set_recolor(lb_desc, true);
1185
lv_label_set_style(lb_desc, &monospace_text);
1186
lv_obj_set_width(lb_desc, LV_HOR_RES / 9 * 4);
1187
1188
lv_obj_t * lb_desc2 = lv_label_create(h1, NULL);
1189
lv_label_set_long_mode(lb_desc2, LV_LABEL_LONG_BREAK);
1190
lv_label_set_recolor(lb_desc2, true);
1191
lv_label_set_style(lb_desc2, &monospace_text);
1192
lv_obj_set_width(lb_desc2, LV_HOR_RES / 9 * 3);
1193
lv_obj_align(lb_desc2, lb_desc, LV_ALIGN_OUT_RIGHT_TOP, 0, 0);
1194
1195
1196
if (!emmc_initialize(false))
1197
{
1198
lv_label_set_text(lb_desc, "#FFDD00 Failed to init eMMC!#");
1199
1200
goto out;
1201
}
1202
1203
int res = sdmmc_storage_vendor_sandisk_report(&emmc_storage, buf);
1204
emmc_end();
1205
1206
if (!res)
1207
{
1208
lv_label_set_text(lb_desc, "#FFDD00 Device Report not supported!#");
1209
lv_label_set_text(lb_desc2, " ");
1210
1211
goto out;
1212
}
1213
1214
mmc_sandisk_report_t *rpt = (mmc_sandisk_report_t *)buf;
1215
1216
u8 fw_update_date[13] = {0};
1217
u8 fw_update_time[9] = {0};
1218
memcpy(fw_update_date, rpt->fw_update_date, sizeof(rpt->fw_update_date));
1219
memcpy(fw_update_time, rpt->fw_update_time, sizeof(rpt->fw_update_time));
1220
1221
s_printf(txt_buf,
1222
"#00DDFF Device report#\n"
1223
//"#FF8000 Average Erases SYS:# %d\n"
1224
"#FF8000 Average Erases SLC:# %d\n"
1225
"#FF8000 Average Erases MLC:# %d\n"
1226
//"#FF8000 Read Reclaims SYS:# %d\n"
1227
"#FF8000 Read Reclaims SLC:# %d\n"
1228
"#FF8000 Read Reclaims MLC:# %d\n"
1229
"#FF8000 Bad Blocks Factory:# %d\n"
1230
"#FF8000 Bad Blocks SYS:# %d\n"
1231
"#FF8000 Bad Blocks SLC:# %d\n"
1232
"#FF8000 Bad Blocks MLC:# %d\n"
1233
"#FF8000 FW Updates:# %d\n"
1234
"#FF8000 FW Buildtime:# %s %s\n"
1235
"#FF8000 Total Writes:# %d MB\n"
1236
//"#FF8000 Voltage Drops:# %d\n"
1237
//"#FF8000 Voltage Droops:# %d\n"
1238
//"#FF8000 VD Failed Recovers:# %d\n"
1239
//"#FF8000 VD Recover Operations:# %d\n"
1240
"#FF8000 Total Writes SLC:# %d MB\n"
1241
"#FF8000 Total Writes MLC:# %d MB\n"
1242
"#FF8000 BigFile limit status:# %d\n"
1243
"#FF8000 Average Erases Hybrid:# %d",
1244
1245
//rpt->avg_erase_cycles_sys,
1246
rpt->avg_erase_cycles_slc,
1247
rpt->avg_erase_cycles_mlc,
1248
//rpt->read_reclaim_cnt_sys,
1249
rpt->read_reclaim_cnt_slc,
1250
rpt->read_reclaim_cnt_mlc,
1251
rpt->bad_blocks_factory,
1252
rpt->bad_blocks_sys,
1253
rpt->bad_blocks_slc,
1254
rpt->bad_blocks_mlc,
1255
rpt->fw_updates_cnt,
1256
fw_update_date,
1257
fw_update_time,
1258
rpt->total_writes_100mb * 100,
1259
//rpt->vdrops,
1260
//rpt->vdroops,
1261
//rpt->vdrops_failed_data_rec,
1262
//rpt->vdrops_data_rec_ops,
1263
rpt->total_writes_slc_100mb * 100,
1264
rpt->total_writes_mlc_100mb * 100,
1265
rpt->mlc_bigfile_mode_limit_exceeded,
1266
rpt->avg_erase_cycles_hybrid);
1267
1268
u8 advanced_report = 0;
1269
for (u32 i = 0; i < sizeof(mmc_sandisk_advanced_report_t); i++)
1270
advanced_report |= *(u8 *)((u8 *)&rpt->advanced + i);
1271
1272
if (advanced_report)
1273
{
1274
s_printf(txt_buf2,
1275
"#00DDFF Advanced Health Status#\n"
1276
"#FF8000 Power ups:# %d\n"
1277
//"#FF8000 Maximum Erases SYS:# %d\n"
1278
"#FF8000 Maximum Erases SLC:# %d\n"
1279
"#FF8000 Maximum Erases MLC:# %d\n"
1280
//"#FF8000 Minimum Erases SYS:# %d\n"
1281
"#FF8000 Minimum Erases SLC:# %d\n"
1282
"#FF8000 Minimum Erases MLC:# %d\n"
1283
"#FF8000 Maximum Erases EUDA:# %d\n"
1284
"#FF8000 Minimum Erases EUDA:# %d\n"
1285
"#FF8000 Average Erases EUDA:# %d\n"
1286
"#FF8000 Read Reclaims EUDA:# %d\n"
1287
"#FF8000 Bad Blocks EUDA:# %d\n"
1288
//"#FF8000 Pre EOL State EUDA:# %d\n"
1289
//"#FF8000 Pre EOL State SYS:# %d\n"
1290
//"#FF8000 Pre EOL State MLC:# %d\n"
1291
"#FF8000 Uncorrectable ECC:# %d\n"
1292
"#FF8000 Temperature Now:# %d oC\n"
1293
//"#FF8000 Temperature Min:# %d oC\n"
1294
"#FF8000 Temperature Max:# %d oC\n"
1295
"#FF8000 Health Level EUDA:# %d%%\n"
1296
//"#FF8000 Health Level SYS:# %d%%\n"
1297
"#FF8000 Health Level MLC:# %d%%",
1298
1299
rpt->advanced.power_inits,
1300
//rpt->advanced.max_erase_cycles_sys,
1301
rpt->advanced.max_erase_cycles_slc,
1302
rpt->advanced.max_erase_cycles_mlc,
1303
//rpt->advanced.min_erase_cycles_sys,
1304
rpt->advanced.min_erase_cycles_slc,
1305
rpt->advanced.min_erase_cycles_mlc,
1306
rpt->advanced.max_erase_cycles_euda,
1307
rpt->advanced.min_erase_cycles_euda,
1308
rpt->advanced.avg_erase_cycles_euda,
1309
rpt->advanced.read_reclaim_cnt_euda,
1310
rpt->advanced.bad_blocks_euda,
1311
//rpt->advanced.pre_eol_euda,
1312
//rpt->advanced.pre_eol_sys,
1313
//rpt->advanced.pre_eol_mlc,
1314
rpt->advanced.uncorrectable_ecc,
1315
rpt->advanced.temperature_now,
1316
//rpt->advanced.temperature_min,
1317
rpt->advanced.temperature_max,
1318
rpt->advanced.health_pct_euda ? 101 - rpt->advanced.health_pct_euda : 0,
1319
//rpt->advanced.health_pct_sys ? 101 - rpt->advanced.health_pct_sys : 0,
1320
rpt->advanced.health_pct_mlc ? 101 - rpt->advanced.health_pct_mlc : 0);
1321
}
1322
else
1323
strcpy(txt_buf2, "#00DDFF Advanced Health Status#\n#FFDD00 Empty!#");
1324
1325
lv_label_set_text(lb_desc, txt_buf);
1326
lv_label_set_text(lb_desc2, txt_buf2);
1327
1328
out:
1329
free(buf);
1330
free (txt_buf);
1331
free (txt_buf2);
1332
1333
lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action); // Important. After set_text.
1334
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
1335
lv_obj_set_top(mbox, true);
1336
1337
return LV_RES_OK;
1338
}
1339
1340
static lv_res_t _create_mbox_benchmark(bool sd_bench)
1341
{
1342
sdmmc_storage_t *storage;
1343
1344
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
1345
lv_obj_set_style(dark_bg, &mbox_darken);
1346
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
1347
1348
static const char * mbox_btn_map[] = { "\251", "\222OK", "\251", "" };
1349
lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL);
1350
lv_mbox_set_recolor_text(mbox, true);
1351
lv_obj_set_width(mbox, LV_HOR_RES * 3 / 7);
1352
1353
char *txt_buf = (char *)malloc(SZ_16K);
1354
1355
s_printf(txt_buf, "#FF8000 %s Benchmark#\n[Raw Reads] Abort: VOL- & VOL+", sd_bench ? "SD Card" : "eMMC");
1356
1357
lv_mbox_set_text(mbox, txt_buf);
1358
txt_buf[0] = 0;
1359
1360
lv_obj_t *h1 = lv_cont_create(mbox, NULL);
1361
lv_cont_set_fit(h1, false, true);
1362
lv_cont_set_style(h1, &lv_style_transp_tight);
1363
lv_obj_set_width(h1, lv_obj_get_width(mbox) - LV_DPI / 10);
1364
1365
lv_obj_t *lbl_status = lv_label_create(h1, NULL);
1366
lv_label_set_style(lbl_status, &monospace_text);
1367
lv_label_set_recolor(lbl_status, true);
1368
lv_label_set_text(lbl_status, " ");
1369
lv_obj_align(lbl_status, h1, LV_ALIGN_IN_TOP_MID, 0, 0);
1370
1371
lv_obj_t *bar = lv_bar_create(mbox, NULL);
1372
lv_obj_set_size(bar, LV_DPI * 2, LV_DPI / 5);
1373
lv_bar_set_range(bar, 0, 100);
1374
lv_bar_set_value(bar, 0);
1375
1376
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
1377
lv_obj_set_top(mbox, true);
1378
manual_system_maintenance(true);
1379
1380
int res = 0;
1381
1382
if (sd_bench)
1383
{
1384
storage = &sd_storage;
1385
1386
// Re-initialize to update trimmers.
1387
sd_end();
1388
res = !sd_mount();
1389
}
1390
else
1391
{
1392
storage = &emmc_storage;
1393
res = !emmc_initialize(false);
1394
if (!res)
1395
emmc_set_partition(EMMC_GPP);
1396
}
1397
1398
if (res)
1399
{
1400
lv_mbox_set_text(mbox, "#FFDD00 Failed to init Storage!#");
1401
goto out;
1402
}
1403
1404
// Set benchmark parameters.
1405
const u32 sct_blk_seq = 0x8000; // 16MB. A2 spec denotes 4MB, but using older big AU.
1406
const u32 sct_blk_4kb = 8; // 4KB.
1407
const u32 sct_rem_seq = 0x200000; // 1GB. A2 spec.
1408
const u32 sct_rem_4kb = 0x80000; // 256MB. A2 spec.
1409
const u32 sct_num_1mb = 0x800; // 1MB.
1410
const u32 size_bytes_seq = sct_rem_seq * SDMMC_DAT_BLOCKSIZE;
1411
const u32 size_bytes_4kb = sct_rem_4kb * SDMMC_DAT_BLOCKSIZE;
1412
1413
// Set calculation divider. 1000 or 1024. (Does not affect IOPS).
1414
u32 mb_div = 1000; // Unfortunately most software uses fake MB.
1415
1416
char *mbs_text;
1417
switch (mb_div)
1418
{
1419
case 1000:
1420
mbs_text = "MB/s";
1421
break;
1422
case 1024:
1423
mbs_text = "MiB/s";
1424
break;
1425
}
1426
1427
// Set actual div in MB/MiB.
1428
mb_div *= mb_div;
1429
1430
int error = 0;
1431
u32 iters = 3;
1432
u32 offset_chunk_start = ALIGN_DOWN(storage->sec_cnt / 3, sct_blk_seq); // Align to block.
1433
if (storage->sec_cnt < 0xC00000)
1434
iters -= 2; // 4GB card.
1435
1436
u32 rnd_off_cnt = sct_rem_4kb / sct_blk_4kb;
1437
u32 *random_offsets = malloc(rnd_off_cnt * sizeof(u32));
1438
u32 *times_taken_4k = malloc(rnd_off_cnt * sizeof(u32));
1439
1440
for (u32 iter_curr = 0; iter_curr < iters; iter_curr++)
1441
{
1442
u32 pct = 0;
1443
u32 prevPct = 200;
1444
u32 timer = 0;
1445
u32 lba_curr = 0;
1446
u32 sector_off = offset_chunk_start * iter_curr;
1447
u32 sector_num = sct_blk_seq;
1448
u32 data_remaining = sct_rem_seq;
1449
1450
s_printf(txt_buf + strlen(txt_buf), "#C7EA46 %d/3# - Sector Offset #C7EA46 %08X#:\n", iter_curr + 1, sector_off);
1451
1452
u32 render_min_ms = 66;
1453
u32 render_timer = get_tmr_ms() + render_min_ms;
1454
while (data_remaining)
1455
{
1456
u32 time_taken = get_tmr_us();
1457
error = !sdmmc_storage_read(storage, sector_off + lba_curr, sector_num, (u8 *)MIXD_BUF_ALIGNED);
1458
time_taken = get_tmr_us() - time_taken;
1459
timer += time_taken;
1460
1461
manual_system_maintenance(false);
1462
data_remaining -= sector_num;
1463
lba_curr += sector_num;
1464
1465
pct = (lba_curr * 100) / sct_rem_seq;
1466
if (pct != prevPct && render_timer < get_tmr_ms())
1467
{
1468
lv_bar_set_value(bar, pct);
1469
manual_system_maintenance(true);
1470
render_timer = get_tmr_ms() + render_min_ms;
1471
1472
prevPct = pct;
1473
1474
if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
1475
error = -1;
1476
}
1477
1478
if (error)
1479
goto error;
1480
}
1481
lv_bar_set_value(bar, 100);
1482
1483
// Calculate rate for transfer.
1484
u32 rate_1k = (u64)size_bytes_seq * 1000 * 1000 * 1000 / mb_div / timer;
1485
s_printf(txt_buf + strlen(txt_buf), " SEQ 16MB - Rate: #C7EA46 %3d.%02d %s#",
1486
rate_1k / 1000, (rate_1k % 1000) / 10, mbs_text);
1487
lv_label_set_text(lbl_status, txt_buf);
1488
lv_obj_align(lbl_status, NULL, LV_ALIGN_CENTER, 0, 0);
1489
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
1490
manual_system_maintenance(true);
1491
1492
pct = 0;
1493
prevPct = 200;
1494
timer = 0;
1495
lba_curr = 0;
1496
sector_num = sct_blk_4kb;
1497
data_remaining = sct_rem_4kb;
1498
1499
u32 loop_idx = 0;
1500
render_timer = get_tmr_ms() + render_min_ms;
1501
while (data_remaining)
1502
{
1503
u32 time_taken = get_tmr_us();
1504
error = !sdmmc_storage_read(storage, sector_off + lba_curr, sector_num, (u8 *)MIXD_BUF_ALIGNED);
1505
time_taken = get_tmr_us() - time_taken;
1506
1507
timer += time_taken;
1508
times_taken_4k[loop_idx++] = time_taken;
1509
1510
manual_system_maintenance(false);
1511
data_remaining -= sector_num;
1512
lba_curr += sector_num;
1513
1514
pct = (lba_curr * 100) / sct_rem_4kb;
1515
if (pct != prevPct && render_timer < get_tmr_ms())
1516
{
1517
lv_bar_set_value(bar, pct);
1518
manual_system_maintenance(true);
1519
render_timer = get_tmr_ms() + render_min_ms;
1520
1521
prevPct = pct;
1522
1523
if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
1524
error = -1;
1525
}
1526
1527
if (error)
1528
goto error;
1529
}
1530
lv_bar_set_value(bar, 100);
1531
1532
qsort(times_taken_4k, loop_idx, sizeof(u32), qsort_compare_int); // Use int for faster compare. Value can't exceed 2s.
1533
1534
u32 pct95 = 0;
1535
for (u32 i = 0; i < loop_idx * 95 / 100; i++)
1536
pct95 += times_taken_4k[i];
1537
pct95 /= loop_idx * 95 / 100;
1538
1539
u32 pct05 = 0;
1540
for (u32 i = 0; i < loop_idx * 5 / 100; i++)
1541
pct05 += times_taken_4k[loop_idx - 1 - i];
1542
pct05 /= loop_idx * 5 / 100;
1543
1544
// Calculate rate and IOPS for transfer.
1545
rate_1k = (u64)size_bytes_4kb * 1000 * 1000 * 1000 / mb_div / timer;
1546
u32 iops = ((u64)(sct_rem_4kb / sct_num_1mb) * 1024 * 1000 * 1000 * 1000) / (4096 / 1024) / timer / 1000;
1547
s_printf(txt_buf + strlen(txt_buf), " AVG #C7EA46 95th# #FF3C28 5th#\n");
1548
s_printf(txt_buf + strlen(txt_buf), " SEQ 4KB - Rate: #C7EA46 %3d.%02d %s# IOPS: #C7EA46 %4d# %4d %4d \n",
1549
rate_1k / 1000, (rate_1k % 1000) / 10, mbs_text, iops, 1000000 / pct95, 1000000 / pct05);
1550
lv_label_set_text(lbl_status, txt_buf);
1551
lv_obj_align(lbl_status, NULL, LV_ALIGN_CENTER, 0, 0);
1552
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
1553
manual_system_maintenance(true);
1554
1555
u32 lba_idx = 0;
1556
u32 random_numbers[4];
1557
for (u32 i = 0; i < rnd_off_cnt; i += 4)
1558
{
1559
// Generate new random numbers.
1560
while (!se_gen_prng128(random_numbers))
1561
;
1562
// Clamp offsets to 256MB range.
1563
random_offsets[i + 0] = random_numbers[0] % sct_rem_4kb;
1564
random_offsets[i + 1] = random_numbers[1] % sct_rem_4kb;
1565
random_offsets[i + 2] = random_numbers[2] % sct_rem_4kb;
1566
random_offsets[i + 3] = random_numbers[3] % sct_rem_4kb;
1567
}
1568
1569
pct = 0;
1570
prevPct = 200;
1571
timer = 0;
1572
data_remaining = sct_rem_4kb;
1573
1574
loop_idx = 0;
1575
render_timer = get_tmr_ms() + render_min_ms;
1576
while (data_remaining)
1577
{
1578
u32 time_taken = get_tmr_us();
1579
error = !sdmmc_storage_read(storage, sector_off + random_offsets[lba_idx], sector_num, (u8 *)MIXD_BUF_ALIGNED);
1580
time_taken = get_tmr_us() - time_taken;
1581
1582
timer += time_taken;
1583
times_taken_4k[loop_idx++] = time_taken;
1584
1585
manual_system_maintenance(false);
1586
data_remaining -= sector_num;
1587
lba_idx++;
1588
1589
pct = (lba_idx * 100) / rnd_off_cnt;
1590
if (pct != prevPct && render_timer < get_tmr_ms())
1591
{
1592
lv_bar_set_value(bar, pct);
1593
manual_system_maintenance(true);
1594
render_timer = get_tmr_ms() + render_min_ms;
1595
1596
prevPct = pct;
1597
1598
if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
1599
error = -1;
1600
}
1601
1602
if (error)
1603
goto error;
1604
}
1605
lv_bar_set_value(bar, 100);
1606
1607
qsort(times_taken_4k, loop_idx, sizeof(u32), qsort_compare_int); // Use int for faster compare. Value can't exceed 2s.
1608
1609
pct95 = 0;
1610
for (u32 i = 0; i < loop_idx * 95 / 100; i++)
1611
pct95 += times_taken_4k[i];
1612
pct95 /= loop_idx * 95 / 100;
1613
1614
pct05 = 0;
1615
for (u32 i = 0; i < loop_idx * 5 / 100; i++)
1616
pct05 += times_taken_4k[loop_idx - 1 - i];
1617
pct05 /= loop_idx * 5 / 100;
1618
1619
// Calculate rate and IOPS for transfer.
1620
rate_1k = (u64)size_bytes_4kb * 1000 * 1000 * 1000 / mb_div / timer;
1621
iops = ((u64)(sct_rem_4kb / sct_num_1mb) * 1024 * 1000 * 1000 * 1000) / (4096 / 1024) / timer / 1000;
1622
s_printf(txt_buf + strlen(txt_buf), " RND 4KB - Rate: #C7EA46 %3d.%02d %s# IOPS: #C7EA46 %4d# %4d %4d \n",
1623
rate_1k / 1000, (rate_1k % 1000) / 10, mbs_text, iops, 1000000 / pct95, 1000000 / pct05);
1624
if (iter_curr == iters - 1)
1625
txt_buf[strlen(txt_buf) - 1] = 0; // Cut off last new line.
1626
lv_label_set_text(lbl_status, txt_buf);
1627
lv_obj_align(lbl_status, NULL, LV_ALIGN_CENTER, 0, 0);
1628
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
1629
manual_system_maintenance(true);
1630
}
1631
1632
error:
1633
free(random_offsets);
1634
free(times_taken_4k);
1635
1636
if (error)
1637
{
1638
if (error == -1)
1639
s_printf(txt_buf + strlen(txt_buf), "\n#FFDD00 Aborted!#");
1640
else
1641
s_printf(txt_buf + strlen(txt_buf), "\n#FFDD00 IO Error occurred!#");
1642
1643
lv_label_set_text(lbl_status, txt_buf);
1644
lv_obj_align(lbl_status, NULL, LV_ALIGN_CENTER, 0, 0);
1645
}
1646
1647
lv_obj_del(bar);
1648
1649
if (sd_bench && error && error != -1)
1650
sd_end();
1651
if (sd_bench)
1652
{
1653
if (error && error != -1)
1654
sd_end();
1655
else
1656
sd_unmount();
1657
}
1658
else
1659
emmc_end();
1660
1661
out:
1662
s_printf(txt_buf, "#FF8000 %s Benchmark#\n[Raw Reads]", sd_bench ? "SD Card" : "eMMC");
1663
lv_mbox_set_text(mbox, txt_buf);
1664
free(txt_buf);
1665
1666
lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action); // Important. After set_text.
1667
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
1668
1669
return LV_RES_OK;
1670
}
1671
1672
static lv_res_t _create_mbox_emmc_bench(lv_obj_t * btn)
1673
{
1674
_create_mbox_benchmark(false);
1675
1676
return LV_RES_OK;
1677
}
1678
1679
static lv_res_t _create_mbox_sd_bench(lv_obj_t * btn)
1680
{
1681
_create_mbox_benchmark(true);
1682
1683
return LV_RES_OK;
1684
}
1685
1686
static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
1687
{
1688
lv_obj_t *win = nyx_create_standard_window(SYMBOL_CHIP" Internal eMMC Info");
1689
lv_win_add_btn(win, NULL, SYMBOL_CHIP" Benchmark", _create_mbox_emmc_bench);
1690
1691
lv_obj_t *desc = lv_cont_create(win, NULL);
1692
lv_obj_set_size(desc, LV_HOR_RES / 2 / 6 * 2, LV_VER_RES - (LV_DPI * 11 / 7) - 5);
1693
1694
lv_obj_t * lb_desc = lv_label_create(desc, NULL);
1695
lv_label_set_long_mode(lb_desc, LV_LABEL_LONG_BREAK);
1696
lv_label_set_recolor(lb_desc, true);
1697
1698
char *txt_buf = (char *)malloc(SZ_16K);
1699
txt_buf[0] = '\n';
1700
txt_buf[1] = 0;
1701
u16 *emmc_errors;
1702
1703
if (!emmc_initialize(false))
1704
{
1705
lv_label_set_text(lb_desc, "#FFDD00 Failed to init eMMC!#");
1706
lv_obj_set_width(lb_desc, lv_obj_get_width(desc));
1707
emmc_errors = emmc_get_error_count();
1708
1709
goto out_error;
1710
}
1711
1712
u32 speed = 0;
1713
char *rsvd_blocks;
1714
char life_a_txt[8];
1715
char life_b_txt[8];
1716
u32 cache = emmc_storage.ext_csd.cache_size;
1717
u32 life_a = emmc_storage.ext_csd.dev_life_est_a;
1718
u32 life_b = emmc_storage.ext_csd.dev_life_est_b;
1719
u16 card_type = emmc_storage.ext_csd.card_type;
1720
char card_type_support[96];
1721
card_type_support[0] = 0;
1722
1723
// Identify manufacturer. Only official eMMCs.
1724
switch (emmc_storage.cid.manfid)
1725
{
1726
case 0x11:
1727
strcat(txt_buf, "Toshiba ");
1728
break;
1729
case 0x15:
1730
strcat(txt_buf, "Samsung ");
1731
break;
1732
case 0x45: // Unofficial.
1733
strcat(txt_buf, "SanDisk ");
1734
lv_win_add_btn(win, NULL, SYMBOL_FILE_ALT" Device Report", _create_mbox_emmc_sandisk_report);
1735
break;
1736
case 0x90:
1737
strcat(txt_buf, "SK Hynix ");
1738
break;
1739
default:
1740
strcat(txt_buf, "Unknown ");
1741
break;
1742
}
1743
1744
s_printf(txt_buf + strlen(txt_buf), "(%02X)\n%c%c%c%c%c%c (%02X)\n%d.%d\n%04X\n%02d/%04d\n\n",
1745
emmc_storage.cid.manfid,
1746
emmc_storage.cid.prod_name[0], emmc_storage.cid.prod_name[1], emmc_storage.cid.prod_name[2],
1747
emmc_storage.cid.prod_name[3], emmc_storage.cid.prod_name[4], emmc_storage.cid.prod_name[5],
1748
emmc_storage.cid.oemid,
1749
emmc_storage.cid.prv & 0xF, emmc_storage.cid.prv >> 4,
1750
emmc_storage.cid.serial, emmc_storage.cid.month, emmc_storage.cid.year);
1751
1752
if (card_type & EXT_CSD_CARD_TYPE_HS_26)
1753
{
1754
strcat(card_type_support, "HS26");
1755
speed = (26 << 16) | 26;
1756
}
1757
if (card_type & EXT_CSD_CARD_TYPE_HS_52)
1758
{
1759
strcat(card_type_support, ", HS52");
1760
speed = (52 << 16) | 52;
1761
}
1762
if (card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
1763
{
1764
strcat(card_type_support, ", DDR52 1.8V");
1765
speed = (52 << 16) | 104;
1766
}
1767
if (card_type & EXT_CSD_CARD_TYPE_HS200_1_8V)
1768
{
1769
strcat(card_type_support, ", HS200 1.8V");
1770
speed = (200 << 16) | 200;
1771
}
1772
if (card_type & EXT_CSD_CARD_TYPE_HS400_1_8V)
1773
{
1774
strcat(card_type_support, ", HS400 1.8V");
1775
speed = (200 << 16) | 400;
1776
}
1777
1778
strcpy(life_a_txt, "-");
1779
strcpy(life_b_txt, "-");
1780
1781
// Normalize cells life.
1782
if (life_a) // SK Hynix is 0 (undefined).
1783
{
1784
life_a--;
1785
life_a = (10 - life_a) * 10;
1786
s_printf(life_a_txt, "%d%%", life_a);
1787
}
1788
1789
if (life_b) // Toshiba is 0 (undefined).
1790
{
1791
life_b--;
1792
life_b = (10 - life_b) * 10;
1793
s_printf(life_b_txt, "%d%%", life_b);
1794
}
1795
1796
switch (emmc_storage.ext_csd.pre_eol_info)
1797
{
1798
case 1:
1799
rsvd_blocks = "Normal (< 80%)";
1800
break;
1801
case 2:
1802
rsvd_blocks = "Warning (> 80%)";
1803
break;
1804
case 3:
1805
rsvd_blocks = "Critical (> 90%)";
1806
break;
1807
default:
1808
rsvd_blocks = "#FF8000 Unknown#";
1809
break;
1810
}
1811
1812
s_printf(txt_buf + strlen(txt_buf),
1813
"#00DDFF V1.%d (rev 1.%d)#\n%02X\n%d MB/s (%d MHz)\n%d MB/s\n%s\n%d %s\n%d MiB\nA: %s, B: %s\n%s",
1814
emmc_storage.ext_csd.ext_struct, emmc_storage.ext_csd.rev,
1815
emmc_storage.csd.cmdclass, speed & 0xFFFF, (speed >> 16) & 0xFFFF,
1816
emmc_storage.csd.busspeed, card_type_support,
1817
!(cache % 1024) ? (cache / 1024) : cache, !(cache % 1024) ? "MiB" : "KiB",
1818
emmc_storage.ext_csd.max_enh_mult * EMMC_BLOCKSIZE / 1024,
1819
life_a_txt, life_b_txt, rsvd_blocks);
1820
1821
lv_label_set_static_text(lb_desc,
1822
"#00DDFF CID:#\n"
1823
"Vendor ID:\n"
1824
"Model:\n"
1825
"Prod Rev:\n"
1826
"S/N:\n"
1827
"Month/Year:\n\n"
1828
"#00DDFF Ext CSD:#\n"
1829
"Cmd Classes:\n"
1830
"Max Rate:\n"
1831
"Current Rate:\n"
1832
"Type Support:\n\n"
1833
"Write Cache:\n"
1834
"Enhanced Area:\n"
1835
"Estimated Life:\n"
1836
"Reserved Used:"
1837
);
1838
lv_obj_set_width(lb_desc, lv_obj_get_width(desc));
1839
1840
lv_obj_t *val = lv_cont_create(win, NULL);
1841
lv_obj_set_size(val, LV_HOR_RES / 11 * 3, LV_VER_RES - (LV_DPI * 11 / 7) - 5);
1842
1843
lv_obj_t * lb_val = lv_label_create(val, lb_desc);
1844
1845
lv_label_set_text(lb_val, txt_buf);
1846
1847
lv_obj_set_width(lb_val, lv_obj_get_width(val));
1848
lv_obj_align(val, desc, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
1849
1850
lv_obj_t *desc2 = lv_cont_create(win, NULL);
1851
lv_obj_set_size(desc2, LV_HOR_RES / 2 / 4 * 4, LV_VER_RES - (LV_DPI * 11 / 7) - 5);
1852
1853
lv_obj_t * lb_desc2 = lv_label_create(desc2, lb_desc);
1854
lv_label_set_style(lb_desc2, &monospace_text);
1855
1856
u32 boot_size = emmc_storage.ext_csd.boot_mult << 17;
1857
u32 rpmb_size = emmc_storage.ext_csd.rpmb_mult << 17;
1858
strcpy(txt_buf, "#00DDFF eMMC Physical Partitions:#\n");
1859
s_printf(txt_buf + strlen(txt_buf), "1: #96FF00 BOOT0# Size: %6d KiB Sectors: 0x%08X\n", boot_size / 1024, boot_size / EMMC_BLOCKSIZE);
1860
s_printf(txt_buf + strlen(txt_buf), "2: #96FF00 BOOT1# Size: %6d KiB Sectors: 0x%08X\n", boot_size / 1024, boot_size / EMMC_BLOCKSIZE);
1861
s_printf(txt_buf + strlen(txt_buf), "3: #96FF00 RPMB# Size: %6d KiB Sectors: 0x%08X\n", rpmb_size / 1024, rpmb_size / EMMC_BLOCKSIZE);
1862
s_printf(txt_buf + strlen(txt_buf), "0: #96FF00 GPP# Size: %6d MiB Sectors: 0x%08X\n", emmc_storage.sec_cnt >> SECTORS_TO_MIB_COEFF, emmc_storage.sec_cnt);
1863
strcat(txt_buf, "\n#00DDFF GPP (eMMC USER) Partition Table:#\n");
1864
1865
emmc_set_partition(EMMC_GPP);
1866
LIST_INIT(gpt);
1867
emmc_gpt_parse(&gpt);
1868
1869
u32 idx = 0;
1870
int lines_left = 20;
1871
s_printf(txt_buf + strlen(txt_buf), "#FFBA00 Idx Name Size Offset Sectors#\n");
1872
LIST_FOREACH_ENTRY(emmc_part_t, part, &gpt, link)
1873
{
1874
int lines = strlen(part->name) > 25 ? 2 : 1;
1875
if ((lines_left - lines) <= 0)
1876
{
1877
strcat(txt_buf, "#FFDD00 Table does not fit on screen!#");
1878
break;
1879
}
1880
1881
if (lines == 2)
1882
{
1883
s_printf(txt_buf + strlen(txt_buf), "%02d: #96FF00 %s#\n %6d MiB %8Xh %8Xh\n",
1884
part->index, part->name, (part->lba_end - part->lba_start + 1) >> SECTORS_TO_MIB_COEFF,
1885
part->lba_start, part->lba_end - part->lba_start + 1);
1886
}
1887
else
1888
{
1889
s_printf(txt_buf + strlen(txt_buf), "%02d: #96FF00 %.25s# %6d MiB %8Xh %8Xh\n",
1890
part->index, part->name, (part->lba_end - part->lba_start + 1) >> SECTORS_TO_MIB_COEFF,
1891
part->lba_start, part->lba_end - part->lba_start + 1);
1892
}
1893
1894
lines_left -= lines;
1895
idx++;
1896
}
1897
if (!idx)
1898
strcat(txt_buf, "#FFDD00 Partition table is empty!#");
1899
1900
emmc_gpt_free(&gpt);
1901
1902
lv_label_set_text(lb_desc2, txt_buf);
1903
lv_obj_set_width(lb_desc2, lv_obj_get_width(desc2));
1904
lv_obj_align(desc2, val, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 6, 0);
1905
1906
emmc_errors = emmc_get_error_count();
1907
if (emmc_get_mode() < EMMC_MMC_HS400 ||
1908
emmc_errors[EMMC_ERROR_INIT_FAIL] ||
1909
emmc_errors[EMMC_ERROR_RW_FAIL] ||
1910
emmc_errors[EMMC_ERROR_RW_RETRY])
1911
{
1912
out_error:
1913
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
1914
lv_obj_set_style(dark_bg, &mbox_darken);
1915
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
1916
1917
static const char * mbox_btn_map[] = { "\251", "\222OK", "\251", "" };
1918
lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL);
1919
lv_mbox_set_recolor_text(mbox, true);
1920
1921
s_printf(txt_buf,
1922
"#FF8000 eMMC Issues Warning#\n\n"
1923
"#FFDD00 Your eMMC is initialized in a slower mode,#\n"
1924
"#FFDD00 or init/read/write errors occurred!#\n"
1925
"#FFDD00 This might mean hardware issues!#\n\n"
1926
"#00DDFF Bus Speed:# %d MB/s\n\n"
1927
"#00DDFF SDMMC4 Errors:#\n"
1928
"Init fails: %d\n"
1929
"Read/Write fails: %d\n"
1930
"Read/Write errors: %d",
1931
emmc_storage.csd.busspeed,
1932
emmc_errors[EMMC_ERROR_INIT_FAIL],
1933
emmc_errors[EMMC_ERROR_RW_FAIL],
1934
emmc_errors[EMMC_ERROR_RW_RETRY]);
1935
1936
lv_mbox_set_text(mbox, txt_buf);
1937
lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action);
1938
lv_obj_set_width(mbox, LV_HOR_RES / 9 * 5);
1939
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
1940
lv_obj_set_top(mbox, true);
1941
}
1942
1943
emmc_end();
1944
free(txt_buf);
1945
1946
return LV_RES_OK;
1947
}
1948
1949
static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
1950
{
1951
lv_obj_t *win = nyx_create_standard_window(SYMBOL_SD" microSD Card Info");
1952
lv_win_add_btn(win, NULL, SYMBOL_SD" Benchmark", _create_mbox_sd_bench);
1953
1954
lv_obj_t *desc = lv_cont_create(win, NULL);
1955
lv_obj_set_size(desc, LV_HOR_RES / 2 / 6 * 2, LV_VER_RES - (LV_DPI * 11 / 8) * 5 / 2);
1956
1957
lv_obj_t * lb_desc = lv_label_create(desc, NULL);
1958
lv_label_set_long_mode(lb_desc, LV_LABEL_LONG_BREAK);
1959
lv_label_set_recolor(lb_desc, true);
1960
1961
lv_label_set_text(lb_desc, "#D4FF00 Please wait...#");
1962
lv_obj_set_width(lb_desc, lv_obj_get_width(desc));
1963
1964
// Disable buttons.
1965
nyx_window_toggle_buttons(win, true);
1966
1967
manual_system_maintenance(true);
1968
1969
if (!sd_mount())
1970
{
1971
lv_label_set_text(lb_desc, "#FFDD00 Failed to init SD!#");
1972
goto failed;
1973
}
1974
1975
lv_label_set_text(lb_desc,
1976
"#00DDFF Card ID:#\n"
1977
"Vendor ID:\n"
1978
"Model:\n"
1979
"OEM ID:\n"
1980
"HW rev:\n"
1981
"FW rev:\n"
1982
"S/N:\n"
1983
"Month/Year:\n\n"
1984
"Max Power:\n"
1985
"Initial bus:"
1986
);
1987
1988
lv_obj_t *val = lv_cont_create(win, NULL);
1989
lv_obj_set_size(val, LV_HOR_RES / 12 * 3, LV_VER_RES - (LV_DPI * 11 / 8) * 5 / 2);
1990
1991
lv_obj_t * lb_val = lv_label_create(val, lb_desc);
1992
1993
char *txt_buf = (char *)malloc(SZ_16K);
1994
txt_buf[0] = '\n';
1995
txt_buf[1] = 0;
1996
1997
// Identify manufacturer.
1998
switch (sd_storage.cid.manfid)
1999
{
2000
case 0x00:
2001
strcat(txt_buf, "Fake ");
2002
break;
2003
case 0x01:
2004
strcat(txt_buf, "Panasonic ");
2005
break;
2006
case 0x02:
2007
strcat(txt_buf, "Toshiba ");
2008
break;
2009
case 0x03:
2010
if (!memcmp(&sd_storage.cid.oemid, "DW", 2))
2011
strcat(txt_buf, "Western Digital "); // WD.
2012
else
2013
strcat(txt_buf, "SanDisk ");
2014
break;
2015
case 0x06:
2016
strcat(txt_buf, "Ritek ");
2017
break;
2018
case 0x09:
2019
strcat(txt_buf, "ATP ");
2020
break;
2021
case 0x13:
2022
strcat(txt_buf, "Kingmax ");
2023
break;
2024
case 0x19:
2025
strcat(txt_buf, "Dynacard ");
2026
break;
2027
case 0x1A:
2028
strcat(txt_buf, "Power Quotient ");
2029
break;
2030
case 0x1B:
2031
strcat(txt_buf, "Samsung ");
2032
break;
2033
case 0x1D:
2034
strcat(txt_buf, "AData ");
2035
break;
2036
case 0x27:
2037
strcat(txt_buf, "Phison ");
2038
break;
2039
case 0x28:
2040
strcat(txt_buf, "Barun Electronics ");
2041
break;
2042
case 0x31:
2043
strcat(txt_buf, "Silicon Power ");
2044
break;
2045
case 0x41:
2046
strcat(txt_buf, "Kingston ");
2047
break;
2048
case 0x51:
2049
strcat(txt_buf, "STEC ");
2050
break;
2051
case 0x5D:
2052
strcat(txt_buf, "SwissBit ");
2053
break;
2054
case 0x61:
2055
strcat(txt_buf, "Netlist ");
2056
break;
2057
case 0x63:
2058
strcat(txt_buf, "Cactus ");
2059
break;
2060
case 0x73:
2061
strcat(txt_buf, "Bongiovi ");
2062
break;
2063
case 0x74:
2064
strcat(txt_buf, "Jiaelec ");
2065
break;
2066
case 0x76:
2067
strcat(txt_buf, "Patriot ");
2068
break;
2069
case 0x82:
2070
strcat(txt_buf, "Jiang Tay ");
2071
break;
2072
case 0x83:
2073
strcat(txt_buf, "Netcom ");
2074
break;
2075
case 0x84:
2076
strcat(txt_buf, "Strontium ");
2077
break;
2078
case 0x9C:
2079
if (!memcmp(&sd_storage.cid.oemid, "OS", 2))
2080
strcat(txt_buf, "Sony "); // SO.
2081
else
2082
strcat(txt_buf, "Barun Electronics "); // BE.
2083
break;
2084
case 0x9F:
2085
strcat(txt_buf, "Taishin ");
2086
break;
2087
case 0xAD:
2088
strcat(txt_buf, "Longsys ");
2089
break;
2090
default:
2091
strcat(txt_buf, "Unknown ");
2092
break;
2093
}
2094
2095
// UHS-I max power limit is 400mA, no matter what the card says.
2096
u32 max_power_nominal = sd_storage.max_power > 400 ? 400 : sd_storage.max_power;
2097
2098
s_printf(txt_buf + strlen(txt_buf), "(%02X)\n%c%c%c%c%c\n%c%c (%04X)\n%X\n%X\n%08x\n%02d/%04d\n\n%d mW (%d mA)\n",
2099
sd_storage.cid.manfid,
2100
sd_storage.cid.prod_name[0], sd_storage.cid.prod_name[1], sd_storage.cid.prod_name[2],
2101
sd_storage.cid.prod_name[3], sd_storage.cid.prod_name[4],
2102
(sd_storage.cid.oemid >> 8) & 0xFF, sd_storage.cid.oemid & 0xFF, sd_storage.cid.oemid,
2103
sd_storage.cid.hwrev, sd_storage.cid.fwrev, sd_storage.cid.serial,
2104
sd_storage.cid.month, sd_storage.cid.year,
2105
max_power_nominal * 3600 / 1000, sd_storage.max_power);
2106
2107
switch (nyx_str->info.sd_init)
2108
{
2109
case SD_1BIT_HS25:
2110
strcat(txt_buf, "HS25 1bit");
2111
break;
2112
case SD_4BIT_HS25:
2113
strcat(txt_buf, "HS25");
2114
break;
2115
case SD_UHS_SDR82: // Report as SDR104.
2116
case SD_UHS_SDR104:
2117
strcat(txt_buf, "SDR104");
2118
break;
2119
case 0:
2120
default:
2121
strcat(txt_buf, "Undefined");
2122
break;
2123
}
2124
2125
lv_label_set_text(lb_val, txt_buf);
2126
2127
lv_obj_set_width(lb_val, lv_obj_get_width(val));
2128
lv_obj_align(val, desc, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
2129
2130
lv_obj_t *desc2 = lv_cont_create(win, NULL);
2131
lv_obj_set_size(desc2, LV_HOR_RES / 2 / 11 * 5, LV_VER_RES - (LV_DPI * 11 / 8) * 5 / 2);
2132
2133
lv_obj_t * lb_desc2 = lv_label_create(desc2, lb_desc);
2134
2135
lv_label_set_static_text(lb_desc2,
2136
"#00DDFF Card-Specific Data#\n"
2137
"Cmd Classes:\n"
2138
"Capacity:\n"
2139
"Capacity (LBA):\n"
2140
"Bus Width:\n"
2141
"Current Rate:\n"
2142
"Speed Class:\n"
2143
"UHS Classes:\n"
2144
"Max Bus Speed:\n\n"
2145
"Write Protect:"
2146
);
2147
lv_obj_set_width(lb_desc2, lv_obj_get_width(desc2));
2148
lv_obj_align(desc2, val, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 5 * 3, 0);
2149
2150
lv_obj_t *val2 = lv_cont_create(win, NULL);
2151
lv_obj_set_size(val2, LV_HOR_RES / 4, LV_VER_RES - (LV_DPI * 11 / 8) * 5 / 2);
2152
2153
lv_obj_t * lb_val2 = lv_label_create(val2, lb_desc);
2154
2155
char *wp_info;
2156
switch (sd_storage.csd.write_protect)
2157
{
2158
case 1:
2159
wp_info = "Temporary";
2160
break;
2161
case 2:
2162
case 3:
2163
wp_info = "Permanent";
2164
break;
2165
default:
2166
wp_info = "None";
2167
break;
2168
}
2169
2170
bool uhs_au_mb = false;
2171
u32 uhs_au_size = sd_storage_get_ssr_au(&sd_storage);
2172
if (uhs_au_size >= 1024)
2173
{
2174
uhs_au_mb = true;
2175
uhs_au_size /= 1024;
2176
}
2177
2178
sd_func_modes_t fmodes = { 0 };
2179
sd_storage_get_fmodes(&sd_storage, NULL, &fmodes);
2180
2181
char *bus_speed;
2182
if (fmodes.cmd_system & SD_MODE_UHS_DDR200)
2183
bus_speed = "DDR200";
2184
else if (fmodes.access_mode & SD_MODE_UHS_SDR104)
2185
bus_speed = "SDR104";
2186
else if (fmodes.access_mode & SD_MODE_UHS_SDR50)
2187
bus_speed = "SDR50";
2188
else if (fmodes.access_mode & SD_MODE_UHS_DDR50)
2189
bus_speed = "DDR50";
2190
else if (fmodes.access_mode & SD_MODE_UHS_SDR25)
2191
bus_speed = "SDR25";
2192
else
2193
bus_speed = "SDR12";
2194
2195
char *cpe = NULL;
2196
if (sd_storage.ssr.app_class == 2)
2197
{
2198
u8 *buf = zalloc(512);
2199
2200
// Directly get and parse ext reg for performance enhance.
2201
sd_storage_parse_perf_enhance(&sd_storage, 2, 0, 0, buf);
2202
2203
bool has_perf_enhance = sd_storage.ser.cache &&
2204
sd_storage.ser.cmdq &&
2205
sd_storage.ser.cache == sd_storage.ser.cache_ext &&
2206
sd_storage.ser.cmdq == sd_storage.ser.cmdq_ext;
2207
if (has_perf_enhance)
2208
cpe = "#FFDD00 "; // CMDQ/CACHE support via a quirk.
2209
else
2210
cpe = "#FF3C28 "; // Broken.
2211
2212
// Get and parse ext reg for performance enhance in spec.
2213
sd_storage_get_ext_regs(&sd_storage, buf);
2214
2215
if (sd_storage.ser.valid)
2216
{
2217
has_perf_enhance = sd_storage.ser.cache &&
2218
sd_storage.ser.cmdq &&
2219
sd_storage.ser.cache == sd_storage.ser.cache_ext &&
2220
sd_storage.ser.cmdq == sd_storage.ser.cmdq_ext;
2221
2222
if (has_perf_enhance)
2223
cpe = NULL; // CMDQ/CACHE support in spec.
2224
else
2225
cpe = "#FF3C28 "; // Broken.
2226
}
2227
2228
free(buf);
2229
}
2230
2231
s_printf(txt_buf,
2232
"#00DDFF v%d.0#\n"
2233
"%02X\n"
2234
"%d MiB\n"
2235
"%X (CP %X)\n"
2236
"%d\n"
2237
"%d MB/s (%d MHz)\n"
2238
"%d (AU: %d %s\n"
2239
"U%d V%d %sA%d%s\n"
2240
"%s\n\n"
2241
"%s",
2242
sd_storage.csd.structure + 1,
2243
sd_storage.csd.cmdclass,
2244
sd_storage.sec_cnt >> 11,
2245
sd_storage.sec_cnt, sd_storage.ssr.protected_size >> 9,
2246
sd_storage.ssr.bus_width,
2247
sd_storage.csd.busspeed,
2248
(sd_storage.csd.busspeed > 10) ? (sd_storage.csd.busspeed * 2) : 50,
2249
sd_storage.ssr.speed_class, uhs_au_size, uhs_au_mb ? "MiB)" : "KiB)",
2250
sd_storage.ssr.uhs_grade, sd_storage.ssr.video_class, cpe ? cpe : "", sd_storage.ssr.app_class, cpe ? "#" : "",
2251
bus_speed,
2252
wp_info);
2253
2254
lv_label_set_text(lb_val2, txt_buf);
2255
2256
lv_obj_set_width(lb_val2, lv_obj_get_width(val2));
2257
lv_obj_align(val2, desc2, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
2258
2259
lv_obj_t *line_sep = lv_line_create(win, NULL);
2260
static const lv_point_t line_pp[] = { {0, 0}, { LV_HOR_RES - (LV_DPI - (LV_DPI / 4)) * 12, 0} };
2261
lv_line_set_points(line_sep, line_pp, 2);
2262
lv_line_set_style(line_sep, lv_theme_get_current()->line.decor);
2263
lv_obj_align(line_sep, desc, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI * 410 / 100, LV_DPI / 7);
2264
2265
lv_obj_t *desc3 = lv_cont_create(win, NULL);
2266
lv_obj_set_size(desc3, LV_HOR_RES / 2 / 2 * 2, LV_VER_RES - (LV_DPI * 11 / 8) * 4);
2267
2268
lv_obj_t * lb_desc3 = lv_label_create(desc3, lb_desc);
2269
lv_label_set_text(lb_desc3, "#D4FF00 Acquiring info...#");
2270
lv_obj_set_width(lb_desc3, lv_obj_get_width(desc3));
2271
2272
lv_obj_align(desc3, desc, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 2);
2273
2274
manual_system_maintenance(true);
2275
2276
lv_obj_set_size(desc3, LV_HOR_RES / 2 / 6 * 2, LV_VER_RES - (LV_DPI * 11 / 8) * 4);
2277
lv_obj_align(desc3, desc, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 2);
2278
2279
lv_obj_t *val3 = lv_cont_create(win, NULL);
2280
lv_obj_set_size(val3, LV_HOR_RES / 12 * 3, LV_VER_RES - (LV_DPI * 11 / 8) * 4);
2281
2282
lv_obj_t * lb_val3 = lv_label_create(val3, lb_desc);
2283
lv_label_set_text(lb_val3, "");
2284
2285
lv_obj_align(val3, desc3, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
2286
2287
lv_obj_t *desc4 = lv_cont_create(win, NULL);
2288
lv_obj_set_size(desc4, LV_HOR_RES / 2 / 2 * 2, LV_VER_RES - (LV_DPI * 11 / 8) * 4);
2289
2290
lv_obj_t * lb_desc4 = lv_label_create(desc4, lb_desc);
2291
lv_label_set_text(lb_desc4, " ");
2292
lv_obj_set_width(lb_desc4, lv_obj_get_width(desc4));
2293
2294
lv_label_set_text(lb_desc4,
2295
"#00DDFF SDMMC1 Errors:#\n"
2296
"Init fails:\n"
2297
"Read/Write fails:\n"
2298
"Read/Write errors:"
2299
);
2300
lv_obj_set_size(desc4, LV_HOR_RES / 2 / 11 * 5, LV_VER_RES - (LV_DPI * 11 / 8) * 4);
2301
lv_obj_set_width(lb_desc4, lv_obj_get_width(desc4));
2302
lv_obj_align(desc4, val3, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 5 * 3, 0);
2303
2304
lv_obj_t *val4 = lv_cont_create(win, NULL);
2305
lv_obj_set_size(val4, LV_HOR_RES / 4, LV_VER_RES - (LV_DPI * 11 / 8) * 4);
2306
2307
lv_obj_t * lb_val4 = lv_label_create(val4, lb_desc);
2308
2309
u16 *sd_errors = sd_get_error_count();
2310
s_printf(txt_buf, "\n%d (%d)\n%d (%d)\n%d (%d)",
2311
sd_errors[SD_ERROR_INIT_FAIL], nyx_str->info.sd_errors[SD_ERROR_INIT_FAIL],
2312
sd_errors[SD_ERROR_RW_FAIL], nyx_str->info.sd_errors[SD_ERROR_RW_FAIL],
2313
sd_errors[SD_ERROR_RW_RETRY], nyx_str->info.sd_errors[SD_ERROR_RW_RETRY]);
2314
2315
lv_label_set_text(lb_val4, txt_buf);
2316
2317
lv_obj_set_width(lb_val4, lv_obj_get_width(val4));
2318
lv_obj_align(val4, desc4, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
2319
2320
manual_system_maintenance(true);
2321
2322
f_getfree("", &sd_fs.free_clst, NULL);
2323
2324
lv_label_set_text(lb_desc3,
2325
"#00DDFF Found FAT FS:#\n"
2326
"Filesystem:\n"
2327
"Cluster:\n"
2328
"Size free/total:"
2329
);
2330
2331
lv_obj_set_width(lb_desc3, lv_obj_get_width(desc3));
2332
2333
s_printf(txt_buf, "\n%s\n%d %s\n%d/%d MiB",
2334
sd_fs.fs_type == FS_EXFAT ? ("exFAT "SYMBOL_SHRK) : ("FAT32"),
2335
(sd_fs.csize > 1) ? (sd_fs.csize >> 1) : SD_BLOCKSIZE,
2336
(sd_fs.csize > 1) ? "KiB" : "B",
2337
(u32)(sd_fs.free_clst * sd_fs.csize >> SECTORS_TO_MIB_COEFF),
2338
(u32)(sd_fs.n_fatent * sd_fs.csize >> SECTORS_TO_MIB_COEFF));
2339
2340
lv_label_set_text(lb_val3, txt_buf);
2341
2342
lv_obj_set_width(lb_val3, lv_obj_get_width(val3));
2343
2344
free(txt_buf);
2345
sd_unmount();
2346
2347
failed:
2348
nyx_window_toggle_buttons(win, false);
2349
2350
return LV_RES_OK;
2351
}
2352
2353
static lv_res_t _create_window_battery_status(lv_obj_t *btn)
2354
{
2355
lv_obj_t *win = nyx_create_standard_window(SYMBOL_BATTERY_FULL" Battery Info");
2356
lv_win_add_btn(win, NULL, SYMBOL_DOWNLOAD" Dump Fuel Regs", _battery_dump_window_action);
2357
2358
lv_obj_t *desc = lv_cont_create(win, NULL);
2359
lv_obj_set_size(desc, LV_HOR_RES / 2 / 4 * 2, LV_VER_RES - (LV_DPI * 11 / 7) - 5);
2360
2361
lv_obj_t * lb_desc = lv_label_create(desc, NULL);
2362
lv_label_set_long_mode(lb_desc, LV_LABEL_LONG_BREAK);
2363
lv_label_set_recolor(lb_desc, true);
2364
2365
lv_label_set_static_text(lb_desc,
2366
"#00DDFF Fuel Gauge IC Info:#\n"
2367
"Capacity now:\n"
2368
"Capacity full:\n"
2369
"Capacity (design):\n"
2370
"Current now:\n"
2371
"Current average:\n"
2372
"Voltage now:\n"
2373
"Voltage open-circuit:\n"
2374
"Min voltage reached:\n"
2375
"Max voltage reached:\n"
2376
"Empty voltage:\n"
2377
"Battery temp:\n\n"
2378
"#00DDFF PMIC IC Info:#\n"
2379
"Main PMIC:\n\n"
2380
"CPU/GPU PMIC:\n"
2381
);
2382
lv_obj_set_width(lb_desc, lv_obj_get_width(desc));
2383
2384
lv_obj_t *val = lv_cont_create(win, NULL);
2385
lv_obj_set_size(val, LV_HOR_RES / 5, LV_VER_RES - (LV_DPI * 11 / 7));
2386
2387
lv_obj_t * lb_val = lv_label_create(val, lb_desc);
2388
2389
char *txt_buf = (char *)malloc(SZ_16K);
2390
int value = 0;
2391
int cap_pct = 0;
2392
2393
// Fuel gauge IC info.
2394
max17050_get_property(MAX17050_RepSOC, &cap_pct);
2395
max17050_get_property(MAX17050_RepCap, &value);
2396
s_printf(txt_buf, "\n%d mAh [%d %%]\n", value, cap_pct >> 8);
2397
2398
max17050_get_property(MAX17050_FullCAP, &value);
2399
s_printf(txt_buf + strlen(txt_buf), "%d mAh\n", value);
2400
2401
max17050_get_property(MAX17050_DesignCap, &value);
2402
bool design_cap_init = value == 1000;
2403
s_printf(txt_buf + strlen(txt_buf), "%s%d mAh%s\n",
2404
design_cap_init ? "#FF8000 " : "", value, design_cap_init ? " - Init "SYMBOL_WARNING"#" : "");
2405
2406
max17050_get_property(MAX17050_Current, &value);
2407
s_printf(txt_buf + strlen(txt_buf), "%d mA\n", value / 1000);
2408
2409
max17050_get_property(MAX17050_AvgCurrent, &value);
2410
s_printf(txt_buf + strlen(txt_buf), "%d mA\n", value / 1000);
2411
2412
max17050_get_property(MAX17050_VCELL, &value);
2413
bool voltage_empty = value < 3200;
2414
s_printf(txt_buf + strlen(txt_buf), "%s%d mV%s\n",
2415
voltage_empty ? "#FF8000 " : "", value, voltage_empty ? " - Low "SYMBOL_WARNING"#" : "");
2416
2417
max17050_get_property(MAX17050_OCVInternal, &value);
2418
s_printf(txt_buf + strlen(txt_buf), "%d mV\n", value);
2419
2420
max17050_get_property(MAX17050_MinVolt, &value);
2421
s_printf(txt_buf + strlen(txt_buf), "%d mV\n", value);
2422
2423
max17050_get_property(MAX17050_MaxVolt, &value);
2424
s_printf(txt_buf + strlen(txt_buf), "%d mV\n", value);
2425
2426
max17050_get_property(MAX17050_V_empty, &value);
2427
s_printf(txt_buf + strlen(txt_buf), "%d mV\n", value);
2428
2429
max17050_get_property(MAX17050_TEMP, &value);
2430
s_printf(txt_buf + strlen(txt_buf), "%d.%d oC\n\n\n", value / 10, (value >= 0 ? value : (~value + 1)) % 10);
2431
2432
// Main Pmic IC info.
2433
value = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CID4);
2434
u32 main_pmic_version = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CID3) & 0xF;
2435
2436
if (value == 0x35)
2437
s_printf(txt_buf + strlen(txt_buf), "max77620 v%d\nErista OTP\n", main_pmic_version);
2438
else if (value == 0x53)
2439
s_printf(txt_buf + strlen(txt_buf), "max77620 v%d\nMariko OTP\n", main_pmic_version);
2440
else
2441
s_printf(txt_buf + strlen(txt_buf), "max77620 v%d\n#FF8000 Unknown OTP# (%02X)\n", main_pmic_version, value);
2442
2443
// CPU/GPU/DRAM Pmic IC info.
2444
u32 cpu_gpu_pmic_type = h_cfg.t210b01 ? (FUSE(FUSE_RESERVED_ODM28_B01) & 1) + 1 : 0;
2445
switch (cpu_gpu_pmic_type)
2446
{
2447
case 0:
2448
s_printf(txt_buf + strlen(txt_buf), "max77621 v%d",
2449
i2c_recv_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_REG_CHIPID1));
2450
break;
2451
case 1:
2452
s_printf(txt_buf + strlen(txt_buf), "max77812-2 v%d", // High power GPU. 2 Outputs, phases 3 1.
2453
i2c_recv_byte(I2C_5, MAX77812_PHASE31_CPU_I2C_ADDR, MAX77812_REG_VERSION) & 7);
2454
break;
2455
case 2:
2456
s_printf(txt_buf + strlen(txt_buf), "max77812-3 v%d.0", // Low power GPU. 3 Outputs, phases 2 1 1.
2457
i2c_recv_byte(I2C_5, MAX77812_PHASE211_CPU_I2C_ADDR, MAX77812_REG_VERSION) & 7);
2458
break;
2459
}
2460
2461
lv_label_set_text(lb_val, txt_buf);
2462
2463
lv_obj_set_width(lb_val, lv_obj_get_width(val));
2464
lv_obj_align(val, desc, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
2465
2466
lv_obj_t *desc2 = lv_cont_create(win, NULL);
2467
lv_obj_set_size(desc2, LV_HOR_RES / 2 / 7 * 4, LV_VER_RES - (LV_DPI * 11 / 7) - 5);
2468
2469
lv_obj_t * lb_desc2 = lv_label_create(desc2, lb_desc);
2470
2471
lv_label_set_static_text(lb_desc2,
2472
"#00DDFF Battery Charger IC Info:#\n"
2473
"Input current limit:\n"
2474
"System voltage limit:\n"
2475
"Charge current limit:\n"
2476
"Charge voltage limit:\n"
2477
"Charge status:\n"
2478
"Temperature status:\n\n"
2479
"#00DDFF USB-PD IC Info:#\n"
2480
"Connection status:\n"
2481
"Input Wattage Limit:\n"
2482
"USB-PD Profiles:"
2483
);
2484
lv_obj_set_width(lb_desc2, lv_obj_get_width(desc2));
2485
lv_obj_align(desc2, val, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 2, 0);
2486
2487
lv_obj_t *val2 = lv_cont_create(win, NULL);
2488
lv_obj_set_size(val2, LV_HOR_RES / 2 / 3, LV_VER_RES - (LV_DPI * 11 / 7) - 5);
2489
2490
lv_obj_t * lb_val2 = lv_label_create(val2, lb_desc);
2491
2492
// Charger IC info.
2493
int iinlim = 0;
2494
bq24193_get_property(BQ24193_InputCurrentLimit, &iinlim);
2495
s_printf(txt_buf, "\n%d mA\n", iinlim);
2496
2497
bq24193_get_property(BQ24193_SystemMinimumVoltage, &value);
2498
s_printf(txt_buf + strlen(txt_buf), "%d mV\n", value);
2499
2500
bq24193_get_property(BQ24193_FastChargeCurrentLimit, &value);
2501
s_printf(txt_buf + strlen(txt_buf), "%d mA\n", value);
2502
2503
bq24193_get_property(BQ24193_ChargeVoltageLimit, &value);
2504
s_printf(txt_buf + strlen(txt_buf), "%d mV\n", value);
2505
2506
bq24193_get_property(BQ24193_ChargeStatus, &value);
2507
switch (value)
2508
{
2509
case 0:
2510
strcat(txt_buf, "Not charging\n");
2511
break;
2512
case 1:
2513
strcat(txt_buf, "Pre-charging\n");
2514
break;
2515
case 2:
2516
strcat(txt_buf, "Fast charging\n");
2517
break;
2518
case 3:
2519
strcat(txt_buf, "Charge terminated\n");
2520
break;
2521
default:
2522
s_printf(txt_buf + strlen(txt_buf), "Unknown (%d)\n", value);
2523
break;
2524
}
2525
2526
bq24193_get_property(BQ24193_TempStatus, &value);
2527
switch (value)
2528
{
2529
case 0:
2530
strcat(txt_buf, "Normal");
2531
break;
2532
case 2:
2533
strcat(txt_buf, "Warm");
2534
break;
2535
case 3:
2536
strcat(txt_buf, "Cool");
2537
break;
2538
case 5:
2539
strcat(txt_buf, "#FF8000 Cold#");
2540
break;
2541
case 6:
2542
strcat(txt_buf, "#FF8000 Hot#");
2543
break;
2544
default:
2545
s_printf(txt_buf + strlen(txt_buf), "Unknown (%d)", value);
2546
break;
2547
}
2548
2549
// USB-PD IC info.
2550
bool inserted;
2551
u32 wattage = 0;
2552
usb_pd_objects_t usb_pd;
2553
bm92t36_get_sink_info(&inserted, &usb_pd);
2554
strcat(txt_buf, "\n\n\n");
2555
strcat(txt_buf, inserted ? "Connected" : "Disconnected");
2556
2557
// Select 5V is no PD contract.
2558
wattage = iinlim * (usb_pd.pdo_no ? usb_pd.selected_pdo.voltage : 5);
2559
2560
s_printf(txt_buf + strlen(txt_buf), "\n%d.%d W", wattage / 1000, (wattage % 1000) / 100);
2561
2562
if (!usb_pd.pdo_no)
2563
strcat(txt_buf, "\nNon PD");
2564
2565
// Limit to 6 profiles so it can fit.
2566
usb_pd.pdo_no = MIN(usb_pd.pdo_no, 6);
2567
2568
for (u32 i = 0; i < usb_pd.pdo_no; i++)
2569
{
2570
bool selected =
2571
usb_pd.pdos[i].amperage == usb_pd.selected_pdo.amperage &&
2572
usb_pd.pdos[i].voltage == usb_pd.selected_pdo.voltage;
2573
s_printf(txt_buf + strlen(txt_buf), "\n%s%d mA, %2d V%s",
2574
selected ? "#D4FF00 " : "",
2575
usb_pd.pdos[i].amperage, usb_pd.pdos[i].voltage,
2576
selected ? "#" : "");
2577
}
2578
2579
lv_label_set_text(lb_val2, txt_buf);
2580
2581
lv_obj_set_width(lb_val2, lv_obj_get_width(val2));
2582
lv_obj_align(val2, desc2, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
2583
2584
free(txt_buf);
2585
2586
return LV_RES_OK;
2587
}
2588
2589
static bool _lockpick_exists_check()
2590
{
2591
#define LOCKPICK_MAGIC_OFFSET 0x118
2592
#define LOCKPICK_VERSION_OFFSET 0x11C
2593
#define LOCKPICK_MAGIC 0x4B434F4C // LOCK.
2594
#define LOCKPICK_MIN_VERSION 0x1090500 // 1.9.5.
2595
2596
bool found = false;
2597
void *buf = malloc(0x200);
2598
if (sd_mount())
2599
{
2600
FIL fp;
2601
if (f_open(&fp, "bootloader/payloads/Lockpick_RCM.bin", FA_READ))
2602
goto out;
2603
2604
// Read Lockpick payload and check versioning.
2605
if (f_read(&fp, buf, 0x200, NULL))
2606
{
2607
f_close(&fp);
2608
2609
goto out;
2610
}
2611
2612
u32 magic = *(u32 *)(buf + LOCKPICK_MAGIC_OFFSET);
2613
u32 version = byte_swap_32(*(u32 *)(buf + LOCKPICK_VERSION_OFFSET) - 0x303030);
2614
2615
if (magic == LOCKPICK_MAGIC && version >= LOCKPICK_MIN_VERSION)
2616
found = true;
2617
2618
f_close(&fp);
2619
}
2620
2621
out:
2622
free(buf);
2623
sd_unmount();
2624
2625
return found;
2626
}
2627
2628
void create_tab_info(lv_theme_t *th, lv_obj_t *parent)
2629
{
2630
lv_page_set_scrl_layout(parent, LV_LAYOUT_PRETTY);
2631
2632
static lv_style_t h_style;
2633
lv_style_copy(&h_style, &lv_style_transp);
2634
h_style.body.padding.inner = 0;
2635
h_style.body.padding.hor = LV_DPI - (LV_DPI / 4);
2636
h_style.body.padding.ver = LV_DPI / 6;
2637
2638
// Create SoC Info container.
2639
lv_obj_t *h1 = lv_cont_create(parent, NULL);
2640
lv_cont_set_style(h1, &h_style);
2641
lv_cont_set_fit(h1, false, true);
2642
lv_obj_set_width(h1, (LV_HOR_RES / 9) * 4);
2643
lv_obj_set_click(h1, false);
2644
lv_cont_set_layout(h1, LV_LAYOUT_OFF);
2645
2646
lv_obj_t *label_sep = lv_label_create(h1, NULL);
2647
lv_label_set_static_text(label_sep, "");
2648
2649
lv_obj_t *label_txt = lv_label_create(h1, NULL);
2650
lv_label_set_static_text(label_txt, "SoC & HW Info");
2651
lv_obj_set_style(label_txt, th->label.prim);
2652
lv_obj_align(label_txt, label_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, 0);
2653
2654
lv_obj_t *line_sep = lv_line_create(h1, NULL);
2655
static const lv_point_t line_pp[] = { {0, 0}, { LV_HOR_RES - (LV_DPI - (LV_DPI / 4)) * 2, 0} };
2656
lv_line_set_points(line_sep, line_pp, 2);
2657
lv_line_set_style(line_sep, th->line.decor);
2658
lv_obj_align(line_sep, label_txt, LV_ALIGN_OUT_BOTTOM_LEFT, -(LV_DPI / 4), LV_DPI / 8);
2659
2660
// Create Bootrom button.
2661
lv_obj_t *btn = lv_btn_create(h1, NULL);
2662
if (hekate_bg)
2663
{
2664
lv_btn_set_style(btn, LV_BTN_STYLE_REL, &btn_transp_rel);
2665
lv_btn_set_style(btn, LV_BTN_STYLE_PR, &btn_transp_pr);
2666
}
2667
lv_obj_t *label_btn = lv_label_create(btn, NULL);
2668
lv_btn_set_fit(btn, true, true);
2669
lv_label_set_static_text(label_btn, SYMBOL_CHIP" Bootrom");
2670
lv_obj_align(btn, line_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, LV_DPI / 4);
2671
lv_btn_set_action(btn, LV_BTN_ACTION_CLICK, _create_window_bootrom_info_status);
2672
2673
// Create TSEC Keys button.
2674
lv_obj_t *btn2 = lv_btn_create(h1, btn);
2675
label_btn = lv_label_create(btn2, NULL);
2676
lv_label_set_static_text(label_btn, SYMBOL_KEY" Lockpick");
2677
lv_obj_align(btn2, btn, LV_ALIGN_OUT_RIGHT_TOP, LV_DPI * 11 / 15, 0);
2678
lv_btn_set_action(btn2, LV_BTN_ACTION_CLICK, _create_mbox_lockpick);
2679
2680
bool lockpick_found = _lockpick_exists_check();
2681
if (!lockpick_found)
2682
lv_btn_set_state(btn2, LV_BTN_STATE_INA);
2683
2684
lv_obj_t *label_txt2 = lv_label_create(h1, NULL);
2685
lv_label_set_recolor(label_txt2, true);
2686
2687
if (lockpick_found)
2688
{
2689
lv_label_set_static_text(label_txt2,
2690
"View Ipatches and dump the unpatched and patched versions\nof BootROM.\n"
2691
"Or dump every single key via #C7EA46 Lockpick RCM#.\n");
2692
}
2693
else
2694
{
2695
lv_label_set_static_text(label_txt2,
2696
"View Ipatches and dump the unpatched and patched versions\nof BootROM. Or dump every single key via #C7EA46 Lockpick RCM#.\n"
2697
"#FFDD00 bootloader/payloads/Lockpick_RCM.bin is missing or old!#\n");
2698
}
2699
2700
lv_obj_set_style(label_txt2, &hint_small_style);
2701
lv_obj_align(label_txt2, btn, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3);
2702
2703
static lv_style_t line_style;
2704
lv_style_copy(&line_style, th->line.decor);
2705
line_style.line.color = LV_COLOR_HEX(0x444444);
2706
2707
line_sep = lv_line_create(h1, line_sep);
2708
lv_obj_align(line_sep, label_txt2, LV_ALIGN_OUT_BOTTOM_LEFT, -(LV_DPI / 4), LV_DPI / 16);
2709
lv_line_set_style(line_sep, &line_style);
2710
2711
// Create Fuses button.
2712
lv_obj_t *btn3 = lv_btn_create(h1, btn);
2713
label_btn = lv_label_create(btn3, NULL);
2714
lv_btn_set_fit(btn3, true, true);
2715
lv_label_set_static_text(label_btn, SYMBOL_CIRCUIT" HW & Fuses");
2716
lv_obj_align(btn3, line_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, LV_DPI / 2);
2717
lv_btn_set_action(btn3, LV_BTN_ACTION_CLICK, _create_window_hw_info_status);
2718
2719
// Create KFuses button.
2720
lv_obj_t *btn4 = lv_btn_create(h1, btn);
2721
label_btn = lv_label_create(btn4, NULL);
2722
lv_label_set_static_text(label_btn, SYMBOL_SHUFFLE" KFuses");
2723
lv_obj_align(btn4, btn3, LV_ALIGN_OUT_RIGHT_TOP, LV_DPI * 46 / 100, 0);
2724
lv_btn_set_action(btn4, LV_BTN_ACTION_CLICK, _kfuse_dump_window_action);
2725
2726
lv_obj_t *label_txt4 = lv_label_create(h1, NULL);
2727
lv_label_set_recolor(label_txt4, true);
2728
lv_label_set_static_text(label_txt4,
2729
"View and dump the cached #C7EA46 Fuses# and #C7EA46 KFuses#.\n"
2730
"Fuses contain info about the SoC/SKU and KFuses HDCP keys.\n"
2731
"You can also see info about #C7EA46 DRAM#, #C7EA46 Screen# and #C7EA46 Touch panel#.");
2732
lv_obj_set_style(label_txt4, &hint_small_style);
2733
lv_obj_align(label_txt4, btn3, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3);
2734
2735
// Create Storage & Battery Info container.
2736
lv_obj_t *h2 = lv_cont_create(parent, NULL);
2737
lv_cont_set_style(h2, &h_style);
2738
lv_cont_set_fit(h2, false, true);
2739
lv_obj_set_width(h2, (LV_HOR_RES / 9) * 4);
2740
lv_obj_set_click(h2, false);
2741
lv_cont_set_layout(h2, LV_LAYOUT_OFF);
2742
lv_obj_align(h2, h1, LV_ALIGN_OUT_RIGHT_TOP, 0, 0);
2743
2744
label_sep = lv_label_create(h2, NULL);
2745
lv_label_set_static_text(label_sep, "");
2746
2747
lv_obj_t *label_txt3 = lv_label_create(h2, NULL);
2748
lv_label_set_static_text(label_txt3, "Storage & Battery Info");
2749
lv_obj_set_style(label_txt3, th->label.prim);
2750
lv_obj_align(label_txt3, label_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, 0);
2751
2752
line_sep = lv_line_create(h2, line_sep);
2753
lv_obj_align(line_sep, label_txt3, LV_ALIGN_OUT_BOTTOM_LEFT, -(LV_DPI / 2), LV_DPI / 8);
2754
lv_line_set_style(line_sep, th->line.decor);
2755
2756
// Create eMMC button.
2757
lv_obj_t *btn5 = lv_btn_create(h2, NULL);
2758
if (hekate_bg)
2759
{
2760
lv_btn_set_style(btn5, LV_BTN_STYLE_REL, &btn_transp_rel);
2761
lv_btn_set_style(btn5, LV_BTN_STYLE_PR, &btn_transp_pr);
2762
}
2763
label_btn = lv_label_create(btn5, NULL);
2764
lv_btn_set_fit(btn5, true, true);
2765
lv_label_set_static_text(label_btn, SYMBOL_CHIP" eMMC ");
2766
lv_obj_align(btn5, line_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 2, LV_DPI / 4);
2767
lv_btn_set_action(btn5, LV_BTN_ACTION_CLICK, _create_window_emmc_info_status);
2768
2769
// Create microSD button.
2770
lv_obj_t *btn6 = lv_btn_create(h2, btn);
2771
label_btn = lv_label_create(btn6, NULL);
2772
lv_label_set_static_text(label_btn, SYMBOL_SD" microSD ");
2773
lv_obj_align(btn6, btn5, LV_ALIGN_OUT_RIGHT_TOP, LV_DPI * 3 / 4, 0);
2774
lv_btn_set_action(btn6, LV_BTN_ACTION_CLICK, _create_window_sdcard_info_status);
2775
2776
lv_obj_t *label_txt5 = lv_label_create(h2, NULL);
2777
lv_label_set_recolor(label_txt5, true);
2778
lv_label_set_static_text(label_txt5,
2779
"View info about the eMMC or microSD and their partition list.\n"
2780
"Additionally you can benchmark read speeds.");
2781
lv_obj_set_style(label_txt5, &hint_small_style);
2782
lv_obj_align(label_txt5, btn5, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3);
2783
2784
line_sep = lv_line_create(h2, line_sep);
2785
lv_obj_align(line_sep, label_txt5, LV_ALIGN_OUT_BOTTOM_LEFT, -(LV_DPI / 4), LV_DPI / 2);
2786
lv_line_set_style(line_sep, &line_style);
2787
2788
// Create Battery button.
2789
lv_obj_t *btn7 = lv_btn_create(h2, NULL);
2790
if (hekate_bg)
2791
{
2792
lv_btn_set_style(btn7, LV_BTN_STYLE_REL, &btn_transp_rel);
2793
lv_btn_set_style(btn7, LV_BTN_STYLE_PR, &btn_transp_pr);
2794
}
2795
label_btn = lv_label_create(btn7, NULL);
2796
lv_btn_set_fit(btn7, true, true);
2797
lv_label_set_static_text(label_btn, SYMBOL_BATTERY_FULL" Battery");
2798
lv_obj_align(btn7, line_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, LV_DPI / 2);
2799
lv_btn_set_action(btn7, LV_BTN_ACTION_CLICK, _create_window_battery_status);
2800
2801
lv_obj_t *label_txt6 = lv_label_create(h2, NULL);
2802
lv_label_set_recolor(label_txt6, true);
2803
lv_label_set_static_text(label_txt6,
2804
"View battery and battery charger related info.\n"
2805
"Additionally you can dump battery charger's registers.\n");
2806
lv_obj_set_style(label_txt6, &hint_small_style);
2807
lv_obj_align(label_txt6, btn7, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3);
2808
}
2809
2810