mirror of
https://github.com/CTCaer/hekate.git
synced 2024-11-22 18:06:40 +00:00
Support dumping all possible eMMC partitions (with file splitting when necessary)
This commit is contained in:
parent
8365426fc3
commit
04de3d184a
1 changed files with 116 additions and 24 deletions
140
ipl/main.c
140
ipl/main.c
|
@ -15,6 +15,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <alloca.h>
|
||||||
|
|
||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
#include "uart.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)
|
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;
|
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;
|
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;
|
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))
|
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);
|
tui_pbar(&gfx_con, 0, gfx_con.y, pct);
|
||||||
|
|
||||||
lba_curr += num;
|
lba_curr += num;
|
||||||
total -= num;
|
totalSectors -= num;
|
||||||
|
bytesWritten += num * NX_EMMC_BLOCKSIZE;
|
||||||
}
|
}
|
||||||
tui_pbar(&gfx_con, 0, gfx_con.y, 100);
|
tui_pbar(&gfx_con, 0, gfx_con.y, 100);
|
||||||
|
|
||||||
|
@ -413,7 +466,14 @@ out:;
|
||||||
return 1;
|
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_clear(&gfx_ctxt, 0xFF000000);
|
||||||
gfx_con_setpos(&gfx_con, 0, 0);
|
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);
|
gfx_printf(&gfx_con, "%kFailed to init eMMC.%k\n", 0xFF0000FF, 0xFFFFFFFF);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
sdmmc_storage_set_mmc_partition(&storage, 0);
|
|
||||||
|
|
||||||
LIST_INIT(gpt);
|
if (dumpType & DUMP_BOOT)
|
||||||
nx_emmc_gpt_parse(&gpt, &storage);
|
{
|
||||||
int i = 0;
|
static u32 BOOT_PART_SIZE = 0x400000;
|
||||||
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);
|
|
||||||
|
|
||||||
//XXX: skip these for now.
|
emmc_part_t bootPart;
|
||||||
if (//!strcmp(part->name, "SYSTEM") ||
|
memset(&bootPart, 0, sizeof(bootPart));
|
||||||
!strcmp(part->name, "USER"))
|
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");
|
memcpy(bootPart.name, "BOOT", 4);
|
||||||
continue;
|
bootPart.name[4] = (u8)('0' + i);
|
||||||
}
|
bootPart.name[5] = 0;
|
||||||
|
|
||||||
dump_emmc_part(part->name, &storage, part);
|
gfx_printf(&gfx_con, "%02d: %s (%08X-%08X)\n", i,
|
||||||
gfx_putc(&gfx_con, '\n');
|
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);
|
sdmmc_storage_end(&storage);
|
||||||
|
gfx_puts(&gfx_con, "Done.\n");
|
||||||
|
|
||||||
out:;
|
out:;
|
||||||
sleep(100000);
|
sleep(100000);
|
||||||
btn_wait();
|
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()
|
void launch_firmware()
|
||||||
{
|
{
|
||||||
ini_sec_t *cfg_sec = NULL;
|
ini_sec_t *cfg_sec = NULL;
|
||||||
|
@ -571,7 +661,9 @@ menu_t menu_cinfo = {
|
||||||
|
|
||||||
ment_t ment_tools[] = {
|
ment_t ment_tools[] = {
|
||||||
MDEF_BACK(),
|
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()
|
MDEF_END()
|
||||||
};
|
};
|
||||||
menu_t menu_tools = {
|
menu_t menu_tools = {
|
||||||
|
|
Loading…
Reference in a new issue