Compare commits

..

14 Commits
0.0.1 ... 0.1.1

Author SHA1 Message Date
Such Meme, Many Skill
e8ddc9cf2f add 9.0 pkg1 which fixes tegraexplorer on 9.0 2019-09-18 19:42:31 +02:00
Such Meme, Many Skill
1c5b049453 (attempt at) doing readme stuff 2019-08-21 00:22:05 +02:00
Such Meme, Many Skill
0c4be1f917 Implement hacky solution to launch firmwaredumper
// i swear this shit hates me
2019-08-21 00:12:26 +02:00
Such Meme, Many Skill
d4eb56a35f Implement broken™️ firmware dumping 2019-08-20 19:39:30 +02:00
Such Meme, Many Skill
9281e4bbbc add dump to sd file option 2019-08-20 01:26:39 +02:00
Such Meme, Many Skill
d000f86c89 Re order the main menu 2019-08-19 23:32:20 +02:00
Such Meme, Many Skill
7dc9320b41 Add system mounting
Also fixed sizes not re rendering when scrolling
2019-08-19 23:01:47 +02:00
Such Meme, Many Skill
f3808edb40 Add biskey dumping + more menus
Thanks shchmue :D

Also can now mount and unmount the sd via the tools menu
2019-08-19 15:04:35 +02:00
Such Meme, Many Skill
7a35d2b00c Add main menu 2019-08-18 20:00:16 +02:00
Such Meme, Many Skill
a094ac4496 Fix payload launching (thanks @huhen) 2019-08-17 12:56:48 +02:00
Such Meme, Many Skill
ada4fd2c7f Add (Broken) payload launching 2019-08-17 01:08:00 +02:00
Such Meme, Many Skill
819d08415d Begone lag! (+ begone big bad overflows) 2019-08-16 23:57:54 +02:00
Such Meme, Many Skill
45eb25270f File sizes shown in list screen 2019-08-16 21:40:04 +02:00
Such Meme, Many Skill
5b15e4cdf7 fix compile errors 2019-08-16 20:07:33 +02:00
15 changed files with 671 additions and 87 deletions

View File

@@ -1,5 +1,25 @@
# TegraExplorer # TegraExplorer
A payload-based file explorer for your switch! A payload-based file explorer for your switch!
## Usage
1. Get your favorite payload injector
2. Inject TegraExplorer as a payload
Navigate around the menu's using the vol+, vol- and power buttons
## Functions
- Navigate the SD card
- Navigate the System partition of your sysnand
- Deleting, copying or moving files
- Launching payloads
- Dumping your current firmware to sd
## Screenshot
![screenshot](example.png)
# Credits # Credits
Based on [Lockpick_RCM](https://github.com/shchmue/Lockpick_RCM), and thus based on [Hekate](https://github.com/CTCaer/hekate) Based on [Lockpick_RCM](https://github.com/shchmue/Lockpick_RCM), and thus based on [Hekate](https://github.com/CTCaer/hekate)
Lots of help from:
shchmue
Denn

BIN
example.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -217,7 +217,7 @@ void gfx_putc(char c)
} }
} }
gfx_con.x += 16; gfx_con.x += 16;
if (gfx_con.x >= gfx_ctxt.width - 16) { if (gfx_con.x >= gfx_ctxt.width - 8) {
gfx_con.x = 0; gfx_con.x = 0;
gfx_con.y += 16; gfx_con.y += 16;
} }

View File

@@ -35,6 +35,7 @@ static const pkg1_id_t _pkg1_ids[] = {
{ "20190208150037", 7 }, //7.0.1 { "20190208150037", 7 }, //7.0.1
{ "20190314172056", 7 }, //8.0.0 { "20190314172056", 7 }, //8.0.0
{ "20190531152432", 8 }, //8.1.0 { "20190531152432", 8 }, //8.1.0
{ "20190809135709", 9 }, //9.0.0
{ NULL } //End. { NULL } //End.
}; };

View File

