Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c5b049453 | ||
|
|
0c4be1f917 | ||
|
|
d4eb56a35f | ||
|
|
9281e4bbbc | ||
|
|
d000f86c89 | ||
|
|
7dc9320b41 | ||
|
|
f3808edb40 | ||
|
|
7a35d2b00c | ||
|
|
a094ac4496 | ||
|
|
ada4fd2c7f | ||
|
|
819d08415d | ||
|
|
45eb25270f | ||
|
|
5b15e4cdf7 |
20
README.md
20
README.md
@@ -1,5 +1,25 @@
|
||||
# TegraExplorer
|
||||
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
|
||||
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;
|
||||
if (gfx_con.x >= gfx_ctxt.width - 16) {
|
||||
if (gfx_con.x >= gfx_ctxt.width - 8) {
|
||||
gfx_con.x = 0;
|
||||
gfx_con.y += 16;
|
||||
}
|
||||
|
||||
@@ -191,7 +191,7 @@
|
||||
|
||||
|
||||
#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,
|
||||
/ 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
|
||||
|
||||
@@ -31,8 +31,6 @@
|
||||
#include "meme/main.h"
|
||||
#include "meme/utils.h"
|
||||
|
||||
#include "keys/keys.h"
|
||||
|
||||
sdmmc_t sd_sdmmc;
|
||||
sdmmc_storage_t sd_storage;
|
||||
__attribute__ ((aligned (16))) FATFS sd_fs;
|
||||
@@ -153,7 +151,6 @@ extern void pivot_stack(u32 stack_top);
|
||||
|
||||
void ipl_main()
|
||||
{
|
||||
bool sd_mounted = false;
|
||||
config_hw();
|
||||
pivot_stack(IPL_STACK_TOP);
|
||||
heap_init(IPL_HEAP_START);
|
||||
@@ -164,8 +161,6 @@ void ipl_main()
|
||||
gfx_con_init();
|
||||
display_backlight_pwm_init();
|
||||
|
||||
|
||||
sd_mounted = sd_mount();
|
||||
meme_main(sd_mounted);
|
||||
meme_main();
|
||||
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;
|
||||
memset(out + strlength, '\0', 1);
|
||||
int ret = copynumb - strlength;
|
||||
return ret;
|
||||
return ret + 4;
|
||||
}
|
||||
|
||||
int messagebox(char *message){
|
||||
int ret = -1;
|
||||
meme_clearscreen();
|
||||
gfx_printf("%s", message);
|
||||
msleep(100);
|
||||
u8 res = btn_wait();
|
||||
if (res & BTN_POWER) ret = 0;
|
||||
else ret = 1;
|
||||
@@ -53,10 +54,10 @@ void meme_clearscreen(){
|
||||
gfx_clear_grey(0x1B);
|
||||
gfx_con_setpos(0, 0);
|
||||
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];
|
||||
int i = 0;
|
||||
int ret = 0;
|
||||
@@ -74,8 +75,11 @@ void _printwithhighlight(int offset, int folderamount, char *items[], int highli
|
||||
}
|
||||
|
||||
gfx_con.x = 720 - (16 * 6);
|
||||
if (muhbits[i + offset] & OPTION1) gfx_printf("DIR");
|
||||
else gfx_printf("FILE");
|
||||
if (!(muhbits[i + offset] & OPTION1)) { //should change later
|
||||
char temp[6];
|
||||
return_readable_byte_amounts(filesizes[i + offset], temp);
|
||||
gfx_printf("%s", temp);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
@@ -86,12 +90,26 @@ int fileexplorergui(char *items[], unsigned int *muhbits, const char path[], int
|
||||
int sleepvalue = 300;
|
||||
int offset = 0;
|
||||
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);
|
||||
gfx_con_setpos(0, 16);
|
||||
gfx_printf("%k%s\n%k", COLOR_GREEN, temp, COLOR_WHITE);
|
||||
while(1){
|
||||
if (change){
|
||||
_printwithhighlight(offset, folderamount, items, select, muhbits);
|
||||
_printwithhighlight(offset, folderamount, items, select, muhbits, filesizes);
|
||||
change = false;
|
||||
msleep(sleepvalue);
|
||||
}
|
||||
@@ -121,5 +139,6 @@ int fileexplorergui(char *items[], unsigned int *muhbits, const char path[], int
|
||||
if (sleepvalue < 30) sleepvalue = 30;
|
||||
}
|
||||
int ret = select + offset;
|
||||
free(filesizes);
|
||||
return ret;
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "../gfx/di.h"
|
||||
#include "../gfx/gfx.h"
|
||||
#include "../utils/btn.h"
|
||||
@@ -6,36 +7,125 @@
|
||||
#include "main.h"
|
||||
#include "mainfunctions.h"
|
||||
#include "../libs/fatfs/ff.h"
|
||||
#include "../storage/sdmmc.h"
|
||||
#include "../utils/util.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();
|
||||
//static const u32 colors[7] = {COLOR_RED, COLOR_ORANGE, COLOR_YELLOW, COLOR_GREEN, COLOR_BLUE, COLOR_VIOLET, COLOR_DEFAULT};
|
||||
//gfx_printf("%k%pTegraExplorer, made by SuchMemeManySkill \n%k%p", colors[6], colors[3], colors[3], colors[6]);
|
||||
//dump_keys();
|
||||
|
||||
/*
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
|
||||
sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4);
|
||||
sdmmc_storage_set_mmc_partition(&storage, 1);
|
||||
*/
|
||||
//f_rename("sd:/yeet.txt", "sd:/yote.txt");
|
||||
sdmmc_storage_set_mmc_partition(&storage, 1); */
|
||||
|
||||
int firmver = -1;
|
||||
firmver = dump_biskeys(bis_keys); // add succeed check
|
||||
|
||||
char *options[6];
|
||||
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){
|
||||
|
||||
char *itemsinfolder[500];
|
||||
unsigned int muhbits[500];
|
||||
|
||||
if (sdinit){
|
||||
sdexplorer(itemsinfolder, muhbits);
|
||||
|
||||
//write file and folder menu
|
||||
//make clipboard and shit like that
|
||||
//figure out time from keys.c
|
||||
//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);
|
||||
}
|
||||
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);
|
||||
//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);
|
||||
|
||||
utils_waitforpower();
|
||||
//utils_waitforpower();
|
||||
}
|
||||
@@ -1,3 +1,6 @@
|
||||
#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 <stdio.h>
|
||||
#include "../gfx/di.h"
|
||||
#include "../gfx/gfx.h"
|
||||
#include "../utils/btn.h"
|
||||
@@ -7,27 +8,42 @@
|
||||
#include "../libs/fatfs/ff.h"
|
||||
#include "../storage/sdmmc.h"
|
||||
#include "graphics.h"
|
||||
#include "external_utils.h"
|
||||
|
||||
int _openfilemenu(const char *path, char *clipboardpath){
|
||||
int _openfilemenu(char *path, char *clipboardpath){
|
||||
meme_clearscreen();
|
||||
FILINFO fno;
|
||||
f_stat(path, &fno);
|
||||
char *options[4];
|
||||
char *options[6];
|
||||
int res = 0;
|
||||
int mres = -1;
|
||||
int ret = -1;
|
||||
int i = 4;
|
||||
|
||||
addchartoarray("Back", options, 0);
|
||||
addchartoarray("Back\n", options, 0);
|
||||
addchartoarray("Copy to clipboard", options, 1);
|
||||
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);
|
||||
int temp = (fno.fsize / 1024 / 1024);
|
||||
gfx_printf("Size MB: %d", temp);
|
||||
|
||||
char size[6];
|
||||
return_readable_byte_amounts(fno.fsize, size);
|
||||
|
||||
gfx_printf("Size: %s", size);
|
||||
|
||||
res = gfx_menulist(160, options, 4);
|
||||
res = gfx_menulist(160, options, i);
|
||||
switch(res){
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
ret = 0;
|
||||
strcpy(clipboardpath, path);
|
||||
@@ -41,46 +57,122 @@ int _openfilemenu(const char *path, char *clipboardpath){
|
||||
if (mres == 0) f_unlink(path);
|
||||
break;
|
||||
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();
|
||||
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 copymode = -1;
|
||||
int folderamount = 0;
|
||||
char path[255] = "sd:/";
|
||||
char clipboard[255] = "";
|
||||
char path[PATHSIZE] = "";
|
||||
char clipboard[PATHSIZE + 1] = "";
|
||||
strcpy(path, rootpath);
|
||||
char app[20], rpp[20];
|
||||
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};
|
||||
|
||||
while(1){
|
||||
gfx_clear_grey(0x1B);
|
||||
gfx_con_setpos(0, 0);
|
||||
gfx_box(0, 0, 719, 15, COLOR_WHITE);
|
||||
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);
|
||||
|
||||
if (value == 1) {
|
||||
if (strcmp("sd:/", path) == 0) break;
|
||||
else removepartpath(path);
|
||||
if (strcmp(app, path) == 0) break;
|
||||
else removepartpath(path, rpp);
|
||||
}
|
||||
else if (value == 2) {
|
||||
if (copymode != -1){
|
||||
copywithpath(clipboard, path, copymode);
|
||||
copywithpath(clipboard, path, copymode, app);
|
||||
copymode = -1;
|
||||
}
|
||||
else messagebox("\nThe Clipboard is empty!");
|
||||
}
|
||||
else {
|
||||
if(muhbits[value - 1] & OPTION1) addpartpath(path, items[value - 1]);
|
||||
if(muhbits[value - 1] & OPTION1) addpartpath(path, items[value - 1], app);
|
||||
else {
|
||||
addpartpath(path, items[value - 1]);
|
||||
addpartpath(path, items[value - 1], app);
|
||||
temp = _openfilemenu(path, clipboard);
|
||||
if (temp != -1) copymode = temp;
|
||||
removepartpath(path);
|
||||
removepartpath(path, rpp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#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 "../libs/fatfs/ff.h"
|
||||
#include "../storage/sdmmc.h"
|
||||
#include "graphics.h"
|
||||
#include "external_utils.h"
|
||||
|
||||
void utils_gfx_init(){
|
||||
display_backlight_brightness(100, 1000);
|
||||
@@ -15,26 +17,72 @@ void utils_gfx_init(){
|
||||
gfx_con_setpos(0, 0);
|
||||
}
|
||||
|
||||
void removepartpath(char *path){
|
||||
void removepartpath(char *path, char *root){
|
||||
char *ret;
|
||||
char temproot[20];
|
||||
ret = strrchr(path, '/');
|
||||
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){
|
||||
if (strcmp(path, "sd:/") != 0) strcat(path, "/");
|
||||
int dumptosd(const char *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);
|
||||
}
|
||||
|
||||
void utils_waitforpower(){
|
||||
u32 btn = btn_wait();
|
||||
if (btn & BTN_VOL_UP)
|
||||
reboot_rcm();
|
||||
else if (btn & BTN_VOL_DOWN)
|
||||
reboot_normal();
|
||||
else
|
||||
power_off();
|
||||
void return_readable_byte_amounts(unsigned long int size, char *in){
|
||||
char type[3];
|
||||
unsigned long int sizetemp = size;
|
||||
int muhbytes = 0;
|
||||
while(sizetemp > 1024){
|
||||
muhbytes++;
|
||||
sizetemp = sizetemp / 1024;
|
||||
}
|
||||
|
||||
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){
|
||||
@@ -43,7 +91,7 @@ void addchartoarray(char *add, char *items[], int spot){
|
||||
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));
|
||||
if (value) muhbits[spot] |= (OPTION1);
|
||||
//ff.h line 368
|
||||
@@ -55,17 +103,18 @@ int readfolder(char *items[], unsigned int *muhbits, const char *path){
|
||||
int i = 2;
|
||||
addchartoarray("Current folder -> One folder up", items, 0);
|
||||
addchartoarray("Clipboard -> Current folder", items, 1);
|
||||
_mallocandaddfolderbit(muhbits, 0, true);
|
||||
_mallocandaddfolderbit(muhbits, 1, true);
|
||||
mallocandaddfolderbit(muhbits, 0, true);
|
||||
mallocandaddfolderbit(muhbits, 1, true);
|
||||
|
||||
|
||||
if (f_opendir(&dir, path)) {
|
||||
gfx_printf("\nFailed to open %s", path);
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
while (!f_readdir(&dir, &fno) && fno.fname[0]){
|
||||
addchartoarray(fno.fname, items, i);
|
||||
_mallocandaddfolderbit(muhbits, i, fno.fattrib & AM_DIR);
|
||||
mallocandaddfolderbit(muhbits, i, fno.fattrib & AM_DIR);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
@@ -73,33 +122,52 @@ int readfolder(char *items[], unsigned int *muhbits, const char *path){
|
||||
return i;
|
||||
}
|
||||
|
||||
int copy(const char *src, const char *dst){
|
||||
int copy(const char *src, const char *dst, int print){
|
||||
FIL in;
|
||||
FIL out;
|
||||
|
||||
if (f_open(&in, src, FA_READ) != FR_OK){
|
||||
unsigned int res = 0;
|
||||
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
|
||||
return 0;
|
||||
//sprintf(temp, "%s %d", src, res);
|
||||
//messagebox(temp);
|
||||
|
||||
return 1;
|
||||
}
|
||||
if (f_open(&out, dst, FA_CREATE_ALWAYS | FA_WRITE) != FR_OK){
|
||||
//something has gone wrong
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BUFFSIZ = 32768;
|
||||
u64 size = f_size(&in);
|
||||
unsigned long totalsize = size, kbwritten = 0;
|
||||
void *buff = malloc(BUFFSIZ);
|
||||
int kbwritten = 0;
|
||||
gfx_printf("%d\n", size);
|
||||
int mbwritten = 0, percentage = 0;
|
||||
bool abort = false;
|
||||
if (print == 1) {
|
||||
meme_clearscreen();
|
||||
gfx_printf("press VOL- to abort the file transfer!\n\n");
|
||||
}
|
||||
while(size > BUFFSIZ){
|
||||
int res1, res2;
|
||||
res1 = f_read(&in, 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;
|
||||
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){
|
||||
@@ -110,20 +178,24 @@ int copy(const char *src, const char *dst){
|
||||
f_close(&in);
|
||||
f_close(&out);
|
||||
|
||||
if(abort){
|
||||
f_unlink(dst);
|
||||
}
|
||||
|
||||
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;
|
||||
f_stat(src, &fno);
|
||||
char dst[255];
|
||||
char dst[PATHSIZE];
|
||||
strcpy(dst, dstpath);
|
||||
if (strcmp(dstpath, "sd:/") != 0) strcat(dst, "/");
|
||||
if (strcmp(dstpath, app) != 0) strcat(dst, "/");
|
||||
strcat(dst, fno.fname);
|
||||
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);
|
||||
return ret;
|
||||
}
|
||||
@@ -5,11 +5,16 @@
|
||||
#define OPTION3 (1 << 2)
|
||||
#define OPTION4 (1 << 3)
|
||||
|
||||
#define PATHSIZE 512
|
||||
|
||||
void utils_gfx_init();
|
||||
void utils_waitforpower();
|
||||
void removepartpath(char *path);
|
||||
void addpartpath(char *path, char *add);
|
||||
void removepartpath(char *path, char *root);
|
||||
void addpartpath(char *path, char *add, char *root);
|
||||
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);
|
||||
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