Support dumping all possible eMMC partitions (with file splitting when necessary)

This commit is contained in:
Rajko Stojadinovic 2018-05-01 13:17:13 +02:00 committed by nwert
parent 8365426fc3
commit 04de3d184a

View file

@ -15,6 +15,8 @@
*/
#include <string.h>
#include <stdlib.h>
#include <alloca.h>
#include "clock.h"
#include "uart.h"
@ -380,17 +382,67 @@ void *sd_file_read(char *path)
int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
{
static u32 FAT32_FILESIZE_LIMIT = 0xFFFFFFFF;
static u32 MULTIPART_SPLIT_SIZE = (1u << 31);
u32 totalSectors = part->lba_end - part->lba_start + 1;
char* outFilename = sd_path;
u32 sdPathLen = strlen(sd_path);
u32 numSplitParts = 0;
if (totalSectors > (FAT32_FILESIZE_LIMIT/NX_EMMC_BLOCKSIZE))
{
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++] = '.';
outFilename[sdPathLen] = '0';
if (numSplitParts >= 10)
{
outFilename[sdPathLen+1] = '0';
outFilename[sdPathLen+2] = 0;
}
else
outFilename[sdPathLen+1] = 0;
}
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 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 bytesWritten = 0;
u32 currPartIdx = 0;
while(totalSectors > 0)
{
u32 num = MIN(total, 512);
if (numSplitParts != 0 && bytesWritten >= MULTIPART_SPLIT_SIZE)
{
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);
if (f_open(&fp, outFilename, FA_CREATE_ALWAYS | FA_WRITE) != FR_OK)
{
free(buf);
return 0;
}
bytesWritten = 0;
}
u32 num = MIN(totalSectors, NUM_SECTORS_PER_ITER);
if(!sdmmc_storage_read(storage, lba_curr, num, buf))
{
@ -403,7 +455,8 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
tui_pbar(&gfx_con, 0, gfx_con.y, pct);
lba_curr += num;
total -= num;
totalSectors -= num;
bytesWritten += num * NX_EMMC_BLOCKSIZE;
}
tui_pbar(&gfx_con, 0, gfx_con.y, 100);
@ -413,7 +466,14 @@ out:;
return 1;
}
void dump_emmc()
typedef enum
{
DUMP_BOOT = 1,
DUMP_SYSTEM = 2,
DUMP_USER = 4
} dumpType_t;
static void dump_emmc_selected(dumpType_t dumpType)
{
gfx_clear(&gfx_ctxt, 0xFF000000);
gfx_con_setpos(&gfx_con, 0, 0);
@ -431,35 +491,65 @@ 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 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 (u32 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;
dump_emmc_part(part->name, &storage, part);
gfx_putc(&gfx_con, '\n');
gfx_printf(&gfx_con, "%02d: %s (%08X-%08X)\n", i,
bootPart.name, bootPart.lba_start, bootPart.lba_end);
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))
{
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)
{
if ((dumpType & DUMP_USER) == 0 && !strcmp(part->name, "USER"))
continue;
if ((dumpType & DUMP_SYSTEM) == 0 && strcmp(part->name, "USER"))
continue;
gfx_printf(&gfx_con, "%02d: %s (%08X-%08X)\n", i++,
part->name, part->lba_start, part->lba_end);
dump_emmc_part(part->name, &storage, part);
gfx_putc(&gfx_con, '\n');
}
}
sdmmc_storage_end(&storage);
gfx_puts(&gfx_con, "Done.\n");
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 launch_firmware()
{
ini_sec_t *cfg_sec = NULL;
@ -571,7 +661,9 @@ menu_t menu_cinfo = {
ment_t ment_tools[] = {
MDEF_BACK(),
MDEF_HANDLER("Dump eMMC", dump_emmc),
MDEF_HANDLER("Dump eMMC", 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 = {