@@ -191,7 +191,7 @@
#define FF_MIN_SS 512 #define FF_MIN_SS 512
#define FF_MAX_SS 4096 #define FF_MAX_SS 512
/* This set of options configures the range of sector size to be supported. (512, /* This set of options configures the range of sector size to be supported. (512,
/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and / 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and
/ harddisk. But a larger value may be required for on-board flash memory and some / harddisk. But a larger value may be required for on-board flash memory and some

View File

@@ -31,8 +31,6 @@
#include "meme/main.h" #include "meme/main.h"
#include "meme/utils.h" #include "meme/utils.h"
#include "keys/keys.h"
sdmmc_t sd_sdmmc; sdmmc_t sd_sdmmc;
sdmmc_storage_t sd_storage; sdmmc_storage_t sd_storage;
__attribute__ ((aligned (16))) FATFS sd_fs; __attribute__ ((aligned (16))) FATFS sd_fs;
@@ -153,7 +151,6 @@ extern void pivot_stack(u32 stack_top);
void ipl_main() void ipl_main()
{ {
bool sd_mounted = false;
config_hw(); config_hw();
pivot_stack(IPL_STACK_TOP); pivot_stack(IPL_STACK_TOP);
heap_init(IPL_HEAP_START); heap_init(IPL_HEAP_START);
@@ -164,8 +161,6 @@ void ipl_main()
gfx_con_init(); gfx_con_init();
display_backlight_pwm_init(); display_backlight_pwm_init();
meme_main();
sd_mounted = sd_mount();
meme_main(sd_mounted);
sd_unmount(); sd_unmount();
} }

View File

@@ -0,0 +1,232 @@
#include "external_utils.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "../gfx/di.h"
#include "../gfx/gfx.h"
#include "../utils/btn.h"
#include "../utils/util.h"
#include "utils.h"
#include "../libs/fatfs/ff.h"
#include "../storage/sdmmc.h"
#include "graphics.h"
#include "../soc/hw_init.h"
#include "../mem/emc.h"
#include "../mem/sdram.h"
#include "../soc/t210.h"
#include "../sec/se.h"
#include "../utils/types.h"
#include "../hos/pkg1.h"
#include "../storage/nx_emmc.h"
#include "../sec/tsec.h"
#include "../soc/t210.h"
#include "../soc/fuse.h"
#include "../mem/mc.h"
extern void reloc_patcher(u32 payload_dst, u32 payload_src, u32 payload_size);
extern boot_cfg_t b_cfg;
extern bool sd_mount();
extern void sd_unmount();
static bool _key_exists(const void *data) { return memcmp(data, zeros, 0x10); };
static void _generate_kek(u32 ks, const void *key_source, void *master_key, const void *kek_seed, const void *key_seed);
sdmmc_storage_t storage;
emmc_part_t *system_part;
sdmmc_t sdmmc;
int launch_payload(char *path, bool update){
if (!update) gfx_clear_grey(0x1B);
gfx_con_setpos(0, 0);
if (!path)
return 1;
if (sd_mount()){
FIL fp;
if (f_open(&fp, path, FA_READ)){
EPRINTF("Payload missing!\n");
return 2;
}
void *buf;
u32 size = f_size(&fp);
if (size < 0x30000)
buf = (void *)RCM_PAYLOAD_ADDR;
else
buf = (void *)COREBOOT_ADDR;
if (f_read(&fp, buf, size, NULL)){
f_close(&fp);
return 3;
}
f_close(&fp);
sd_unmount();
if (size < 0x30000){
reloc_patcher(PATCHED_RELOC_ENTRY, EXT_PAYLOAD_ADDR, ALIGN(size, 0x10));
reconfig_hw_workaround(false, byte_swap_32(*(u32 *)(buf + size - sizeof(u32))));
}
else {
reloc_patcher(PATCHED_RELOC_ENTRY, EXT_PAYLOAD_ADDR, 0x7000);
reconfig_hw_workaround(true, 0);
}
void (*ext_payload_ptr)() = (void *)EXT_PAYLOAD_ADDR;
void (*update_ptr)() = (void *)RCM_PAYLOAD_ADDR;
msleep(100);
if (!update)
(*ext_payload_ptr)();
else {
EMC(EMC_SCRATCH0) |= EMC_HEKA_UPD;
(*update_ptr)();
}
}
return 4;
}
int dump_biskeys(u8 bis_key[4][32]){
u8 temp_key[0x10], device_key[0x10] = {0};
tsec_ctxt_t tsec_ctxt;
int retries = 0;
sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4);
// Read package1.
u8 *pkg1 = (u8 *)malloc(0x40000);
sdmmc_storage_set_mmc_partition(&storage, 1);
sdmmc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1);
if (!pkg1_id) {
EPRINTF("Unknown pkg1 version.");
return -1;
}
bool found_tsec_fw = false;
for (const u32 *pos = (const u32 *)pkg1; (u8 *)pos < pkg1 + 0x40000; pos += 0x100 / sizeof(u32)) {
if (*pos == 0xCF42004D) {
tsec_ctxt.fw = (u8 *)pos;
found_tsec_fw = true;
break;
}
}
if (!found_tsec_fw) {
EPRINTF("Failed to locate TSEC firmware.");
return -1;
}
u8 tsec_keys[0x10] = {0};
tsec_key_data_t *key_data = (tsec_key_data_t *)(tsec_ctxt.fw + TSEC_KEY_DATA_ADDR);
tsec_ctxt.pkg1 = pkg1;
tsec_ctxt.size = 0x100 + key_data->blob0_size + key_data->blob1_size + key_data->blob2_size + key_data->blob3_size + key_data->blob4_size;
if (pkg1_id->kb >= KB_FIRMWARE_VERSION_700) {
// Exit after TSEC key generation.
*((vu16 *)((u32)tsec_ctxt.fw + 0x2DB5)) = 0x02F8;
}
int res = 0;
mc_disable_ahb_redirect();
while (tsec_query(tsec_keys, 0, &tsec_ctxt) < 0) {
memset(tsec_keys, 0x00, 0x10);
retries++;
if (retries > 15) {
res = -1;
break;
}
}
free(pkg1);
mc_enable_ahb_redirect();
if (res < 0) {
gfx_printf("ERROR %x dumping TSEC.\n", res);
return -1;
}
u32 sbk[4] = {FUSE(FUSE_PRIVATE_KEY0), FUSE(FUSE_PRIVATE_KEY1),
FUSE(FUSE_PRIVATE_KEY2), FUSE(FUSE_PRIVATE_KEY3)};
se_aes_key_set(8, tsec_keys, 0x10);
se_aes_key_set(9, sbk, 0x10);
se_aes_crypt_block_ecb(8, 0, temp_key, keyblob_key_source);
se_aes_crypt_block_ecb(9, 0, temp_key, temp_key);
se_aes_key_set(7, temp_key, 0x10);
se_aes_crypt_block_ecb(7, 0, device_key, per_console_key_source);
/* key = unwrap(source, wrapped_key):
key_set(ks, wrapped_key), block_ecb(ks, 0, key, source) -> final key in key
*/
if (_key_exists(device_key)) {
se_aes_key_set(8, device_key, 0x10);
se_aes_unwrap_key(8, 8, retail_specific_aes_key_source); // kek = unwrap(rsaks, devkey)
se_aes_crypt_block_ecb(8, 0, bis_key[0] + 0x00, bis_key_source[0] + 0x00); // bkey = unwrap(bkeys, kek)
se_aes_crypt_block_ecb(8, 0, bis_key[0] + 0x10, bis_key_source[0] + 0x10);
// kek = generate_kek(bkeks, devkey, aeskek, aeskey)
_generate_kek(8, bis_kek_source, device_key, aes_kek_generation_source, aes_key_generation_source);
se_aes_crypt_block_ecb(8, 0, bis_key[1] + 0x00, bis_key_source[1] + 0x00); // bkey = unwrap(bkeys, kek)
se_aes_crypt_block_ecb(8, 0, bis_key[1] + 0x10, bis_key_source[1] + 0x10);
se_aes_crypt_block_ecb(8, 0, bis_key[2] + 0x00, bis_key_source[2] + 0x00);
se_aes_crypt_block_ecb(8, 0, bis_key[2] + 0x10, bis_key_source[2] + 0x10);
memcpy(bis_key[3], bis_key[2], 0x20);
}
sdmmc_storage_set_mmc_partition(&storage, 0);
// Parse eMMC GPT.
LIST_INIT(gpt);
nx_emmc_gpt_parse(&gpt, &storage);
/*
char part_name[37] = "SYSTEM";
// todo: menu selection for this
u32 bis_key_index = 0;
if (strcmp(part_name, "PRODINFOF") == 0)
bis_key_index = 0;
else if (strcmp(part_name, "SAFE") == 0)
bis_key_index = 1;
else if (strcmp(part_name, "SYSTEM") == 0)
bis_key_index = 2;
else if (strcmp(part_name, "USER") == 0)
bis_key_index = 3;
else {
gfx_printf("Partition name %s unrecognized.", part_name);
return;
}
*/
se_aes_key_set(8, bis_key[2] + 0x00, 0x10);
se_aes_key_set(9, bis_key[2] + 0x10, 0x10);
system_part = nx_emmc_part_find(&gpt, "SYSTEM");
if (!system_part) {
gfx_printf("Failed to locate SYSTEM partition.");
return -1;
}
__attribute__ ((aligned (16))) FATFS emmc_fs;
if (f_mount(&emmc_fs, "emmc:", 1)) {
gfx_printf("Mount failed.");
return -1;
}
return pkg1_id->kb;
}
static void _generate_kek(u32 ks, const void *key_source, void *master_key, const void *kek_seed, const void *key_seed) {
if (!_key_exists(key_source) || !_key_exists(master_key) || !_key_exists(kek_seed))
return;
se_aes_key_set(ks, master_key, 0x10);
se_aes_unwrap_key(ks, ks, kek_seed);
se_aes_unwrap_key(ks, ks, key_source);
if (key_seed && _key_exists(key_seed))
se_aes_unwrap_key(ks, ks, key_seed);
}

