Compare commits

..

8 Commits

Author SHA1 Message Date
Kostas Missos
b77f185269 Fix small typo 2018-05-03 20:21:10 +03:00
Kostas Missos
f776c1f79f Add SD write retry and some other changes
Increase retry count to 6 tries
Add colors and change a little bit some messages
Change some namings
2018-05-03 19:26:57 +03:00
Kostas Missos
c0bad45cde Add partial dumping when free space is not enough 2018-05-03 19:23:26 +03:00
Rajko Stojadinovic
e7373548fa Make it smaller 2018-05-02 15:37:15 +12:00
Rajko Stojadinovic
138a7658ad Add missing const on constants 2018-05-02 15:37:15 +12:00
Rajko Stojadinovic
8a327030bd Enable exFAT support, don't split files if using it (fsync them instead at 2GiB boundaries), add RawNand dump option 2018-05-02 15:37:15 +12:00
Rajko Stojadinovic
ee30961b3a Fix percentage overflow when dumping USER, also add retry in case of read failure (experienced by some users) 2018-05-02 15:37:15 +12:00
Rajko Stojadinovic
04de3d184a Support dumping all possible eMMC partitions (with file splitting when necessary) 2018-05-02 15:37:15 +12:00
3 changed files with 281 additions and 357 deletions

View File

