mirror of
https://github.com/suchmememanyskill/TegraExplorer.git
synced 2025-01-10 03:37:33 -03:00
Add fw dumping
- also fatfs is stupid - also close files properly on a failed copy - also check for errors during folder readouts - also make sure holding vol- doesn't dump the keys anyway
This commit is contained in:
parent
859ad2cc4c
commit
513bd804b1
18 changed files with 222 additions and 29 deletions
|
@ -4048,7 +4048,8 @@ FRESULT f_write (
|
||||||
}
|
}
|
||||||
if (clst == 0) {
|
if (clst == 0) {
|
||||||
EFSPRINTF("DSKFULL");
|
EFSPRINTF("DSKFULL");
|
||||||
break; /* Could not allocate a new cluster (disk full) */
|
fp->flag |= FA_MODIFIED;
|
||||||
|
ABORT(fs, FR_DISK_ERR); /* Could not allocate a new cluster (disk full) */
|
||||||
}
|
}
|
||||||
if (clst == 1) {
|
if (clst == 1) {
|
||||||
EFSPRINTF("CCHK");
|
EFSPRINTF("CCHK");
|
||||||
|
|
|
@ -13,6 +13,7 @@ ErrCode_t FileCopy(const char *locin, const char *locout, u8 options){
|
||||||
u64 sizeRemaining, toCopy;
|
u64 sizeRemaining, toCopy;
|
||||||
u8 *buff;
|
u8 *buff;
|
||||||
u32 x, y;
|
u32 x, y;
|
||||||
|
ErrCode_t err = newErrCode(0);
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
|
||||||
gfx_con_getpos(&x, &y);
|
gfx_con_getpos(&x, &y);
|
||||||
|
@ -47,11 +48,13 @@ ErrCode_t FileCopy(const char *locin, const char *locout, u8 options){
|
||||||
toCopy = MIN(sizeRemaining, TConf.FSBuffSize);
|
toCopy = MIN(sizeRemaining, TConf.FSBuffSize);
|
||||||
|
|
||||||
if ((res = f_read(&in, buff, toCopy, NULL))){
|
if ((res = f_read(&in, buff, toCopy, NULL))){
|
||||||
return newErrCode(res);
|
err = newErrCode(res);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((res = f_write(&out, buff, toCopy, NULL))){
|
if ((res = f_write(&out, buff, toCopy, NULL))){
|
||||||
return newErrCode(res);
|
err = newErrCode(res);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
sizeRemaining -= toCopy;
|
sizeRemaining -= toCopy;
|
||||||
|
@ -74,5 +77,5 @@ ErrCode_t FileCopy(const char *locin, const char *locout, u8 options){
|
||||||
f_chmod(locout, in_info.fattrib, 0x3A);
|
f_chmod(locout, in_info.fattrib, 0x3A);
|
||||||
|
|
||||||
//f_stat(locin, &in_info); //somehow stops fatfs from being weird
|
//f_stat(locin, &in_info); //somehow stops fatfs from being weird
|
||||||
return newErrCode(0);
|
return err;
|
||||||
}
|
}
|
|
@ -42,4 +42,13 @@ char *GetFileAttribs(FSEntry_t entry){
|
||||||
char *ret = CpyStr("RHSVDA");
|
char *ret = CpyStr("RHSVDA");
|
||||||
MaskIn(ret, entry.optionUnion, '-');
|
MaskIn(ret, entry.optionUnion, '-');
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FileExists(char* path){
|
||||||
|
FRESULT fr;
|
||||||
|
FILINFO fno;
|
||||||
|
|
||||||
|
fr = f_stat(path, &fno);
|
||||||
|
|
||||||
|
return !(fr & FR_NO_FILE);
|
||||||
|
}
|
||||||
|
|
|
@ -5,4 +5,5 @@
|
||||||
u64 GetFileSize(char *path);
|
u64 GetFileSize(char *path);
|
||||||
char *EscapeFolder(const char *current);
|
char *EscapeFolder(const char *current);
|
||||||
char *CombinePaths(const char *current, const char *add);
|
char *CombinePaths(const char *current, const char *add);
|
||||||
char *GetFileAttribs(FSEntry_t entry);
|
char *GetFileAttribs(FSEntry_t entry);
|
||||||
|
bool FileExists(char* path);
|
|
@ -30,13 +30,7 @@ MenuEntry_t MakeMenuOutFSEntry(FSEntry_t entry){
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clearFileVector(Vector_t *v){
|
|
||||||
vecPDefArray(FSEntry_t*, entries, v);
|
|
||||||
for (int i = 0; i < v->count; i++)
|
|
||||||
free(entries[i].name);
|
|
||||||
|
|
||||||
free(v->data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileExplorer(char *path){
|
void FileExplorer(char *path){
|
||||||
char *storedPath = CpyStr(path);
|
char *storedPath = CpyStr(path);
|
||||||
|
@ -48,8 +42,15 @@ void FileExplorer(char *path){
|
||||||
|
|
||||||
gfx_clearscreen();
|
gfx_clearscreen();
|
||||||
gfx_printf("Loading...\r");
|
gfx_printf("Loading...\r");
|
||||||
//gfx_printf(" ");
|
|
||||||
Vector_t fileVec = ReadFolder(storedPath);
|
int readRes = 0;
|
||||||
|
Vector_t fileVec = ReadFolder(storedPath, &readRes);
|
||||||
|
if (readRes){
|
||||||
|
clearFileVector(&fileVec);
|
||||||
|
DrawError(newErrCode(readRes));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
vecDefArray(FSEntry_t*, fsEntries, fileVec);
|
vecDefArray(FSEntry_t*, fsEntries, fileVec);
|
||||||
|
|
||||||
topEntries[0].name = storedPath;
|
topEntries[0].name = storedPath;
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "../../hid/hid.h"
|
#include "../../hid/hid.h"
|
||||||
#include <libs/fatfs/ff.h>
|
#include <libs/fatfs/ff.h>
|
||||||
#include "../../utils/utils.h"
|
#include "../../utils/utils.h"
|
||||||
|
#include "../../keys/nca.h"
|
||||||
|
|
||||||
MenuEntry_t FileMenuEntries[] = {
|
MenuEntry_t FileMenuEntries[] = {
|
||||||
// Still have to think up the options
|
// Still have to think up the options
|
||||||
|
@ -50,17 +51,12 @@ void MoveClipboard(char *path, FSEntry_t entry){
|
||||||
free(thing);
|
free(thing);
|
||||||
}
|
}
|
||||||
|
|
||||||
MenuEntry_t DeleteEntries[] = {
|
|
||||||
{.optionUnion = COLORTORGB(COLOR_YELLOW), .name = "No"},
|
|
||||||
{.R = 255, .name = "Yes"}
|
|
||||||
};
|
|
||||||
|
|
||||||
void DeleteFile(char *path, FSEntry_t entry){
|
void DeleteFile(char *path, FSEntry_t entry){
|
||||||
gfx_con_setpos(384 + 16, 200 + 16 + 10 * 16);
|
gfx_con_setpos(384 + 16, 200 + 16 + 10 * 16);
|
||||||
SETCOLOR(COLOR_RED, COLOR_DARKGREY);
|
SETCOLOR(COLOR_RED, COLOR_DARKGREY);
|
||||||
gfx_printf("Are you sure? ");
|
gfx_printf("Are you sure? ");
|
||||||
|
|
||||||
if (!MakeHorizontalMenu(DeleteEntries, 2, 3, COLOR_DARKGREY))
|
if (!MakeYesNoHorzMenu(3, COLOR_DARKGREY))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
char *thing = CombinePaths(path, entry.name);
|
char *thing = CombinePaths(path, entry.name);
|
||||||
|
|
|
@ -1,19 +1,27 @@
|
||||||
#include "folderReader.h"
|
#include "folderReader.h"
|
||||||
#include <libs/fatfs/ff.h>
|
#include <libs/fatfs/ff.h>
|
||||||
#include "../../utils/utils.h"
|
#include "../../utils/utils.h"
|
||||||
|
#include <mem/heap.h>
|
||||||
|
|
||||||
Vector_t /* of type FSEntry_t */ ReadFolder(char *path){
|
void clearFileVector(Vector_t *v){
|
||||||
|
vecPDefArray(FSEntry_t*, entries, v);
|
||||||
|
for (int i = 0; i < v->count; i++)
|
||||||
|
free(entries[i].name);
|
||||||
|
|
||||||
|
free(v->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector_t /* of type FSEntry_t */ ReadFolder(char *path, int *res){
|
||||||
Vector_t out = newVec(sizeof(FSEntry_t), 16); // we may want to prealloc with the same size as the folder
|
Vector_t out = newVec(sizeof(FSEntry_t), 16); // we may want to prealloc with the same size as the folder
|
||||||
DIR dir;
|
DIR dir;
|
||||||
FILINFO fno;
|
FILINFO fno;
|
||||||
int res;
|
|
||||||
|
|
||||||
if ((res = f_opendir(&dir, path))){
|
if ((*res = f_opendir(&dir, path))){
|
||||||
// Err!
|
// Err!
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!f_readdir(&dir, &fno) && fno.fname[0]) {
|
while (!(*res = f_readdir(&dir, &fno)) && fno.fname[0]) {
|
||||||
FSEntry_t newEntry = {.optionUnion = fno.fattrib, .name = CpyStr(fno.fname)};
|
FSEntry_t newEntry = {.optionUnion = fno.fattrib, .name = CpyStr(fno.fname)};
|
||||||
|
|
||||||
if (!newEntry.isDir){
|
if (!newEntry.isDir){
|
||||||
|
|
|
@ -3,4 +3,5 @@
|
||||||
#include "../../utils/vector.h"
|
#include "../../utils/vector.h"
|
||||||
#include "../fstypes.h"
|
#include "../fstypes.h"
|
||||||
|
|
||||||
Vector_t /* of type FSEntry_t */ ReadFolder(char *path);
|
void clearFileVector(Vector_t *v);
|
||||||
|
Vector_t /* of type FSEntry_t */ ReadFolder(char *path, int *res);
|
|
@ -19,6 +19,15 @@ void gfx_clearscreen(){
|
||||||
RESETCOLOR;
|
RESETCOLOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MenuEntry_t YesNoEntries[] = {
|
||||||
|
{.optionUnion = COLORTORGB(COLOR_YELLOW), .name = "No"},
|
||||||
|
{.R = 255, .name = "Yes"}
|
||||||
|
};
|
||||||
|
|
||||||
|
int MakeYesNoHorzMenu(int spacesBetween, u32 bg){
|
||||||
|
return MakeHorizontalMenu(YesNoEntries, ARR_LEN(YesNoEntries), spacesBetween, bg);
|
||||||
|
}
|
||||||
|
|
||||||
int MakeHorizontalMenu(MenuEntry_t *entries, int len, int spacesBetween, u32 bg){
|
int MakeHorizontalMenu(MenuEntry_t *entries, int len, int spacesBetween, u32 bg){
|
||||||
u32 initialX = 0, initialY = 0;
|
u32 initialX = 0, initialY = 0;
|
||||||
u32 highlight = 0;
|
u32 highlight = 0;
|
||||||
|
|
|
@ -14,4 +14,5 @@
|
||||||
#define RGBUnionToU32(optionUnion) (optionUnion | 0xFF000000)
|
#define RGBUnionToU32(optionUnion) (optionUnion | 0xFF000000)
|
||||||
|
|
||||||
void gfx_clearscreen();
|
void gfx_clearscreen();
|
||||||
int MakeHorizontalMenu(MenuEntry_t *entries, int len, int spacesBetween, u32 bg);
|
int MakeHorizontalMenu(MenuEntry_t *entries, int len, int spacesBetween, u32 bg);
|
||||||
|
int MakeYesNoHorzMenu(int spacesBetween, u32 bg);
|
31
source/keys/nca.c
Normal file
31
source/keys/nca.c
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#include "nca.h"
|
||||||
|
#include "keys.h"
|
||||||
|
#include <libs/fatfs/ff.h>
|
||||||
|
#include <sec/se.h>
|
||||||
|
#include <mem/heap.h>
|
||||||
|
|
||||||
|
// Thanks switchbrew https://switchbrew.org/wiki/NCA_Format
|
||||||
|
// This function is hacky, should change it but am lazy
|
||||||
|
int GetNcaType(char *path){
|
||||||
|
FIL fp;
|
||||||
|
u32 read_bytes = 0;
|
||||||
|
|
||||||
|
if (f_open(&fp, path, FA_READ | FA_OPEN_EXISTING))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
u8 *dec_header = (u8*)malloc(0x400);
|
||||||
|
|
||||||
|
if (f_lseek(&fp, 0x200) || f_read(&fp, dec_header, 32, &read_bytes) || read_bytes != 32){
|
||||||
|
f_close(&fp);
|
||||||
|
free(dec_header);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
se_aes_xts_crypt(7,6,0,1, dec_header + 0x200, dec_header, 32, 1);
|
||||||
|
|
||||||
|
u8 ContentType = dec_header[0x205];
|
||||||
|
|
||||||
|
f_close(&fp);
|
||||||
|
free(dec_header);
|
||||||
|
return ContentType;
|
||||||
|
}
|
12
source/keys/nca.h
Normal file
12
source/keys/nca.h
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
enum NcaTypes {
|
||||||
|
Porgram = 0,
|
||||||
|
Meta,
|
||||||
|
Control,
|
||||||
|
Manual,
|
||||||
|
Data,
|
||||||
|
PublicData
|
||||||
|
};
|
||||||
|
|
||||||
|
int GetNcaType(char *path);
|
|
@ -271,6 +271,7 @@ void ipl_main()
|
||||||
emu_cfg.enabled = !h_cfg.emummc_force_disable;
|
emu_cfg.enabled = !h_cfg.emummc_force_disable;
|
||||||
h_cfg.emummc_force_disable = 1;
|
h_cfg.emummc_force_disable = 1;
|
||||||
|
|
||||||
|
TConf.pkg1ID = "Unk";
|
||||||
|
|
||||||
hidInit();
|
hidInit();
|
||||||
|
|
||||||
|
@ -290,7 +291,7 @@ void ipl_main()
|
||||||
int res = -1;
|
int res = -1;
|
||||||
|
|
||||||
|
|
||||||
if (DumpKeys() || btn_read() & BTN_VOL_DOWN)
|
if (btn_read() & BTN_VOL_DOWN || DumpKeys())
|
||||||
res = GetKeysFromFile("sd:/switch/prod.keys");
|
res = GetKeysFromFile("sd:/switch/prod.keys");
|
||||||
|
|
||||||
TConf.keysDumped = (res > 0) ? 0 : 1;
|
TConf.keysDumped = (res > 0) ? 0 : 1;
|
||||||
|
|
|
@ -82,6 +82,7 @@ void GptMenu(u8 MMCType){
|
||||||
else {
|
else {
|
||||||
if (TConf.curExplorerLoc > LOC_SD)
|
if (TConf.curExplorerLoc > LOC_SD)
|
||||||
ResetCopyParams();
|
ResetCopyParams();
|
||||||
|
|
||||||
TConf.curExplorerLoc = LOC_EMMC;
|
TConf.curExplorerLoc = LOC_EMMC;
|
||||||
FileExplorer("bis:/");
|
FileExplorer("bis:/");
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,10 @@ void SetKeySlots(){
|
||||||
se_aes_key_set(3, dumpedKeys.bis_key[1] + AES_128_KEY_SIZE, AES_128_KEY_SIZE);
|
se_aes_key_set(3, dumpedKeys.bis_key[1] + AES_128_KEY_SIZE, AES_128_KEY_SIZE);
|
||||||
se_aes_key_set(4, dumpedKeys.bis_key[2], AES_128_KEY_SIZE);
|
se_aes_key_set(4, dumpedKeys.bis_key[2], AES_128_KEY_SIZE);
|
||||||
se_aes_key_set(5, dumpedKeys.bis_key[2] + AES_128_KEY_SIZE, AES_128_KEY_SIZE);
|
se_aes_key_set(5, dumpedKeys.bis_key[2] + AES_128_KEY_SIZE, AES_128_KEY_SIZE);
|
||||||
|
|
||||||
|
// Not for bis but whatever
|
||||||
|
se_aes_key_set(6, dumpedKeys.header_key + 0x00, 0x10);
|
||||||
|
se_aes_key_set(7, dumpedKeys.header_key + 0x10, 0x10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ MenuEntry_t mainMenuEntries[] = {
|
||||||
{.optionUnion = COLORTORGB(COLOR_YELLOW), .name = "Emummc"},
|
{.optionUnion = COLORTORGB(COLOR_YELLOW), .name = "Emummc"},
|
||||||
{.B = 255, .G = 255, .name = "Test Controllers"},
|
{.B = 255, .G = 255, .name = "Test Controllers"},
|
||||||
{.R = 255, .name = "Cause an exception"},
|
{.R = 255, .name = "Cause an exception"},
|
||||||
|
{.optionUnion = COLORTORGB(COLOR_BLUE), .name = "Dump Firmware"},
|
||||||
{.optionUnion = COLORTORGB(COLOR_ORANGE), .name = "View dumped keys"},
|
{.optionUnion = COLORTORGB(COLOR_ORANGE), .name = "View dumped keys"},
|
||||||
{.R = 255, .name = "Reboot to payload"}
|
{.R = 255, .name = "Reboot to payload"}
|
||||||
};
|
};
|
||||||
|
@ -73,6 +74,7 @@ menuPaths mainMenuPaths[] = {
|
||||||
HandleEMUMMC,
|
HandleEMUMMC,
|
||||||
TestControllers,
|
TestControllers,
|
||||||
CrashTE,
|
CrashTE,
|
||||||
|
DumpSysFw,
|
||||||
ViewKeys,
|
ViewKeys,
|
||||||
RebootToPayload
|
RebootToPayload
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,6 +3,20 @@
|
||||||
#include "../gfx/gfxutils.h"
|
#include "../gfx/gfxutils.h"
|
||||||
#include "../gfx/menu.h"
|
#include "../gfx/menu.h"
|
||||||
#include "../hid/hid.h"
|
#include "../hid/hid.h"
|
||||||
|
#include <libs/fatfs/ff.h>
|
||||||
|
#include "../keys/keys.h"
|
||||||
|
#include "../keys/nca.h"
|
||||||
|
#include <storage/nx_sd.h>
|
||||||
|
#include "../fs/fsutils.h"
|
||||||
|
#include <utils/util.h>
|
||||||
|
#include "../storage/mountmanager.h"
|
||||||
|
#include "../err.h"
|
||||||
|
#include <utils/sprintf.h>
|
||||||
|
#include <mem/heap.h>
|
||||||
|
#include "../tegraexplorer/tconf.h"
|
||||||
|
#include "../fs/readers/folderReader.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include "../fs/fscopy.h"
|
||||||
|
|
||||||
void TestControllers(){
|
void TestControllers(){
|
||||||
gfx_clearscreen();
|
gfx_clearscreen();
|
||||||
|
@ -26,4 +40,101 @@ extern int launch_payload(char *path);
|
||||||
|
|
||||||
void RebootToPayload(){
|
void RebootToPayload(){
|
||||||
launch_payload("atmosphere/reboot_payload.bin");
|
launch_payload("atmosphere/reboot_payload.bin");
|
||||||
|
}
|
||||||
|
|
||||||
|
void DumpSysFw(){
|
||||||
|
char sysPath[25 + 36 + 3 + 1]; // 24 for "bis:/Contents/registered", 36 for ncaName.nca, 3 for /00, and 1 to make sure :)
|
||||||
|
char *baseSdPath;
|
||||||
|
|
||||||
|
u32 timer = get_tmr_s();
|
||||||
|
|
||||||
|
if (!sd_mount())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (connectMMC(MMC_CONN_EMMC))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!TConf.keysDumped)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ErrCode_t err = mountMMCPart("SYSTEM");
|
||||||
|
if (err.err){
|
||||||
|
DrawError(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
baseSdPath = malloc(36 + 16);
|
||||||
|
sprintf(baseSdPath, "sd:/tegraexplorer/Firmware/%d (%s)", TConf.pkg1ver, TConf.pkg1ID);
|
||||||
|
int baseSdPathLen = strlen(baseSdPath);
|
||||||
|
|
||||||
|
f_mkdir("sd:/tegraexplorer");
|
||||||
|
f_mkdir("sd:/tegraexplorer/Firmware");
|
||||||
|
|
||||||
|
gfx_clearscreen();
|
||||||
|
|
||||||
|
gfx_printf("Pkg1 id: '%s', kb %d\n", TConf.pkg1ID, TConf.pkg1ver);
|
||||||
|
if (FileExists(baseSdPath)){
|
||||||
|
SETCOLOR(COLOR_ORANGE, COLOR_DEFAULT);
|
||||||
|
gfx_printf("Destination already exists. Replace? ");
|
||||||
|
if (!MakeYesNoHorzMenu(3, COLOR_DEFAULT)){
|
||||||
|
free(baseSdPath);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
RESETCOLOR;
|
||||||
|
gfx_printf("\nReminder! delete the folder. i can't delete recursively yet");
|
||||||
|
gfx_putc('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
f_mkdir(baseSdPath);
|
||||||
|
|
||||||
|
gfx_printf("Out: %s\nReading entries...\n", baseSdPath);
|
||||||
|
int readRes = 0;
|
||||||
|
Vector_t fileVec = ReadFolder("bis:/Contents/registered", &readRes);
|
||||||
|
if (readRes){
|
||||||
|
DrawError(newErrCode(readRes));
|
||||||
|
free(baseSdPath);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx_printf("Starting dump...\n");
|
||||||
|
SETCOLOR(COLOR_GREEN, COLOR_DEFAULT);
|
||||||
|
|
||||||
|
int res = 0;
|
||||||
|
int total = 1;
|
||||||
|
vecDefArray(FSEntry_t*, fsEntries, fileVec);
|
||||||
|
for (int i = 0; i < fileVec.count; i++){
|
||||||
|
sprintf(sysPath, (fsEntries[i].isDir) ? "%s/%s/00" : "%s/%s", "bis:/Contents/registered", fsEntries[i].name);
|
||||||
|
int contentType = GetNcaType(sysPath);
|
||||||
|
|
||||||
|
if (contentType < 0){
|
||||||
|
res = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *sdPath = malloc(baseSdPathLen + 45);
|
||||||
|
sprintf(sdPath, "%s/%s", baseSdPath, fsEntries[i].name);
|
||||||
|
if (contentType == Meta)
|
||||||
|
memcpy(sdPath + strlen(sdPath) - 4, ".cnmt.nca", 10);
|
||||||
|
|
||||||
|
gfx_printf("[%3d / %3d] %s\r", total, fileVec.count, fsEntries[i].name);
|
||||||
|
total++;
|
||||||
|
err = FileCopy(sysPath, sdPath, 0);
|
||||||
|
free(sdPath);
|
||||||
|
if (err.err){
|
||||||
|
DrawError(err);
|
||||||
|
res = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clearFileVector(&fileVec);
|
||||||
|
|
||||||
|
RESETCOLOR;
|
||||||
|
|
||||||
|
if (res){
|
||||||
|
gfx_printf("\nDump failed...\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx_printf("\n\nDone! Time taken: %ds\nPress any key to exit", get_tmr_s() - timer);
|
||||||
|
free(baseSdPath);
|
||||||
|
hidWait();
|
||||||
}
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
void RebootToPayload();
|
void RebootToPayload();
|
||||||
void TestControllers();
|
void TestControllers();
|
||||||
|
void DumpSysFw();
|
Loading…
Reference in a new issue