View File

@@ -0,0 +1,53 @@
#pragma once
#define RELOC_META_OFF 0x7C
#define PATCHED_RELOC_SZ 0x94
#define PATCHED_RELOC_STACK 0x40007000
#define PATCHED_RELOC_ENTRY 0x40010000
#define EXT_PAYLOAD_ADDR 0xC03C0000
#define RCM_PAYLOAD_ADDR (EXT_PAYLOAD_ADDR + ALIGN(PATCHED_RELOC_SZ, 0x10))
#define COREBOOT_ADDR (0xD0000000 - 0x100000)
#define CBFS_DRAM_EN_ADDR 0x4003e000
#define CBFS_DRAM_MAGIC 0x4452414D // "DRAM"
#define EMC_BASE 0x7001B000
#define EMC(off) _REG(EMC_BASE, off)
#include "../utils/types.h"
int launch_payload(char *path, int update);
int dump_biskeys(u8 bis_key[4][32]);
static const u8 zeros[0x10] = {0};
static const u8 keyblob_key_source[0x10] = {
0xDF, 0x20, 0x6F, 0x59, 0x44, 0x54, 0xEF, 0xDC, 0x70, 0x74, 0x48, 0x3B, 0x0D, 0xED, 0x9F, 0xD3};
//======================================Keys======================================//
// from Package1 -> Secure_Monitor
static const u8 aes_kek_generation_source[0x10] = {
0x4D, 0x87, 0x09, 0x86, 0xC4, 0x5D, 0x20, 0x72, 0x2F, 0xBA, 0x10, 0x53, 0xDA, 0x92, 0xE8, 0xA9};
static const u8 retail_specific_aes_key_source[0x10] = {
0xE2, 0xD6, 0xB8, 0x7A, 0x11, 0x9C, 0xB8, 0x80, 0xE8, 0x22, 0x88, 0x8A, 0x46, 0xFB, 0xA1, 0x95};
// from Package1ldr (or Secure_Monitor on 6.2.0)
static const u8 per_console_key_source[0x10] = {
0x4F, 0x02, 0x5F, 0x0E, 0xB6, 0x6D, 0x11, 0x0E, 0xDC, 0x32, 0x7D, 0x41, 0x86, 0xC2, 0xF4, 0x78};
// from SPL
static const u8 aes_key_generation_source[0x10] = {
0x89, 0x61, 0x5E, 0xE0, 0x5C, 0x31, 0xB6, 0x80, 0x5F, 0xE5, 0x8F, 0x3D, 0xA2, 0x4F, 0x7A, 0xA8};
// from FS
static const u8 bis_kek_source[0x10] = {
0x34, 0xC1, 0xA0, 0xC4, 0x82, 0x58, 0xF8, 0xB4, 0xFA, 0x9E, 0x5E, 0x6A, 0xDA, 0xFC, 0x7E, 0x4F};
static const u8 bis_key_source[3][0x20] = {
{
0xF8, 0x3F, 0x38, 0x6E, 0x2C, 0xD2, 0xCA, 0x32, 0xA8, 0x9A, 0xB9, 0xAA, 0x29, 0xBF, 0xC7, 0x48,
0x7D, 0x92, 0xB0, 0x3A, 0xA8, 0xBF, 0xDE, 0xE1, 0xA7, 0x4C, 0x3B, 0x6E, 0x35, 0xCB, 0x71, 0x06},
{
0x41, 0x00, 0x30, 0x49, 0xDD, 0xCC, 0xC0, 0x65, 0x64, 0x7A, 0x7E, 0xB4, 0x1E, 0xED, 0x9C, 0x5F,
0x44, 0x42, 0x4E, 0xDA, 0xB4, 0x9D, 0xFC, 0xD9, 0x87, 0x77, 0x24, 0x9A, 0xDC, 0x9F, 0x7C, 0xA4},
{
0x52, 0xC2, 0xE9, 0xEB, 0x09, 0xE3, 0xEE, 0x29, 0x32, 0xA1, 0x0C, 0x1F, 0xB6, 0xA0, 0x92, 0x6C,
0x4D, 0x12, 0xE1, 0x4B, 0x2A, 0x47, 0x4C, 0x1C, 0x09, 0xCB, 0x03, 0x59, 0xF0, 0x15, 0xF4, 0xE4}
};

