forked from CTCaer/hekate
Support dumping all possible eMMC partitions (with file splitting when necessary)
This commit is contained in:
parent
8365426fc3
commit
04de3d184a
140
ipl/main.c
140
ipl/main.c
@ -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 = {
|
||||
|
Loading…
Reference in New Issue
Block a user