@@ -44,7 +44,7 @@ OBJS = $(addprefix $(BUILD)/, \
OBJS += $(addprefix $(BUILD)/, diskio.o ff.o ffunicode.o)
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork
CFLAGS = $(ARCH) -O2 -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -std=gnu11# -Wall
CFLAGS = $(ARCH) -Os -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -std=gnu11# -Wall
LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections
.PHONY: all clean

View File

@@ -200,7 +200,7 @@
/ disk_ioctl() function. */
#define FF_FS_NOFSINFO 0
#define FF_FS_NOFSINFO 1
/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
/ option, and f_getfree() function at first time after volume mount will force
/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
@@ -224,7 +224,7 @@
/ buffer in the filesystem object (FATFS) is used for the file data transfer. */
#define FF_FS_EXFAT 0
#define FF_FS_EXFAT 1
/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
/ When enable exFAT, also LFN needs to be enabled.
/ Note that enabling exFAT discards ANSI C (C89) compatibility. */

View File

@@ -15,6 +15,8 @@
*/
#include <string.h>
#include <stdlib.h>
#include <alloca.h>
#include "clock.h"
#include "uart.h"
@@ -380,40 +382,228 @@ void *sd_file_read(char *path)
int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
{
static const u32 FAT32_FILESIZE_LIMIT = 0xFFFFFFFF;
static const u32 MULTIPART_SPLIT_SIZE = (1u << 31);
static const u32 SECTORS_TO_MB_COEFF = 0x800;
u32 totalSectors = part->lba_end - part->lba_start + 1;
u32 currPartIdx = 0;
u32 numSplitParts = 0;
u32 maxSplitParts = 0;
int isSmallSdCard = 0;
int partialDumpInProgress = 0;
char* outFilename = sd_path;
u32 sdPathLen = strlen(sd_path);
FIL partialIdxFp;
char partialIdxFilename[12];
memcpy(partialIdxFilename, "partial.idx", 11);
partialIdxFilename[11] = 0;
gfx_printf(&gfx_con, "SD Card free space: %dMB, Total dump size %dMB\n",
sd_fs.free_clst * sd_fs.csize / SECTORS_TO_MB_COEFF,
totalSectors / SECTORS_TO_MB_COEFF);
// Check if the USER partition or the RAW eMMC fits the sd card free space
if (totalSectors > (sd_fs.free_clst * sd_fs.csize))
{
isSmallSdCard = 1;
gfx_printf(&gfx_con, "%kSD card free space is smaller than dump total size.%k\n", 0xFF00BAFF, 0xFFFFFFFF);
maxSplitParts = (sd_fs.free_clst * sd_fs.csize) / (MULTIPART_SPLIT_SIZE / 512);
if (!maxSplitParts)
{
gfx_printf(&gfx_con, "%kNot enough free space for partial dumping.%k\n", 0xFF0000FF, 0xFFFFFFFF);
return 0;
}
}
// Check if we continueing a previous raw eMMC dump in progress.
if (isSmallSdCard)
{
if (f_open(&partialIdxFp, partialIdxFilename, FA_READ) == FR_OK)
{
gfx_printf(&gfx_con, "%kFound partial dump in progress. Continuing...%k\n", 0xFF14FDAE, 0xFFFFFFFF);
partialDumpInProgress = 1;
f_read(&partialIdxFp, &currPartIdx, 4, NULL);
f_close(&partialIdxFp);
// Increase maxSplitParts to accommodate previously dumped parts
maxSplitParts += currPartIdx;
}
else
gfx_printf(&gfx_con, "%kContinuing with partial dumping...%k\n", 0xFF00BAFF, 0xFFFFFFFF);
}
// Check if filesystem is FAT32 or the free space is smaller and dump in parts
if (((sd_fs.fs_type != FS_EXFAT) || isSmallSdCard) && totalSectors > (FAT32_FILESIZE_LIMIT/NX_EMMC_BLOCKSIZE))
{
static const u32 MULTIPART_SPLIT_SECTORS = MULTIPART_SPLIT_SIZE/NX_EMMC_BLOCKSIZE;
numSplitParts = (totalSectors+MULTIPART_SPLIT_SECTORS-1)/MULTIPART_SPLIT_SECTORS;
outFilename = alloca(sdPathLen+4);
memcpy(outFilename, sd_path, sdPathLen);
outFilename[sdPathLen++] = '.';
if (!partialDumpInProgress)
{
outFilename[sdPathLen] = '0';
if (numSplitParts >= 10)
{
outFilename[sdPathLen+1] = '0';
outFilename[sdPathLen+2] = 0;
}
else
outFilename[sdPathLen+1] = 0;
}
// Continue from where we left, if partial dump in proggress.
else
{
if (numSplitParts >= 10 && currPartIdx < 10)
{
outFilename[sdPathLen] = '0';
itoa(currPartIdx, &outFilename[sdPathLen+1], 10);
}
else
itoa(currPartIdx, &outFilename[sdPathLen], 10);
}
}
FIL fp;
if (f_open(&fp, sd_path, FA_CREATE_ALWAYS | FA_WRITE) != FR_OK)
if (f_open(&fp, outFilename, FA_CREATE_ALWAYS | FA_WRITE) != FR_OK)
return 0;
u8 *buf = (u8 *)malloc(NX_EMMC_BLOCKSIZE * 512);
static const u32 NUM_SECTORS_PER_ITER = 512;
u8 *buf = (u8 *)malloc(NX_EMMC_BLOCKSIZE * NUM_SECTORS_PER_ITER);
u32 total = part->lba_end - part->lba_start + 1;
u32 lba_curr = part->lba_start;
while(total > 0)
{
u32 num = MIN(total, 512);
u32 bytesWritten = 0;
u32 prevPct=200;
if(!sdmmc_storage_read(storage, lba_curr, num, buf))
// Continue from where we left, if partial dump in proggress.
if (partialDumpInProgress)
{
lba_curr += currPartIdx * (MULTIPART_SPLIT_SIZE / NX_EMMC_BLOCKSIZE);
totalSectors -= currPartIdx * (MULTIPART_SPLIT_SIZE / NX_EMMC_BLOCKSIZE);
}
while(totalSectors > 0)
{
if (numSplitParts != 0 && bytesWritten >= MULTIPART_SPLIT_SIZE)
{
gfx_printf(&gfx_con, "%kError reading %d blocks @ LBA %08X%k\n",
0xFF0000FF, num, lba_curr, 0xFFFFFFFF);
goto out;
f_close(&fp);
memset(&fp, 0, sizeof(fp));
currPartIdx++;
if (numSplitParts >= 10 && currPartIdx < 10)
{
outFilename[sdPathLen] = '0';
itoa(currPartIdx, &outFilename[sdPathLen+1], 10);
}
else
itoa(currPartIdx, &outFilename[sdPathLen], 10);
// More parts to dump that do not currently fit the sd card free space
if (isSmallSdCard && currPartIdx >= maxSplitParts)
{
// Create partial dump index file
if (f_open(&partialIdxFp, partialIdxFilename, FA_CREATE_ALWAYS | FA_WRITE) == FR_OK)
{
f_write(&partialIdxFp, &currPartIdx, 4, NULL);
f_close(&partialIdxFp);
}
else
{
gfx_printf(&gfx_con, "%k\nError creating partial.idx file.%k\n", 0xFF0000FF, 0xFFFFFFFF);
free(buf);
return 0;
}
gfx_puts(&gfx_con, "\n1. Press any key and Power off Switch from the main menu.\n\
2. Move the files from SD card to free space.\n \
Don\'t move the partial.idx file!\n\
3. Unplug and re-plug USB while pressing Vol+.\n\
4. Run hekate - ipl again and press Dump RAW eMMC to continue");
free(buf);
return 1;
}
if (f_open(&fp, outFilename, FA_CREATE_ALWAYS | FA_WRITE) != FR_OK)
{
free(buf);
return 0;
}
bytesWritten = 0;
}
f_write(&fp, buf, NX_EMMC_BLOCKSIZE * num, NULL);
u32 pct = ((lba_curr - part->lba_start) * 100) / (part->lba_end - part->lba_start);
tui_pbar(&gfx_con, 0, gfx_con.y, pct);
int retryCount=0;
u32 num = MIN(totalSectors, NUM_SECTORS_PER_ITER);
while(!sdmmc_storage_read(storage, lba_curr, num, buf))
{
gfx_printf(&gfx_con, "%kError reading %d blocks @ LBA %08X from eMMC (try %d)%k\n",
0xFF0000FF, num, lba_curr, ++retryCount, 0xFFFFFFFF);
sleep(500000);
if (retryCount >= 6)
goto out;
}
retryCount=0;
while (f_write(&fp, buf, NX_EMMC_BLOCKSIZE * num, NULL)){
gfx_printf(&gfx_con, "%kError writing %d blocks from eMMC LBA %08X to SD Card (try %d)%k\n",
0xFF0000FF, num, lba_curr, ++retryCount, 0xFFFFFFFF);
sleep(500000);
if (retryCount >= 6)
goto out;
}
u32 pct = (u64)((u64)(lba_curr - part->lba_start) * 100u) / (u64)(part->lba_end - part->lba_start);
if (pct != prevPct)
{
tui_pbar(&gfx_con, 0, gfx_con.y, pct);
prevPct = pct;
}
lba_curr += num;
total -= num;
totalSectors -= num;
bytesWritten += num * NX_EMMC_BLOCKSIZE;
//force a flush after a lot of data if not splitting
if (numSplitParts == 0 && bytesWritten >= MULTIPART_SPLIT_SIZE)
{
f_sync(&fp);
bytesWritten = 0;
}
}
tui_pbar(&gfx_con, 0, gfx_con.y, 100);
out:;
free(buf);
f_close(&fp);
// Partial dump done. Remove partial dump index file.
if(partialDumpInProgress)
{
f_unlink(partialIdxFilename);
gfx_printf(&gfx_con, "\n\nYou can now join the files and get the complete raw eMMC dump.\n");
}
return 1;
}
void dump_emmc()
typedef enum
{
DUMP_BOOT = 1,
DUMP_SYSTEM = 2,
DUMP_USER = 4,
DUMP_RAW = 8
} dumpType_t;
static void dump_emmc_selected(dumpType_t dumpType)
{
gfx_clear(&gfx_ctxt, 0xFF000000);
gfx_con_setpos(&gfx_con, 0, 0);
@@ -423,6 +613,11 @@ void dump_emmc()
gfx_printf(&gfx_con, "%kFailed to mount SD card (make sure that it is inserted).%k\n", 0xFF0000FF, 0xFFFFFFFF);
goto out;
}
else
{
// Get SD Card free space for partial dumping
f_getfree("", &sd_fs.free_clst, NULL);
}
sdmmc_storage_t storage;
sdmmc_t sdmmc;
@@ -431,343 +626,85 @@ void dump_emmc()
gfx_printf(&gfx_con, "%kFailed to init eMMC.%k\n", 0xFF0000FF, 0xFFFFFFFF);
goto out;
}
sdmmc_storage_set_mmc_partition(&storage, 0);
LIST_INIT(gpt);
nx_emmc_gpt_parse(&gpt, &storage);
int i = 0;
LIST_FOREACH_ENTRY(emmc_part_t, part, &gpt, link)
{
gfx_printf(&gfx_con, "%02d: %s (%08X-%08X)\n", i++,
part->name, part->lba_start, part->lba_end);
if (dumpType & DUMP_BOOT)
{
static const u32 BOOT_PART_SIZE = 0x400000;
//XXX: skip these for now.
if (//!strcmp(part->name, "SYSTEM") ||
!strcmp(part->name, "USER"))
emmc_part_t bootPart;
memset(&bootPart, 0, sizeof(bootPart));
bootPart.lba_start = 0;
bootPart.lba_end = (BOOT_PART_SIZE/NX_EMMC_BLOCKSIZE)-1;
for (i=0; i<2; i++)
{
gfx_puts(&gfx_con, "Skipped.\n");
continue;
memcpy(bootPart.name, "BOOT", 4);
bootPart.name[4] = (u8)('0' + i);
bootPart.name[5] = 0;
gfx_printf(&gfx_con, "%k%02d: %s (%08X-%08X)%k\n", 0xFFFFDD00, i,
bootPart.name, bootPart.lba_start, bootPart.lba_end, 0xFFFFFFFF);
sdmmc_storage_set_mmc_partition(&storage, i+1);
dump_emmc_part(bootPart.name, &storage, &bootPart);
gfx_putc(&gfx_con, '\n');
}
}
if ((dumpType & DUMP_SYSTEM) || (dumpType & DUMP_USER) || (dumpType & DUMP_RAW))
{
sdmmc_storage_set_mmc_partition(&storage, 0);
if ((dumpType & DUMP_SYSTEM) || (dumpType & DUMP_USER))
{
LIST_INIT(gpt);
nx_emmc_gpt_parse(&gpt, &storage);
LIST_FOREACH_ENTRY(emmc_part_t, part, &gpt, link)
{
if ((dumpType & DUMP_USER) == 0 && !strcmp(part->name, "USER"))
continue;
if ((dumpType & DUMP_SYSTEM) == 0 && strcmp(part->name, "USER"))
continue;
gfx_printf(&gfx_con, "%k%02d: %s (%08X-%08X)%k\n", 0xFFFFDD00, i++,
part->name, part->lba_start, part->lba_end, 0xFFFFFFFF);
dump_emmc_part(part->name, &storage, part);
gfx_putc(&gfx_con, '\n');
}
}
if (dumpType & DUMP_RAW)
{
static const u32 RAW_AREA_NUM_SECTORS = 0x3A3E000;
dump_emmc_part(part->name, &storage, part);
gfx_putc(&gfx_con, '\n');
emmc_part_t rawPart;
memset(&rawPart, 0, sizeof(rawPart));
rawPart.lba_start = 0;
rawPart.lba_end = RAW_AREA_NUM_SECTORS-1;
strcpy(rawPart.name, "rawnand.bin");
{
gfx_printf(&gfx_con, "%k%02d: %s (%08X-%08X)%k\n", 0xFFFFDD00, i++,
rawPart.name, rawPart.lba_start, rawPart.lba_end, 0xFFFFFFFF);
dump_emmc_part(rawPart.name, &storage, &rawPart);
gfx_putc(&gfx_con, '\n');
}
}
}
sdmmc_storage_end(&storage);
gfx_puts(&gfx_con, "Done. Press any key.\n");
out:;
sleep(100000);
btn_wait();
}
void dump_boot0_emmc()
{
emmc_part_t *part = (emmc_part_t *)malloc(sizeof(emmc_part_t));
gfx_clear(&gfx_ctxt, 0xFF000000);
gfx_con_setpos(&gfx_con, 0, 0);
if (!sd_mount())
{
gfx_printf(&gfx_con, "%kFailed to mount SD card (make sure that it is inserted).%k\n", 0xFF0000FF, 0xFFFFFFFF);
goto out;
}
sdmmc_storage_t storage;
sdmmc_t sdmmc;
if(!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4))
{
gfx_printf(&gfx_con, "%kFailed to init eMMC.%k\n", 0xFF0000FF, 0xFFFFFFFF);
goto out;
}
sdmmc_storage_set_mmc_partition(&storage, 1);
//LIST_INIT(gpt);
//nx_emmc_gpt_parse(&gpt, &storage);
part->name[0] = 0x62;
part->name[1] = 0x6f;
part->name[2] = 0x6f;
part->name[3] = 0x74;
part->name[4] = 0x5f;
part->name[6] = 0x0;
part->name[5] = 0x30;
part->lba_start = 0x0000;
part->lba_end = 0x1FFF;
gfx_printf(&gfx_con, "%s (%08X-%08X)\n",
part->name, part->lba_start, part->lba_end);
dump_emmc_part(part->name, &storage, part);
gfx_putc(&gfx_con, '\n');
sdmmc_storage_end(&storage);
out:;
sleep(100000);
btn_wait();
}
void dump_boot1_emmc()
{
emmc_part_t *part = (emmc_part_t *)malloc(sizeof(emmc_part_t));
gfx_clear(&gfx_ctxt, 0xFF000000);
gfx_con_setpos(&gfx_con, 0, 0);
if (!sd_mount())
{
gfx_printf(&gfx_con, "%kFailed to mount SD card (make sure that it is inserted).%k\n", 0xFF0000FF, 0xFFFFFFFF);
goto out;
}
sdmmc_storage_t storage;
sdmmc_t sdmmc;
if(!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4))
{
gfx_printf(&gfx_con, "%kFailed to init eMMC.%k\n", 0xFF0000FF, 0xFFFFFFFF);
goto out;
}
sdmmc_storage_set_mmc_partition(&storage, 2);
//LIST_INIT(gpt);
//nx_emmc_gpt_parse(&gpt, &storage);
part->name[0] = 0x62;
part->name[1] = 0x6f;
part->name[2] = 0x6f;
part->name[3] = 0x74;
part->name[4] = 0x5f;
part->name[6] = 0x0;
part->name[5] = 0x31;
part->lba_start = 0x0000;
part->lba_end = 0x1FFF;
gfx_printf(&gfx_con, "%s (%08X-%08X)\n",
part->name, part->lba_start, part->lba_end);
dump_emmc_part(part->name, &storage, part);
gfx_putc(&gfx_con, '\n');
sdmmc_storage_end(&storage);
out:;
sleep(100000);
btn_wait();
}
void dump_raw_emmc()
{
emmc_part_t *part = (emmc_part_t *)malloc(sizeof(emmc_part_t));
gfx_clear(&gfx_ctxt, 0xFF000000);
gfx_con_setpos(&gfx_con, 0, 0);
if (!sd_mount())
{
gfx_printf(&gfx_con, "%kFailed to mount SD card (make sure that it is inserted).%k\n", 0xFF0000FF, 0xFFFFFFFF);
goto out;
}
sdmmc_storage_t storage;
sdmmc_t sdmmc;
if(!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4))
{
gfx_printf(&gfx_con, "%kFailed to init eMMC.%k\n", 0xFF0000FF, 0xFFFFFFFF);
goto out;
}
sdmmc_storage_set_mmc_partition(&storage, 0);
//LIST_INIT(gpt);
//nx_emmc_gpt_parse(&gpt, &storage);
part->name[0] = 0x70;
part->name[1] = 0x61;
part->name[2] = 0x72;
part->name[3] = 0x74;
part->name[4] = 0x5f;
part->name[6] = 0x0;
part->name[5] = 0x30;
part->lba_start = 0x000000;
part->lba_end = 0x7FFFFF;
gfx_printf(&gfx_con, "%s (%08X-%08X)\n",
part->name, part->lba_start, part->lba_end);
dump_emmc_part(part->name, &storage, part);
gfx_putc(&gfx_con, '\n');
part->name[5] = 0x31;
part->lba_start = 0x800000;
part->lba_end = 0xFFFFFF;
gfx_printf(&gfx_con, "%s (%08X-%08X)\n",
part->name, part->lba_start, part->lba_end);
dump_emmc_part(part->name, &storage, part);
gfx_putc(&gfx_con, '\n');
sdmmc_storage_end(&storage);
out:;
sleep(100000);
btn_wait();
}
void dump_raw_emmc1()
{
emmc_part_t *part = (emmc_part_t *)malloc(sizeof(emmc_part_t));
gfx_clear(&gfx_ctxt, 0xFF000000);
gfx_con_setpos(&gfx_con, 0, 0);
if (!sd_mount())
{
gfx_printf(&gfx_con, "%kFailed to mount SD card (make sure that it is inserted).%k\n", 0xFF0000FF, 0xFFFFFFFF);
goto out;
}
sdmmc_storage_t storage;
sdmmc_t sdmmc;
if(!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4))
{
gfx_printf(&gfx_con, "%kFailed to init eMMC.%k\n", 0xFF0000FF, 0xFFFFFFFF);
goto out;
}
sdmmc_storage_set_mmc_partition(&storage, 0);
//LIST_INIT(gpt);
//nx_emmc_gpt_parse(&gpt, &storage);
part->name[0] = 0x70;
part->name[1] = 0x61;
part->name[2] = 0x72;
part->name[3] = 0x74;
part->name[4] = 0x5f;
part->name[6] = 0x0;
part->name[5] = 0x32;
part->lba_start = 0x1000000;
part->lba_end = 0x17FFFFF;
gfx_printf(&gfx_con, "%s (%08X-%08X)\n",
part->name, part->lba_start, part->lba_end);
dump_emmc_part(part->name, &storage, part);
gfx_putc(&gfx_con, '\n');
part->name[5] = 0x33;
part->lba_start = 0x1800000;
part->lba_end = 0x1FFFFFF;
gfx_printf(&gfx_con, "%s (%08X-%08X)\n",
part->name, part->lba_start, part->lba_end);
dump_emmc_part(part->name, &storage, part);
gfx_putc(&gfx_con, '\n');
sdmmc_storage_end(&storage);
out:;
sleep(100000);
btn_wait();
}
void dump_raw_emmc2()
{
emmc_part_t *part = (emmc_part_t *)malloc(sizeof(emmc_part_t));
gfx_clear(&gfx_ctxt, 0xFF000000);
gfx_con_setpos(&gfx_con, 0, 0);
if (!sd_mount())
{
gfx_printf(&gfx_con, "%kFailed to mount SD card (make sure that it is inserted).%k\n", 0xFF0000FF, 0xFFFFFFFF);
goto out;
}
sdmmc_storage_t storage;
sdmmc_t sdmmc;
if(!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4))
{
gfx_printf(&gfx_con, "%kFailed to init eMMC.%k\n", 0xFF0000FF, 0xFFFFFFFF);
goto out;
}
sdmmc_storage_set_mmc_partition(&storage, 0);
//LIST_INIT(gpt);
//nx_emmc_gpt_parse(&gpt, &storage);
part->name[0] = 0x70;
part->name[1] = 0x61;
part->name[2] = 0x72;
part->name[3] = 0x74;
part->name[4] = 0x5f;
part->name[6] = 0x0;
part->name[5] = 0x34;
part->lba_start = 0x2000000;
part->lba_end = 0x27FFFFF;
gfx_printf(&gfx_con, "%s (%08X-%08X)\n",
part->name, part->lba_start, part->lba_end);
dump_emmc_part(part->name, &storage, part);
gfx_putc(&gfx_con, '\n');
part->name[5] = 0x35;
part->lba_start = 0x2800000;
part->lba_end = 0x2FFFFFF;
gfx_printf(&gfx_con, "%s (%08X-%08X)\n",
part->name, part->lba_start, part->lba_end);
dump_emmc_part(part->name, &storage, part);
gfx_putc(&gfx_con, '\n');
sdmmc_storage_end(&storage);
out:;
sleep(100000);
btn_wait();
}
void dump_raw_emmc3()
{
emmc_part_t *part = (emmc_part_t *)malloc(sizeof(emmc_part_t));
gfx_clear(&gfx_ctxt, 0xFF000000);
gfx_con_setpos(&gfx_con, 0, 0);
if (!sd_mount())
{
gfx_printf(&gfx_con, "%kFailed to mount SD card (make sure that it is inserted).%k\n", 0xFF0000FF, 0xFFFFFFFF);
goto out;
}
sdmmc_storage_t storage;
sdmmc_t sdmmc;
if(!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4))
{
gfx_printf(&gfx_con, "%kFailed to init eMMC.%k\n", 0xFF0000FF, 0xFFFFFFFF);
goto out;
}
sdmmc_storage_set_mmc_partition(&storage, 0);
//LIST_INIT(gpt);
//nx_emmc_gpt_parse(&gpt, &storage);
part->name[0] = 0x70;
part->name[1] = 0x61;
part->name[2] = 0x72;
part->name[3] = 0x74;
part->name[4] = 0x5f;
part->name[6] = 0x0;
part->name[5] = 0x36;
part->lba_start = 0x3000000;
part->lba_end = 0x37FFFFF;
gfx_printf(&gfx_con, "%s (%08X-%08X)\n",
part->name, part->lba_start, part->lba_end);
dump_emmc_part(part->name, &storage, part);
gfx_putc(&gfx_con, '\n');
part->name[5] = 0x37;
part->lba_start = 0x3800000;
part->lba_end = 0x3A3DFFF;
gfx_printf(&gfx_con, "%s (%08X-%08X)\n",
part->name, part->lba_start, part->lba_end);
dump_emmc_part(part->name, &storage, part);
gfx_putc(&gfx_con, '\n');
sdmmc_storage_end(&storage);
out:;
sleep(100000);
btn_wait();
}
void dump_emmc_system() { dump_emmc_selected(DUMP_SYSTEM); }
void dump_emmc_user() { dump_emmc_selected(DUMP_USER); }
void dump_emmc_boot() { dump_emmc_selected(DUMP_BOOT); }
void dump_emmc_rawnand() { dump_emmc_selected(DUMP_RAW); }
void launch_firmware()
{
@@ -878,25 +815,12 @@ menu_t menu_cinfo = {
"Console info", 0, 0
};
ment_t ment_rawemmc[] = {
MDEF_BACK(),
MDEF_HANDLER("Boot0", dump_boot0_emmc),
MDEF_HANDLER("Boot1", dump_boot1_emmc),
MDEF_HANDLER("1st 8GB", dump_raw_emmc),
MDEF_HANDLER("2nd 8GB", dump_raw_emmc1),
MDEF_HANDLER("3rd 8GB", dump_raw_emmc2),
MDEF_HANDLER("4th 8GB", dump_raw_emmc3),
MDEF_END()
};
menu_t menu_rawemmc = {
ment_rawemmc,
"Dump raw eMMC", 0, 0
};
ment_t ment_tools[] = {
MDEF_BACK(),
MDEF_HANDLER("Dump eMMC", dump_emmc),
MDEF_MENU("Dump raw eMMC", &menu_rawemmc),
MDEF_HANDLER("Dump RAW eMMC", dump_emmc_rawnand),
MDEF_HANDLER("Dump eMMC SYS", dump_emmc_system),
MDEF_HANDLER("Dump eMMC USER", dump_emmc_user),
MDEF_HANDLER("Dump eMMC BOOT", dump_emmc_boot),
MDEF_END()
};
menu_t menu_tools = {