View File

@@ -14,13 +14,14 @@ int _copystring(char *out, const char *in, int copynumb){
if (strlength > copynumb + 1) strlength = copynumb; if (strlength > copynumb + 1) strlength = copynumb;
memset(out + strlength, '\0', 1); memset(out + strlength, '\0', 1);
int ret = copynumb - strlength; int ret = copynumb - strlength;
return ret; return ret + 4;
} }
int messagebox(char *message){ int messagebox(char *message){
int ret = -1; int ret = -1;
meme_clearscreen(); meme_clearscreen();
gfx_printf("%s", message); gfx_printf("%s", message);
msleep(100);
u8 res = btn_wait(); u8 res = btn_wait();
if (res & BTN_POWER) ret = 0; if (res & BTN_POWER) ret = 0;
else ret = 1; else ret = 1;
@@ -53,10 +54,10 @@ void meme_clearscreen(){
gfx_clear_grey(0x1B); gfx_clear_grey(0x1B);
gfx_con_setpos(0, 0); gfx_con_setpos(0, 0);
gfx_box(0, 0, 719, 15, COLOR_WHITE); gfx_box(0, 0, 719, 15, COLOR_WHITE);
gfx_printf("%k%pTegraExplorer, by SuchMemeManySkill\n%k%p", COLOR_DEFAULT, COLOR_WHITE, COLOR_WHITE, COLOR_DEFAULT); gfx_printf("%k%pTegraExplorer\n%k%p", COLOR_DEFAULT, COLOR_WHITE, COLOR_WHITE, COLOR_DEFAULT);
} }
void _printwithhighlight(int offset, int folderamount, char *items[], int highlight, unsigned int *muhbits){ void _printwithhighlight(int offset, int folderamount, char *items[], int highlight, unsigned int *muhbits, int *filesizes){
char temp[39]; char temp[39];
int i = 0; int i = 0;
int ret = 0; int ret = 0;
@@ -74,8 +75,11 @@ void _printwithhighlight(int offset, int folderamount, char *items[], int highli
} }
gfx_con.x = 720 - (16 * 6); gfx_con.x = 720 - (16 * 6);
if (muhbits[i + offset] & OPTION1) gfx_printf("DIR"); if (!(muhbits[i + offset] & OPTION1)) { //should change later
else gfx_printf("FILE"); char temp[6];
return_readable_byte_amounts(filesizes[i + offset], temp);
gfx_printf("%s", temp);
}
i++; i++;
} }
} }
@@ -86,12 +90,26 @@ int fileexplorergui(char *items[], unsigned int *muhbits, const char path[], int
int sleepvalue = 300; int sleepvalue = 300;
int offset = 0; int offset = 0;
char temp[43]; char temp[43];
gfx_con_setpos(0, 16); int *filesizes;
int i = 0;
filesizes = (int*) calloc(500, sizeof(int));
gfx_con_setpos(0, 48);
for (i = 0; i < folderamount; i++){
if(!(muhbits[i] & OPTION1)){
char temppath[PATHSIZE];
strcpy(temppath, path);
strcat(temppath, "/");
strcat(temppath, items[i]);
filesizes[i] = getfilesize(temppath);
gfx_printf("Calcing filesizes: %d / %d\r", i, folderamount - 2);
}
}
_copystring(temp, path, 43); _copystring(temp, path, 43);
gfx_con_setpos(0, 16);
gfx_printf("%k%s\n%k", COLOR_GREEN, temp, COLOR_WHITE); gfx_printf("%k%s\n%k", COLOR_GREEN, temp, COLOR_WHITE);
while(1){ while(1){
if (change){ if (change){
_printwithhighlight(offset, folderamount, items, select, muhbits); _printwithhighlight(offset, folderamount, items, select, muhbits, filesizes);
change = false; change = false;
msleep(sleepvalue); msleep(sleepvalue);
} }
@@ -121,5 +139,6 @@ int fileexplorergui(char *items[], unsigned int *muhbits, const char path[], int
if (sleepvalue < 30) sleepvalue = 30; if (sleepvalue < 30) sleepvalue = 30;
} }
int ret = select + offset; int ret = select + offset;
free(filesizes);
return ret; return ret;
} }

View File

