Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e8ddc9cf2f | ||
|
|
1c5b049453 | ||
|
|
0c4be1f917 | ||
|
|
d4eb56a35f | ||
|
|
9281e4bbbc | ||
|
|
d000f86c89 | ||
|
|
7dc9320b41 | ||
|
|
f3808edb40 | ||
|
|
7a35d2b00c | ||
|
|
a094ac4496 | ||
|
|
ada4fd2c7f | ||
|
|
819d08415d | ||
|
|
45eb25270f | ||
|
|
5b15e4cdf7 |
20
README.md
20
README.md
@@ -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
|
||||||
|

|
||||||
|
|
||||||
# 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
BIN
example.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
232
source/meme/external_utils.c
Normal file
232
source/meme/external_utils.c
Normal 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);
|
||||||
|
}
|
||||||
53
source/meme/external_utils.h
Normal file
53
source/meme/external_utils.h
Normal 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}
|
||||||
|
};
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -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();
|
||||||
}
|
}
|
||||||
@@ -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();
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
Reference in New Issue
Block a user