diff --git a/source/err.c b/source/err.c index 31eaa92..c2183d4 100644 --- a/source/err.c +++ b/source/err.c @@ -26,7 +26,9 @@ const char *TEErrors[] = { [TE_ERR_SAME_LOC - 1] = "Same copy location", [TE_ERR_KEYDUMP_FAIL - 1] = "Keydump failed", [TE_ERR_PARTITION_NOT_FOUND - 1] = "Failed to find partition", - [TE_ERR_PATH_IN_PATH - 1] = "Can't move/copy folder into itself" + [TE_ERR_PATH_IN_PATH - 1] = "Can't move/copy folder into itself", + [TE_ERR_EMMC_READ_FAIL - 1] = "Emmc/Emummc read failed", + [TE_ERR_NO_SD - 1] = "No sd detected", }; const char *GetErrStr(u32 err){ diff --git a/source/err.h b/source/err.h index 88af1ed..b713254 100644 --- a/source/err.h +++ b/source/err.h @@ -17,6 +17,9 @@ enum { TE_ERR_KEYDUMP_FAIL, TE_ERR_PARTITION_NOT_FOUND, TE_ERR_PATH_IN_PATH, + TE_ERR_EMMC_READ_FAIL, + TE_ERR_EMMC_WRITE_FAIL, + TE_ERR_NO_SD, }; #define newErrCode(err) (ErrCode_t) {err, __LINE__, __FILE__} diff --git a/source/storage/emmcfile.c b/source/storage/emmcfile.c new file mode 100644 index 0000000..ef5e9e9 --- /dev/null +++ b/source/storage/emmcfile.c @@ -0,0 +1,84 @@ +#include "emmcfile.h" +#include "../gfx/gfx.h" +#include "emummc.h" +#include "mountmanager.h" +#include +#include "nx_emmc.h" +#include +#include "../err.h" +#include "../tegraexplorer/tconf.h" +#include "../gfx/gfxutils.h" +#include "../hid/hid.h" +#include +#include + +// Uses default storage in nx_emmc.c +// Expects the correct mmc & partition to be set +ErrCode_t EmmcDumpToFile(const char *path, u32 lba_start, u32 lba_end){ + FIL fp; + u32 curLba = lba_start; + u32 totalSectors = lba_end - lba_start + 1; + + int res = f_open(&fp, path, FA_CREATE_ALWAYS | FA_WRITE); + if (res){ + return newErrCode(res); + } + + ErrCode_t err = newErrCode(0); + + u8 *buff = malloc(TConf.FSBuffSize); + + u32 x, y; + gfx_con_getpos(&x, &y); + + while (totalSectors > 0){ + u32 num = MIN(totalSectors, TConf.FSBuffSize / NX_EMMC_BLOCKSIZE); + if (!emummc_storage_read(&emmc_storage, curLba, num, buff)){ + err = newErrCode(TE_ERR_EMMC_READ_FAIL); + break; + } + + if ((res = f_write(&fp, buff, num * NX_EMMC_BLOCKSIZE, NULL))){ + err = newErrCode(res); + break; + } + + curLba += num; + totalSectors -= num; + + u32 percent = ((curLba - lba_start) * 100) / ((lba_end - lba_start + 1)); + gfx_printf("[%3d%%]", percent); + gfx_con_setpos(x, y); + } + + f_close(&fp); + free(buff); + return err; +} + +ErrCode_t DumpEmmcPart(const char *path, const char *part){ + const u32 BOOT_PART_SIZE = emmc_storage.ext_csd.boot_mult << 17; + + if (!sd_mount()) + return newErrCode(TE_ERR_NO_SD); + + // maybe check for existing file here + + if (!memcmp(part, "BOOT0", 5)){ + emummc_storage_set_mmc_partition(&emmc_storage, 1); + return EmmcDumpToFile(path, 0, (BOOT_PART_SIZE / NX_EMMC_BLOCKSIZE) - 1); + } + else if (!memcmp(part, "BOOT1", 5)){ + emummc_storage_set_mmc_partition(&emmc_storage, 2); + return EmmcDumpToFile(path, 0, (BOOT_PART_SIZE / NX_EMMC_BLOCKSIZE) - 1); + } + else { + emummc_storage_set_mmc_partition(&emmc_storage, 0); + + emmc_part_t *system_part = nx_emmc_part_find(GetCurGPT(), part); + if (!system_part) + return newErrCode(TE_ERR_PARTITION_NOT_FOUND); + + return EmmcDumpToFile(path, system_part->lba_start, system_part->lba_end); + } +} \ No newline at end of file diff --git a/source/storage/emmcfile.h b/source/storage/emmcfile.h new file mode 100644 index 0000000..0fd5a4f --- /dev/null +++ b/source/storage/emmcfile.h @@ -0,0 +1,4 @@ +#pragma once +#include "../err.h" + +ErrCode_t DumpEmmcPart(const char *path, const char *part); \ No newline at end of file diff --git a/source/storage/gptmenu.c b/source/storage/gptmenu.c index 0e0cf60..39438a1 100644 --- a/source/storage/gptmenu.c +++ b/source/storage/gptmenu.c @@ -11,11 +11,15 @@ #include "../fs/menus/explorer.h" #include "../err.h" #include "../tegraexplorer/tconf.h" +#include "emmcfile.h" +#include +#include "../fs/fsutils.h" MenuEntry_t GptMenuHeader[] = { {.optionUnion = COLORTORGB(COLOR_ORANGE), .name = "<- Back"}, - {.optionUnion = COLORTORGB(COLOR_GREY) | SKIPBIT, .name = "Clipboard -> Partition"}, - {.optionUnion = COLORTORGB(COLOR_GREY) | SKIPBIT, .name = "\nBoot0/1"} // Should be blue when implemented + {.optionUnion = COLORTORGB(COLOR_GREY) | SKIPBIT, .name = "Clipboard -> Partition\n"}, + {.optionUnion = COLORTORGB(COLOR_BLUE), .name = "BOOT0", .icon = 128, .showSize = 1, .size = 4, .sizeDef = 2}, + {.optionUnion = COLORTORGB(COLOR_BLUE), .name = "BOOT1", .icon = 128, .showSize = 1, .size = 4, .sizeDef = 2} }; const char *GptFSEntries[] = { @@ -30,7 +34,7 @@ void GptMenu(u8 MMCType){ return; Vector_t GptMenu = newVec(sizeof(MenuEntry_t), 15); - GptMenu.count = 3; + GptMenu.count = ARR_LEN(GptMenuHeader); memcpy(GptMenu.data, GptMenuHeader, sizeof(MenuEntry_t) * ARR_LEN(GptMenuHeader)); link_t *gpt = GetCurGPT(); @@ -70,7 +74,7 @@ void GptMenu(u8 MMCType){ res = newMenu(&GptMenu, res, 40, 20, ALWAYSREDRAW | ENABLEB, GptMenu.count); - if (res < 3){ + if (res < 2){ break; } else if (entries[res].icon == 127){ @@ -88,7 +92,25 @@ void GptMenu(u8 MMCType){ } } else { - DrawError(newErrCode(TE_ERR_UNIMPLEMENTED)); + if (!sd_mount()) + continue; + + gfx_clearscreen(); + gfx_printf("Do you want to dump %s? ", entries[res].name); + if (MakeYesNoHorzMenu(3, COLOR_DEFAULT)){ + gfx_putc('\n'); + RESETCOLOR; + gfx_printf("Dumping %s... ", entries[res].name); + + f_mkdir("sd:/tegraexplorer"); + f_mkdir("sd:/tegraexplorer/Dumps"); + + char *path = CombinePaths("sd:/tegraexplorer/Dumps", entries[res].name); + + ErrCode_t a = DumpEmmcPart(path, entries[res].name); + if (a.err) + DrawError(a); + } } } diff --git a/source/storage/mountmanager.c b/source/storage/mountmanager.c index a3311a2..447be23 100644 --- a/source/storage/mountmanager.c +++ b/source/storage/mountmanager.c @@ -27,12 +27,16 @@ void SetKeySlots(){ LIST_INIT(curGpt); -void disconnectMMC(){ +void unmountMMCPart(){ if (TConf.connectedMMCMounted) f_unmount("bis:"); + TConf.connectedMMCMounted = 0; +} + +void disconnectMMC(){ + unmountMMCPart(); if (TConf.currentMMCConnected != MMC_CONN_None){ - TConf.connectedMMCMounted = 0; TConf.currentMMCConnected = MMC_CONN_None; emummc_storage_end(&emmc_storage); nx_emmc_gpt_free(&curGpt); @@ -57,21 +61,22 @@ int connectMMC(u8 mmcType){ } ErrCode_t mountMMCPart(const char *partition){ - if (!TConf.connectedMMCMounted){ - emummc_storage_set_mmc_partition(&emmc_storage, 0); // why i have to do this twice beats me - - emmc_part_t *system_part = nx_emmc_part_find(&curGpt, partition); - if (!system_part) - return newErrCode(TE_ERR_PARTITION_NOT_FOUND); - - nx_emmc_bis_init(system_part); + unmountMMCPart(); - int res = 0; - if ((res = f_mount(&emmc_fs, "bis:", 1))) - return newErrCode(res); + emummc_storage_set_mmc_partition(&emmc_storage, 0); // why i have to do this twice beats me + + emmc_part_t *system_part = nx_emmc_part_find(&curGpt, partition); + if (!system_part) + return newErrCode(TE_ERR_PARTITION_NOT_FOUND); + + nx_emmc_bis_init(system_part); - TConf.connectedMMCMounted = 1; - } + int res = 0; + if ((res = f_mount(&emmc_fs, "bis:", 1))) + return newErrCode(res); + + TConf.connectedMMCMounted = 1; + return newErrCode(0); } @@ -80,10 +85,4 @@ link_t *GetCurGPT(){ if (TConf.currentMMCConnected != MMC_CONN_None) return &curGpt; return NULL; -} - -void unmountMMCPart(){ - if (TConf.connectedMMCMounted) - f_unmount("bis:"); - TConf.connectedMMCMounted = 0; } \ No newline at end of file diff --git a/source/tegraexplorer/mainmenu.c b/source/tegraexplorer/mainmenu.c index d2b9d44..9ee9d3b 100644 --- a/source/tegraexplorer/mainmenu.c +++ b/source/tegraexplorer/mainmenu.c @@ -15,10 +15,6 @@ #include #include "../fs/fsutils.h" -#include -#include "../utils/utils.h" -#include - enum { MainExplore = 0, MainBrowseSd,