@@ -1,4 +1,5 @@
#include <string.h> #include <string.h>
#include <stdio.h>
#include "../gfx/di.h" #include "../gfx/di.h"
#include "../gfx/gfx.h" #include "../gfx/gfx.h"
#include "../utils/btn.h" #include "../utils/btn.h"
@@ -6,36 +7,125 @@
#include "main.h" #include "main.h"
#include "mainfunctions.h" #include "mainfunctions.h"
#include "../libs/fatfs/ff.h" #include "../libs/fatfs/ff.h"
#include "../storage/sdmmc.h" #include "../utils/util.h"
#include "graphics.h" #include "graphics.h"
#include "external_utils.h"
void meme_main(bool sdinit){ extern bool sd_mount();
extern void sd_unmount();
static u32 bis_keys[4][8];
void meme_main(){
utils_gfx_init(); utils_gfx_init();
//static const u32 colors[7] = {COLOR_RED, COLOR_ORANGE, COLOR_YELLOW, COLOR_GREEN, COLOR_BLUE, COLOR_VIOLET, COLOR_DEFAULT}; //dump_keys();
//gfx_printf("%k%pTegraExplorer, made by SuchMemeManySkill \n%k%p", colors[6], colors[3], colors[3], colors[6]);
/* /*
sdmmc_storage_t storage; sdmmc_storage_t storage;
sdmmc_t sdmmc; sdmmc_t sdmmc;
sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4); sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4);
sdmmc_storage_set_mmc_partition(&storage, 1); sdmmc_storage_set_mmc_partition(&storage, 1); */
*/
//f_rename("sd:/yeet.txt", "sd:/yote.txt");
int firmver = -1;
firmver = dump_biskeys(bis_keys); // add succeed check
char *itemsinfolder[500]; char *options[6];
unsigned int muhbits[500]; char *itemsinfolder[1000];
unsigned int muhbits[1000];
bool sd_mounted = false;
sd_mounted = sd_mount();
if (!sd_mounted) messagebox("\nSD INIT FAILED");
while (1){
int i = 0, ret = 0;
if (sd_mounted){
addchartoarray("[SD:/] SD card", options, i);
i++;
}
addchartoarray("[emmc:/] SYSTEM", options, i);
if (!sd_mounted) addchartoarray("\nMount SD", options, i+1);
else addchartoarray("\nUnmount SD", options, i+1);
addchartoarray("\nTools", options, i+2);
addchartoarray("About", options, i+3);
addchartoarray("Exit", options, i+4);
meme_clearscreen();
ret = gfx_menulist(32, options, (i + 5));
if (strcmp(options[ret - 1], "[SD:/] SD card") == 0){
sdexplorer(itemsinfolder, muhbits, "sd:/");
}
else if (strcmp(options[ret - 1], "About") == 0){
messagebox(ABOUT_MESSAGE);
}
else if (strcmp(options[ret - 1], "\nMount SD") == 0 || strcmp(options[ret - 1], "\nUnmount SD") == 0){
if (sd_mounted){
sd_unmount();
sd_mounted = false;
}
else {
sd_mounted = sd_mount();
if (!sd_mounted) messagebox("\nSD INIT FAILED");
}
}
else if (strcmp(options[ret - 1], "[emmc:/] SYSTEM") == 0){
ret = messagebox(SYSTEM_WARNING_MESSAGE); // note: maybe add some sort of color system for messageboxes
if (ret == 0) sdexplorer(itemsinfolder, muhbits, "emmc:/");
}
else if (strcmp(options[ret - 1], "\nTools") == 0){
meme_clearscreen();
addchartoarray("Back", options, 0);
addchartoarray("\nPrint BISKEYS", options, 1);
addchartoarray("Dump firmware", options, 2);
ret = gfx_menulist(32, options, 3);
switch(ret){
case 2:
meme_clearscreen();
gfx_printf("\nBisKey 0:\n");
gfx_hexdump(0, bis_keys[0], 0x20 * sizeof(u8));
gfx_printf("\n\nBisKey 1:\n");
gfx_hexdump(0, bis_keys[1], 0x20 * sizeof(u8));
gfx_printf("\n\nBisKey 2 + 3:\n");
gfx_hexdump(0, bis_keys[2], 0x20 * sizeof(u8));
btn_wait();
break;
case 3:
ret = messagebox("\nThis will dump your firmware to your sd!\nThis might take a while\n\nVol-/+ to cancel\nPower to continue...");
if (ret == 0 && sd_mounted) sdexplorer(itemsinfolder, muhbits, "DumpFirmware");
break;
}
}
else {
meme_clearscreen();
addchartoarray("Back", options, 0);
addchartoarray("\nReboot to RCM", options, 1);
addchartoarray("Reboot normally", options, 2);
addchartoarray("Power off", options, 3);
ret = gfx_menulist(32, options, 4);
if (ret != 1) sd_unmount();
switch(ret){
case 2:
reboot_rcm();
case 3:
reboot_normal();
case 4:
power_off();
default:
break;
}
}
}
//if (sd_mounted){
if (sdinit){
sdexplorer(itemsinfolder, muhbits);
//write file and folder menu //write file and folder menu
//make clipboard and shit like that //make clipboard and shit like that
//figure out time from keys.c //figure out time from keys.c
//figure out how to reboot to payloads https://github.com/CTCaer/hekate/blob/101c8bc1d0813da10016be771a9919c9e8112277/bootloader/main.c#L266 //figure out how to reboot to payloads https://github.com/CTCaer/hekate/blob/101c8bc1d0813da10016be771a9919c9e8112277/bootloader/main.c#L266
gfx_printf("%k\n\nExited main loop, vol+ to reboot to rcm\nvol- to reboot normally\npower to power off\n", COLOR_GREEN); //gfx_printf("%k\n\nExited main loop, vol+ to reboot to rcm\nvol- to reboot normally\npower to power off\n", COLOR_GREEN);
} //}
else gfx_printf("%k%pSD INIT FAILED\n\nvol+ to reboot to rcm\nvol- to reboot normally\npower to power off", COLOR_RED, COLOR_DEFAULT); //else gfx_printf("%k%pSD INIT FAILED\n\nvol+ to reboot to rcm\nvol- to reboot normally\npower to power off", COLOR_RED, COLOR_DEFAULT);
utils_waitforpower(); //utils_waitforpower();
} }

View File

@@ -1,3 +1,6 @@
#pragma once #pragma once
void meme_main(bool sdinit); #define ABOUT_MESSAGE "\nCreator: Such Meme, Many Skill#2921\nCool people: Denn, shchmue\nTesters: PhazonicRidley, huhen\n\n\nProject based on Lockpick_RCM\n With additional code from Hekate"
#define SYSTEM_WARNING_MESSAGE "\nNOTICE!\n\nAbout to enter SYSTEM:/\nThis is a SYSTEM partition!\nMessing something up here \n will brick your switch!\n\nVol+/- to cancel\nPower to continue..."
void meme_main();

View File

@@ -1,4 +1,5 @@
#include <string.h> #include <string.h>
#include <stdio.h>
#include "../gfx/di.h" #include "../gfx/di.h"
#include "../gfx/gfx.h" #include "../gfx/gfx.h"
#include "../utils/btn.h" #include "../utils/btn.h"
@@ -7,27 +8,42 @@
#include "../libs/fatfs/ff.h" #include "../libs/fatfs/ff.h"
#include "../storage/sdmmc.h" #include "../storage/sdmmc.h"
#include "graphics.h" #include "graphics.h"
#include "external_utils.h"
int _openfilemenu(const char *path, char *clipboardpath){ int _openfilemenu(char *path, char *clipboardpath){
meme_clearscreen(); meme_clearscreen();
FILINFO fno; FILINFO fno;
f_stat(path, &fno); f_stat(path, &fno);
char *options[4]; char *options[6];
int res = 0; int res = 0;
int mres = -1; int mres = -1;
int ret = -1; int ret = -1;
int i = 4;
addchartoarray("Back", options, 0); addchartoarray("Back\n", options, 0);
addchartoarray("Copy to clipboard", options, 1); addchartoarray("Copy to clipboard", options, 1);
addchartoarray("Move to clipboard", options, 2); addchartoarray("Move to clipboard", options, 2);
addchartoarray("Delete file", options, 3); addchartoarray("Delete file\n", options, 3);
if (strstr(path, ".bin") != NULL){
addchartoarray("Launch payload", options, i);
i++;
}
if (strcmp(strstr(path, "emmc:/"), path) == 0){
addchartoarray("Dump to SD", options, i);
i++;
}
gfx_printf("%kPath: %s%k\n\n", COLOR_GREEN, path, COLOR_WHITE); gfx_printf("%kPath: %s%k\n\n", COLOR_GREEN, path, COLOR_WHITE);
int temp = (fno.fsize / 1024 / 1024);
gfx_printf("Size MB: %d", temp);
res = gfx_menulist(160, options, 4); char size[6];
return_readable_byte_amounts(fno.fsize, size);
gfx_printf("Size: %s", size);
res = gfx_menulist(160, options, i);
switch(res){ switch(res){
case 1:
break;
case 2: case 2:
ret = 0; ret = 0;
strcpy(clipboardpath, path); strcpy(clipboardpath, path);
@@ -41,46 +57,122 @@ int _openfilemenu(const char *path, char *clipboardpath){
if (mres == 0) f_unlink(path); if (mres == 0) f_unlink(path);
break; break;
default: default:
break; if (strcmp(options[res - 1], "Launch payload") == 0) launch_payload(path, 0);
else if (strcmp(options[res - 1], "Dump to SD") == 0) {
int res = 0;
res = dumptosd(path);
if (res == 1) messagebox("Copy Failed\nInput or Output is invalid");
}
} }
meme_clearscreen(); meme_clearscreen();
return ret; return ret;
} }
void sdexplorer(char *items[], unsigned int *muhbits){ int dumpfirmware(char *items[], unsigned int *muhbits){
DIR dir;
FILINFO fno;
char path[28] = "emmc:/Contents/registered";
char sdpath[28] = "sd:/tegraexplorer/firmware";
char tempnand[100] = "";
char tempsd[100] = "";
int ret = 0, i = 0, foldersize = 0;
meme_clearscreen();
gfx_printf("\nStarting copy of firmware\n\n");
f_mkdir("sd:/tegraexplorer");
f_mkdir("sd:/tegraexplorer/firmware");
if (f_opendir(&dir, path)) {
messagebox("Failed to open directory!");
return -1;
}
while (!f_readdir(&dir, &fno) && fno.fname[0]){
addchartoarray(fno.fname, items, foldersize);
mallocandaddfolderbit(muhbits, foldersize, fno.fattrib & AM_DIR);
foldersize++;
}
f_closedir(&dir);
for (i = 0; i < foldersize; i++){
if (muhbits[i] & AM_DIR){
sprintf(tempnand, "%s/%s/00", path, items[i]);
sprintf(tempsd, "%s/%s", sdpath, items[i]);
ret = copy(tempnand, tempsd, 0);
if (ret != 0) {
messagebox("Copy failed! (infolder)");
return 1;
}
f_closedir(&dir);
}
else {
sprintf(tempnand, "%s/%s", path, items[i]);
sprintf(tempsd, "%s/%s", sdpath, items[i]);
ret = copy(tempnand, tempsd, 0);
if (ret != 0) {
messagebox("Copy failed! (infile)");
return 1;
}
}
gfx_printf("Copied %d / %d nca files\r", i + 1, foldersize);
}
messagebox("\nDump completed!\n\nThe firmware dump is located \n in sd:/tegraexplorer/firmware");
return 0;
}
void sdexplorer(char *items[], unsigned int *muhbits, char *rootpath){
if (strcmp(rootpath, "DumpFirmware") == 0){
dumpfirmware(items, muhbits);
return;
}
int value = 1; int value = 1;
int copymode = -1; int copymode = -1;
int folderamount = 0; int folderamount = 0;
char path[255] = "sd:/"; char path[PATHSIZE] = "";
char clipboard[255] = ""; char clipboard[PATHSIZE + 1] = "";
strcpy(path, rootpath);
char app[20], rpp[20];
int temp = -1; int temp = -1;
strcpy(app, rootpath);
strcpy(rpp, app);
removepartpath(rpp, "rpp");
//static const u32 colors[8] = {COLOR_RED, COLOR_ORANGE, COLOR_YELLOW, COLOR_GREEN, COLOR_BLUE, COLOR_VIOLET, COLOR_DEFAULT, COLOR_WHITE}; //static const u32 colors[8] = {COLOR_RED, COLOR_ORANGE, COLOR_YELLOW, COLOR_GREEN, COLOR_BLUE, COLOR_VIOLET, COLOR_DEFAULT, COLOR_WHITE};
while(1){ while(1){
gfx_clear_grey(0x1B); gfx_clear_grey(0x1B);
gfx_con_setpos(0, 0); gfx_con_setpos(0, 0);
gfx_box(0, 0, 719, 15, COLOR_WHITE); gfx_box(0, 0, 719, 15, COLOR_WHITE);
folderamount = readfolder(items, muhbits, path); folderamount = readfolder(items, muhbits, path);
gfx_printf("%k%pTegraExplorer, by SuchMemeManySkill %d\n%k%p", COLOR_DEFAULT, COLOR_WHITE, folderamount - 2, COLOR_WHITE, COLOR_DEFAULT); if (folderamount == -1){
messagebox("\nInvalid path\n\nReturning to main menu");
break;
}
gfx_printf("%k%pTegraExplorer - %s", COLOR_DEFAULT, COLOR_WHITE, app);
gfx_con_setpos(39 * 16, 0);
gfx_printf("%d\n%k%p", folderamount - 2, COLOR_WHITE, COLOR_DEFAULT);
value = fileexplorergui(items, muhbits, path, folderamount); value = fileexplorergui(items, muhbits, path, folderamount);
if (value == 1) { if (value == 1) {
if (strcmp("sd:/", path) == 0) break; if (strcmp(app, path) == 0) break;
else removepartpath(path); else removepartpath(path, rpp);
} }
else if (value == 2) { else if (value == 2) {
if (copymode != -1){ if (copymode != -1){
copywithpath(clipboard, path, copymode); copywithpath(clipboard, path, copymode, app);
copymode = -1; copymode = -1;
} }
else messagebox("\nThe Clipboard is empty!");
} }
else { else {
if(muhbits[value - 1] & OPTION1) addpartpath(path, items[value - 1]); if(muhbits[value - 1] & OPTION1) addpartpath(path, items[value - 1], app);
else { else {
addpartpath(path, items[value - 1]); addpartpath(path, items[value - 1], app);
temp = _openfilemenu(path, clipboard); temp = _openfilemenu(path, clipboard);
if (temp != -1) copymode = temp; if (temp != -1) copymode = temp;
removepartpath(path); removepartpath(path, rpp);
} }
} }
} }

View File

@@ -1,3 +1,5 @@
#pragma once #pragma once
void sdexplorer(char *items[], unsigned int *muhbits); void sdexplorer(char *items[], unsigned int *muhbits, char *rootpath);
int dumpfirmware(char *items[], unsigned int *muhbits);
void wtf(char *items[], unsigned int *muhbits);

View File

@@ -8,6 +8,8 @@
#include "utils.h" #include "utils.h"
#include "../libs/fatfs/ff.h" #include "../libs/fatfs/ff.h"
#include "../storage/sdmmc.h" #include "../storage/sdmmc.h"
#include "graphics.h"
#include "external_utils.h"
void utils_gfx_init(){ void utils_gfx_init(){
display_backlight_brightness(100, 1000); display_backlight_brightness(100, 1000);
@@ -15,26 +17,72 @@ void utils_gfx_init(){
gfx_con_setpos(0, 0); gfx_con_setpos(0, 0);
} }
void removepartpath(char *path){ void removepartpath(char *path, char *root){
char *ret; char *ret;
char temproot[20];
ret = strrchr(path, '/'); ret = strrchr(path, '/');
memset(ret, '\0', 1); memset(ret, '\0', 1);
if (strcmp(path, "sd:") == 0) strcpy(path, "sd:/"); sprintf(temproot, "%s%s", root, "/");
if (strcmp(path, root) == 0) strcpy(path, temproot);
} }
void addpartpath(char *path, char *add){ int dumptosd(const char *path){
if (strcmp(path, "sd:/") != 0) strcat(path, "/"); f_mkdir("sd:/tegraexplorer");
f_mkdir("sd:/tegraexplorer/nanddump");
FILINFO fno;
int res = 0;
f_stat(path, &fno);
char pathname[PATHSIZE];
char foldername[75];
strcpy(pathname, path);
removepartpath(pathname, "emmc:");
strcpy(foldername, strrchr(pathname, '/'));
if (strcmp(foldername, "/") == 0) strcpy(foldername, "/root");
sprintf(pathname, "%s%s", "sd:/tegraexplorer/nanddump", foldername);
f_mkdir(pathname);
sprintf(pathname, "%s%s%s%s", "sd:/tegraexplorer/nanddump", foldername, "/", fno.fname);
res = copy(path, pathname, 1);
return res;
}
void addpartpath(char *path, char *add, char *root){
if (strcmp(path, root) != 0) strcat(path, "/");
strcat(path, add); strcat(path, add);
} }
void utils_waitforpower(){ void return_readable_byte_amounts(unsigned long int size, char *in){
u32 btn = btn_wait(); char type[3];
if (btn & BTN_VOL_UP) unsigned long int sizetemp = size;
reboot_rcm(); int muhbytes = 0;
else if (btn & BTN_VOL_DOWN) while(sizetemp > 1024){
reboot_normal(); muhbytes++;
else sizetemp = sizetemp / 1024;
power_off(); }
switch(muhbytes){
case 0:
strcpy(type, "B");
break;
case 1:
strcpy(type, "KB");
break;
case 2:
strcpy(type, "MB");
break;
case 3:
strcpy(type, "GB");
break;
default:
strcpy(type, "GB");
break;
}
sprintf(in, "%d%s", sizetemp, type);
}
int getfilesize(const char *path){
FILINFO fno;
f_stat(path, &fno);
return fno.fsize;
} }
void addchartoarray(char *add, char *items[], int spot){ void addchartoarray(char *add, char *items[], int spot){
@@ -43,7 +91,7 @@ void addchartoarray(char *add, char *items[], int spot){
strlcpy(items[spot], add, size); strlcpy(items[spot], add, size);
} }
void _mallocandaddfolderbit(unsigned int *muhbits, int spot, bool value){ void mallocandaddfolderbit(unsigned int *muhbits, int spot, bool value){
muhbits[spot] = (unsigned int) malloc (sizeof(int)); muhbits[spot] = (unsigned int) malloc (sizeof(int));
if (value) muhbits[spot] |= (OPTION1); if (value) muhbits[spot] |= (OPTION1);
//ff.h line 368 //ff.h line 368
@@ -55,17 +103,18 @@ int readfolder(char *items[], unsigned int *muhbits, const char *path){
int i = 2; int i = 2;
addchartoarray("Current folder -> One folder up", items, 0); addchartoarray("Current folder -> One folder up", items, 0);
addchartoarray("Clipboard -> Current folder", items, 1); addchartoarray("Clipboard -> Current folder", items, 1);
_mallocandaddfolderbit(muhbits, 0, true); mallocandaddfolderbit(muhbits, 0, true);
_mallocandaddfolderbit(muhbits, 1, true); mallocandaddfolderbit(muhbits, 1, true);
if (f_opendir(&dir, path)) { if (f_opendir(&dir, path)) {
gfx_printf("\nFailed to open %s", path); gfx_printf("\nFailed to open %s", path);
return 0; return -1;
} }
else { else {
while (!f_readdir(&dir, &fno) && fno.fname[0]){ while (!f_readdir(&dir, &fno) && fno.fname[0]){
addchartoarray(fno.fname, items, i); addchartoarray(fno.fname, items, i);
_mallocandaddfolderbit(muhbits, i, fno.fattrib & AM_DIR); mallocandaddfolderbit(muhbits, i, fno.fattrib & AM_DIR);
i++; i++;
} }
} }
@@ -73,33 +122,52 @@ int readfolder(char *items[], unsigned int *muhbits, const char *path){
return i; return i;
} }
int copy(const char *src, const char *dst){ int copy(const char *src, const char *dst, int print){
FIL in; FIL in;
FIL out; FIL out;
unsigned int res = 0;
if (f_open(&in, src, FA_READ) != FR_OK){ char temp[100];
if (strcmp(src, dst) == 0){
//in and out are the same, aborting!
return 2;
}
res = f_open(&in, src, FA_READ | FA_OPEN_EXISTING);
if (res != FR_OK){
//something has gone wrong //something has gone wrong
return 0; //sprintf(temp, "%s %d", src, res);
//messagebox(temp);
return 1;
} }
if (f_open(&out, dst, FA_CREATE_ALWAYS | FA_WRITE) != FR_OK){ if (f_open(&out, dst, FA_CREATE_ALWAYS | FA_WRITE) != FR_OK){
//something has gone wrong //something has gone wrong
return 0; return 1;
} }
int BUFFSIZ = 32768; int BUFFSIZ = 32768;
u64 size = f_size(&in); u64 size = f_size(&in);
unsigned long totalsize = size, kbwritten = 0;
void *buff = malloc(BUFFSIZ); void *buff = malloc(BUFFSIZ);
int kbwritten = 0; int mbwritten = 0, percentage = 0;
gfx_printf("%d\n", size); bool abort = false;
if (print == 1) {
meme_clearscreen();
gfx_printf("press VOL- to abort the file transfer!\n\n");
}
while(size > BUFFSIZ){ while(size > BUFFSIZ){
int res1, res2; int res1, res2;
res1 = f_read(&in, buff, BUFFSIZ, NULL); res1 = f_read(&in, buff, BUFFSIZ, NULL);
res2 = f_write(&out, buff, BUFFSIZ, NULL); res2 = f_write(&out, buff, BUFFSIZ, NULL);
kbwritten = kbwritten + BUFFSIZ; kbwritten = kbwritten + (BUFFSIZ / 1024);
mbwritten = kbwritten / 1024;
percentage = (mbwritten * 100) / ((totalsize / 1024) / 1024);
gfx_printf("Written %d\r", kbwritten);
size = size - BUFFSIZ; size = size - BUFFSIZ;
if (print == 1){
gfx_printf("Written %dMB [%k%d%k%%]\r", mbwritten, COLOR_GREEN, percentage, COLOR_WHITE);
if (btn_read() & BTN_VOL_DOWN) size = 0, abort = true;
}
} }
if(size != 0){ if(size != 0){
@@ -110,20 +178,24 @@ int copy(const char *src, const char *dst){
f_close(&in); f_close(&in);
f_close(&out); f_close(&out);
if(abort){
f_unlink(dst);
}
free(buff); free(buff);
return 1; return 0;
} }
int copywithpath(const char *src, const char *dstpath, int mode){ int copywithpath(const char *src, const char *dstpath, int mode, char *app){
FILINFO fno; FILINFO fno;
f_stat(src, &fno); f_stat(src, &fno);
char dst[255]; char dst[PATHSIZE];
strcpy(dst, dstpath); strcpy(dst, dstpath);
if (strcmp(dstpath, "sd:/") != 0) strcat(dst, "/"); if (strcmp(dstpath, app) != 0) strcat(dst, "/");
strcat(dst, fno.fname); strcat(dst, fno.fname);
int ret = -1; int ret = -1;
if (mode == 0) ret = copy(src, dst); if (mode == 0) ret = copy(src, dst, 1);
if (mode == 1) f_rename(src, dst); if (mode == 1) f_rename(src, dst);
return ret; return ret;
} }

View File

@@ -5,11 +5,16 @@
#define OPTION3 (1 << 2) #define OPTION3 (1 << 2)
#define OPTION4 (1 << 3) #define OPTION4 (1 << 3)
#define PATHSIZE 512
void utils_gfx_init(); void utils_gfx_init();
void utils_waitforpower(); void removepartpath(char *path, char *root);
void removepartpath(char *path); void addpartpath(char *path, char *add, char *root);
void addpartpath(char *path, char *add);
int readfolder(char *items[], unsigned int *muhbits, const char *path); int readfolder(char *items[], unsigned int *muhbits, const char *path);
int copy(const char *src, const char *dst); int copy(const char *src, const char *dst, int print);
void addchartoarray(char *add, char *items[], int spot); void addchartoarray(char *add, char *items[], int spot);
int copywithpath(const char *src, const char *dstpath, int mode); int copywithpath(const char *src, const char *dstpath, int mode, char *app);
void return_readable_byte_amounts(unsigned long int size, char *in);
int getfilesize(const char *path);
int dumptosd(const char *path);
void mallocandaddfolderbit(unsigned int *muhbits, int spot, bool value);