mirror of
https://github.com/Decscots/Lockpick_RCM
synced 2024-11-25 03:09:24 +00:00
Improve emummc semantics and error checking
This commit is contained in:
parent
bd09f5418d
commit
5ed601dd4b
7 changed files with 114 additions and 76 deletions
10
Makefile
10
Makefile
|
@ -49,6 +49,11 @@ LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defs
|
||||||
.PHONY: all clean
|
.PHONY: all clean
|
||||||
|
|
||||||
all: $(OUTPUTDIR)/$(TARGET).bin
|
all: $(OUTPUTDIR)/$(TARGET).bin
|
||||||
|
@echo -n "Payload size is "
|
||||||
|
$(eval BIN_SIZE = $(shell wc -c < $(OUTPUTDIR)/$(TARGET).bin))
|
||||||
|
@echo $(BIN_SIZE)
|
||||||
|
@echo "Max size is 126296 Bytes."
|
||||||
|
@if [ ${BIN_SIZE} -gt 126296 ]; then echo "\e[1;33mPayload size exceeds limit!\e[0m"; fi
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@rm -rf $(BUILDDIR)
|
@rm -rf $(BUILDDIR)
|
||||||
|
@ -57,11 +62,6 @@ clean:
|
||||||
$(OUTPUTDIR)/$(TARGET).bin: $(BUILDDIR)/$(TARGET)/$(TARGET).elf
|
$(OUTPUTDIR)/$(TARGET).bin: $(BUILDDIR)/$(TARGET)/$(TARGET).elf
|
||||||
@mkdir -p "$(@D)"
|
@mkdir -p "$(@D)"
|
||||||
$(OBJCOPY) -S -O binary $< $@
|
$(OBJCOPY) -S -O binary $< $@
|
||||||
@echo -n "Payload size is "
|
|
||||||
$(eval BIN_SIZE = $(shell wc -c < $(OUTPUTDIR)/$(TARGET).bin))
|
|
||||||
@echo $(BIN_SIZE)
|
|
||||||
@echo "Max size is 126296 Bytes."
|
|
||||||
@if [ ${BIN_SIZE} -gt 126296 ]; then echo "\e[1;33mPayload size exceeds limit!\e[0m"; fi
|
|
||||||
|
|
||||||
$(BUILDDIR)/$(TARGET)/$(TARGET).elf: $(OBJS)
|
$(BUILDDIR)/$(TARGET)/$(TARGET).elf: $(OBJS)
|
||||||
$(CC) $(LDFLAGS) -T $(SOURCEDIR)/link.ld $^ -o $@
|
$(CC) $(LDFLAGS) -T $(SOURCEDIR)/link.ld $^ -o $@
|
||||||
|
|
|
@ -79,6 +79,7 @@
|
||||||
#define NYX_FB_SZ 0x384000 // 1280 x 720 x 4.
|
#define NYX_FB_SZ 0x384000 // 1280 x 720 x 4.
|
||||||
|
|
||||||
#define DRAM_MEM_HOLE_ADR 0xF6A00000
|
#define DRAM_MEM_HOLE_ADR 0xF6A00000
|
||||||
|
#define NX_BIS_LOOKUP_ADR DRAM_MEM_HOLE_ADR
|
||||||
#define DRAM_MEM_HOLE_SZ 0x8140000
|
#define DRAM_MEM_HOLE_SZ 0x8140000
|
||||||
/* --- Hole: 129MB 0xF6A00000 - 0xFEB3FFFF --- */
|
/* --- Hole: 129MB 0xF6A00000 - 0xFEB3FFFF --- */
|
||||||
#define DRAM_START2 0xFEB40000
|
#define DRAM_START2 0xFEB40000
|
||||||
|
|
|
@ -86,7 +86,7 @@ void tui_pbar(int x, int y, u32 val, u32 fgcol, u32 bgcol)
|
||||||
gfx_con_setpos(cx, cy);
|
gfx_con_setpos(cx, cy);
|
||||||
|
|
||||||
// Update status bar.
|
// Update status bar.
|
||||||
tui_sbar(false);
|
// tui_sbar(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *tui_do_menu(menu_t *menu)
|
void *tui_do_menu(menu_t *menu)
|
||||||
|
@ -94,7 +94,7 @@ void *tui_do_menu(menu_t *menu)
|
||||||
int idx = 0, prev_idx = 0, cnt = 0x7FFFFFFF;
|
int idx = 0, prev_idx = 0, cnt = 0x7FFFFFFF;
|
||||||
|
|
||||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||||
tui_sbar(true);
|
// tui_sbar(true);
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
@ -203,7 +203,7 @@ void *tui_do_menu(menu_t *menu)
|
||||||
gfx_con.fntsz = 16;
|
gfx_con.fntsz = 16;
|
||||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||||
}
|
}
|
||||||
tui_sbar(false);
|
// tui_sbar(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "../hos/pkg2.h"
|
#include "../hos/pkg2.h"
|
||||||
#include "../hos/sept.h"
|
#include "../hos/sept.h"
|
||||||
#include <libs/fatfs/ff.h>
|
#include <libs/fatfs/ff.h>
|
||||||
|
#include <libs/save/save.h>
|
||||||
#include <mem/heap.h>
|
#include <mem/heap.h>
|
||||||
#include <mem/mc.h>
|
#include <mem/mc.h>
|
||||||
#include <mem/minerva.h>
|
#include <mem/minerva.h>
|
||||||
|
@ -46,7 +47,6 @@
|
||||||
#include <utils/util.h>
|
#include <utils/util.h>
|
||||||
|
|
||||||
#include "key_sources.inl"
|
#include "key_sources.inl"
|
||||||
#include "save.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
@ -123,14 +123,12 @@ void dump_keys() {
|
||||||
sd_mount();
|
sd_mount();
|
||||||
|
|
||||||
display_backlight_brightness(h_cfg.backlight, 1000);
|
display_backlight_brightness(h_cfg.backlight, 1000);
|
||||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
gfx_clear_grey(0x1B);
|
||||||
gfx_con_setpos(0, 0);
|
gfx_con_setpos(0, 0);
|
||||||
|
|
||||||
gfx_printf("[%kLo%kck%kpi%kck%k_R%kCM%k v%d.%d.%d%k]\n\n",
|
gfx_printf("[%kLo%kck%kpi%kck%k_R%kCM%k v%d.%d.%d%k]\n\n",
|
||||||
colors[0], colors[1], colors[2], colors[3], colors[4], colors[5], 0xFFFF00FF, LP_VER_MJ, LP_VER_MN, LP_VER_BF, 0xFFCCCCCC);
|
colors[0], colors[1], colors[2], colors[3], colors[4], colors[5], 0xFFFF00FF, LP_VER_MJ, LP_VER_MN, LP_VER_BF, 0xFFCCCCCC);
|
||||||
|
|
||||||
tui_sbar(true);
|
|
||||||
|
|
||||||
_key_count = 0;
|
_key_count = 0;
|
||||||
_titlekey_count = 0;
|
_titlekey_count = 0;
|
||||||
color_idx = 0;
|
color_idx = 0;
|
||||||
|
@ -150,8 +148,14 @@ void dump_keys() {
|
||||||
|
|
||||||
// Read package1.
|
// Read package1.
|
||||||
u8 *pkg1 = (u8 *)malloc(0x40000);
|
u8 *pkg1 = (u8 *)malloc(0x40000);
|
||||||
emummc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0);
|
if (!emummc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0)) {
|
||||||
emummc_storage_read(&emmc_storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
|
EPRINTF("Unable to set partition.");
|
||||||
|
goto out_wait;
|
||||||
|
}
|
||||||
|
if (!emummc_storage_read(&emmc_storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1)) {
|
||||||
|
EPRINTF("Unable to read pkg1.");
|
||||||
|
goto out_wait;
|
||||||
|
}
|
||||||
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1);
|
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1);
|
||||||
if (!pkg1_id) {
|
if (!pkg1_id) {
|
||||||
EPRINTF("Unknown pkg1 version.\n Make sure you have the latest Lockpick_RCM.\n If a new firmware version just came out,\n Lockpick_RCM must be updated.\n Check Github for new release.");
|
EPRINTF("Unknown pkg1 version.\n Make sure you have the latest Lockpick_RCM.\n If a new firmware version just came out,\n Lockpick_RCM must be updated.\n Check Github for new release.");
|
||||||
|
@ -326,7 +330,10 @@ get_tsec: ;
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify keyblob is not corrupt
|
// verify keyblob is not corrupt
|
||||||
emummc_storage_read(&emmc_storage, 0x180000 / NX_EMMC_BLOCKSIZE + i, 1, keyblob_block);
|
if (!emummc_storage_read(&emmc_storage, 0x180000 / NX_EMMC_BLOCKSIZE + i, 1, keyblob_block)) {
|
||||||
|
EPRINTFARGS("Unable to read keyblob %x.", i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
se_aes_key_set(10, keyblob_mac_key[i], 0x10);
|
se_aes_key_set(10, keyblob_mac_key[i], 0x10);
|
||||||
se_aes_cmac(10, keyblob_mac, 0x10, keyblob_block + 0x10, 0xa0);
|
se_aes_cmac(10, keyblob_mac, 0x10, keyblob_block + 0x10, 0xa0);
|
||||||
if (memcmp(keyblob_block, keyblob_mac, 0x10) != 0) {
|
if (memcmp(keyblob_block, keyblob_mac, 0x10) != 0) {
|
||||||
|
@ -381,7 +388,10 @@ get_tsec: ;
|
||||||
u8 *pkg2 = NULL;
|
u8 *pkg2 = NULL;
|
||||||
pkg2_kip1_info_t *ki = NULL;
|
pkg2_kip1_info_t *ki = NULL;
|
||||||
|
|
||||||
emummc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP);
|
if (!emummc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP)) {
|
||||||
|
EPRINTF("Unable to set partition.");
|
||||||
|
goto out_wait;
|
||||||
|
}
|
||||||
// Parse eMMC GPT.
|
// Parse eMMC GPT.
|
||||||
LIST_INIT(gpt);
|
LIST_INIT(gpt);
|
||||||
nx_emmc_gpt_parse(&gpt, &emmc_storage);
|
nx_emmc_gpt_parse(&gpt, &emmc_storage);
|
||||||
|
@ -596,7 +606,6 @@ pkg2_done:
|
||||||
}
|
}
|
||||||
|
|
||||||
path[24] = '/';
|
path[24] = '/';
|
||||||
nx_emmc_bis_cache_lock(true);
|
|
||||||
while (!f_readdir(&dir, &fno) && fno.fname[0] && titles_found < title_limit) {
|
while (!f_readdir(&dir, &fno) && fno.fname[0] && titles_found < title_limit) {
|
||||||
minerva_periodic_training();
|
minerva_periodic_training();
|
||||||
memcpy(path + 25, fno.fname, 36);
|
memcpy(path + 25, fno.fname, 36);
|
||||||
|
@ -659,7 +668,6 @@ pkg2_done:
|
||||||
}
|
}
|
||||||
f_closedir(&dir);
|
f_closedir(&dir);
|
||||||
free(dec_header);
|
free(dec_header);
|
||||||
nx_emmc_bis_cache_lock(false);
|
|
||||||
|
|
||||||
// derive eticket_rsa_kek and ssl_rsa_kek
|
// derive eticket_rsa_kek and ssl_rsa_kek
|
||||||
if (_key_exists(es_keys[0]) && _key_exists(es_keys[1]) && _key_exists(master_key[0])) {
|
if (_key_exists(es_keys[0]) && _key_exists(es_keys[1]) && _key_exists(master_key[0])) {
|
||||||
|
@ -732,7 +740,10 @@ get_titlekeys:
|
||||||
|
|
||||||
u8 keypair[0x230] = {0};
|
u8 keypair[0x230] = {0};
|
||||||
|
|
||||||
emummc_storage_read(&emmc_storage, 0x4400 / NX_EMMC_BLOCKSIZE, 0x4000 / NX_EMMC_BLOCKSIZE, buffer);
|
if (!emummc_storage_read(&emmc_storage, 0x4400 / NX_EMMC_BLOCKSIZE, 0x4000 / NX_EMMC_BLOCKSIZE, buffer)) {
|
||||||
|
EPRINTF("Unable to read PRODINFO.");
|
||||||
|
goto dismount;
|
||||||
|
}
|
||||||
|
|
||||||
se_aes_xts_crypt(1, 0, 0, 0, buffer, buffer, 0x4000, 1);
|
se_aes_xts_crypt(1, 0, 0, 0, buffer, buffer, 0x4000, 1);
|
||||||
|
|
||||||
|
@ -777,9 +788,9 @@ get_titlekeys:
|
||||||
|
|
||||||
se_rsa_key_set(0, N, 0x100, D, 0x100);
|
se_rsa_key_set(0, N, 0x100, D, 0x100);
|
||||||
|
|
||||||
u32 br = buf_size;
|
u64 br = buf_size;
|
||||||
u32 file_tkey_count = 0;
|
u32 file_tkey_count = 0;
|
||||||
u64 total_br = 0;
|
u64 offset = 0;
|
||||||
rights_ids = (u8 *)(MIXD_BUF_ALIGNED + 0x40000);
|
rights_ids = (u8 *)(MIXD_BUF_ALIGNED + 0x40000);
|
||||||
titlekeys = (u8 *)(MIXD_BUF_ALIGNED + 0x80000);
|
titlekeys = (u8 *)(MIXD_BUF_ALIGNED + 0x80000);
|
||||||
save_ctx = calloc(1, sizeof(save_ctx_t));
|
save_ctx = calloc(1, sizeof(save_ctx_t));
|
||||||
|
@ -792,48 +803,52 @@ get_titlekeys:
|
||||||
u32 pct = 0, last_pct = 0;
|
u32 pct = 0, last_pct = 0;
|
||||||
|
|
||||||
save_ctx->file = &fp;
|
save_ctx->file = &fp;
|
||||||
save_ctx->tool_ctx.action = 0;
|
save_ctx->action = 0;
|
||||||
memcpy(save_ctx->save_mac_key, save_mac_key, 0x10);
|
memcpy(save_ctx->save_mac_key, save_mac_key, 0x10);
|
||||||
|
|
||||||
nx_emmc_bis_cluster_cache_init();
|
|
||||||
save_process_success = save_process(save_ctx);
|
save_process_success = save_process(save_ctx);
|
||||||
|
|
||||||
if (!save_process_success) {
|
if (!save_process_success) {
|
||||||
EPRINTF("Failed to process e1 save.");
|
EPRINTF("Failed to process e1 save.");
|
||||||
f_close(&fp);
|
f_close(&fp);
|
||||||
goto dismount;
|
goto dismount;
|
||||||
}
|
}
|
||||||
|
|
||||||
char ticket_bin_path[SAVE_FS_LIST_MAX_NAME_LENGTH] = "/ticket.bin";
|
char ticket_bin_path[0x40] = "/ticket.bin";
|
||||||
char ticket_list_bin_path[SAVE_FS_LIST_MAX_NAME_LENGTH] = "/ticket_list.bin";
|
char ticket_list_bin_path[0x40] = "/ticket_list.bin";
|
||||||
allocation_table_storage_ctx_t fat_storage;
|
save_data_file_ctx_t ticket_file;
|
||||||
save_fs_list_entry_t entry = {0, "", {0}, 0};
|
|
||||||
if (!save_hierarchical_file_table_get_file_entry_by_path(&save_ctx->save_filesystem_core.file_table, ticket_list_bin_path, &entry)) {
|
if (!save_open_file(save_ctx, &ticket_file, ticket_list_bin_path, OPEN_MODE_READ)) {
|
||||||
EPRINTF("Unable to locate ticket_list.bin in e1.");
|
EPRINTF("Unable to locate ticket_list.bin in e1.");
|
||||||
f_close(&fp);
|
f_close(&fp);
|
||||||
goto dismount;
|
goto dismount;
|
||||||
}
|
}
|
||||||
save_open_fat_storage(&save_ctx->save_filesystem_core, &fat_storage, entry.value.save_file_info.start_block);
|
|
||||||
while (br == buf_size && total_br < entry.value.save_file_info.length) {
|
while (br == buf_size && offset < ticket_file.size) {
|
||||||
br = save_allocation_table_storage_read(&fat_storage, buffer, total_br, buf_size);
|
if (!save_data_file_read(&ticket_file, &br, offset, buffer, buf_size) || buffer[0] == 0)
|
||||||
if (buffer[0] == 0) break;
|
break;
|
||||||
total_br += br;
|
offset += br;
|
||||||
minerva_periodic_training();
|
minerva_periodic_training();
|
||||||
for (u32 j = 0; j < buf_size; j += 0x20) {
|
for (u32 j = 0; j < buf_size; j += 0x20) {
|
||||||
if (buffer[j] == 0xff && buffer[j+1] == 0xff && buffer[j+2] == 0xff && buffer[j+3] == 0xff) break;
|
if (buffer[j] == 0xff && buffer[j+1] == 0xff && buffer[j+2] == 0xff && buffer[j+3] == 0xff)
|
||||||
|
break;
|
||||||
file_tkey_count++;
|
file_tkey_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!save_hierarchical_file_table_get_file_entry_by_path(&save_ctx->save_filesystem_core.file_table, ticket_bin_path, &entry)) {
|
|
||||||
|
if (!save_open_file(save_ctx, &ticket_file, ticket_bin_path, OPEN_MODE_READ)) {
|
||||||
EPRINTF("Unable to locate ticket.bin in e1 save.");
|
EPRINTF("Unable to locate ticket.bin in e1 save.");
|
||||||
f_close(&fp);
|
f_close(&fp);
|
||||||
goto dismount;
|
goto dismount;
|
||||||
}
|
}
|
||||||
save_open_fat_storage(&save_ctx->save_filesystem_core, &fat_storage, entry.value.save_file_info.start_block);
|
|
||||||
total_br = 0;
|
offset = 0;
|
||||||
while (br == buf_size && total_br < entry.value.save_file_info.length) {
|
br = buf_size;
|
||||||
br = save_allocation_table_storage_read(&fat_storage, buffer, total_br, buf_size);
|
|
||||||
if (buffer[0] == 0) break;
|
while (br == buf_size && offset < ticket_file.size) {
|
||||||
total_br += br;
|
if (!save_data_file_read(&ticket_file, &br, offset, buffer, buf_size) || buffer[0] == 0)
|
||||||
|
break;
|
||||||
|
offset += br;
|
||||||
for (u32 j = 0; j < buf_size; j += 0x400) {
|
for (u32 j = 0; j < buf_size; j += 0x400) {
|
||||||
pct = _titlekey_count * 100 / file_tkey_count;
|
pct = _titlekey_count * 100 / file_tkey_count;
|
||||||
if (pct > last_pct && pct <= 100) {
|
if (pct > last_pct && pct <= 100) {
|
||||||
|
@ -855,7 +870,6 @@ get_titlekeys:
|
||||||
save_free_contexts(save_ctx);
|
save_free_contexts(save_ctx);
|
||||||
save_process_success = false;
|
save_process_success = false;
|
||||||
memset(save_ctx, 0, sizeof(save_ctx_t));
|
memset(save_ctx, 0, sizeof(save_ctx_t));
|
||||||
memset(&fat_storage, 0, sizeof(allocation_table_storage_ctx_t));
|
|
||||||
|
|
||||||
gfx_con_setpos(0, save_y);
|
gfx_con_setpos(0, save_y);
|
||||||
TPRINTFARGS("\n%kCommon... ", colors[(color_idx++) % 6]);
|
TPRINTFARGS("\n%kCommon... ", colors[(color_idx++) % 6]);
|
||||||
|
@ -870,10 +884,9 @@ get_titlekeys:
|
||||||
}
|
}
|
||||||
|
|
||||||
save_ctx->file = &fp;
|
save_ctx->file = &fp;
|
||||||
save_ctx->tool_ctx.action = 0;
|
save_ctx->action = 0;
|
||||||
memcpy(save_ctx->save_mac_key, save_mac_key, 0x10);
|
memcpy(save_ctx->save_mac_key, save_mac_key, 0x10);
|
||||||
|
|
||||||
nx_emmc_bis_cluster_cache_init();
|
|
||||||
save_process_success = save_process(save_ctx);
|
save_process_success = save_process(save_ctx);
|
||||||
if (!save_process_success) {
|
if (!save_process_success) {
|
||||||
EPRINTF("Failed to process e2 save.");
|
EPRINTF("Failed to process e2 save.");
|
||||||
|
@ -881,40 +894,41 @@ get_titlekeys:
|
||||||
goto dismount;
|
goto dismount;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!save_hierarchical_file_table_get_file_entry_by_path(&save_ctx->save_filesystem_core.file_table, ticket_list_bin_path, &entry)) {
|
if (!save_open_file(save_ctx, &ticket_file, ticket_list_bin_path, OPEN_MODE_READ)) {
|
||||||
EPRINTF("Unable to locate ticket_list.bin in e2 save.");
|
EPRINTF("Unable to locate ticket_list.bin in e2 save.");
|
||||||
f_close(&fp);
|
f_close(&fp);
|
||||||
goto dismount;
|
goto dismount;
|
||||||
}
|
}
|
||||||
save_open_fat_storage(&save_ctx->save_filesystem_core, &fat_storage, entry.value.save_file_info.start_block);
|
|
||||||
|
|
||||||
total_br = 0;
|
offset = 0;
|
||||||
file_tkey_count = 0;
|
file_tkey_count = 0;
|
||||||
while (br == buf_size && total_br < entry.value.save_file_info.length) {
|
br = buf_size;
|
||||||
br = save_allocation_table_storage_read(&fat_storage, buffer, total_br, buf_size);
|
while (br == buf_size && offset < ticket_file.size) {
|
||||||
if (buffer[0] == 0) break;
|
if (!save_data_file_read(&ticket_file, &br, offset, buffer, buf_size) || buffer[0] == 0)
|
||||||
total_br += br;
|
break;
|
||||||
|
offset += br;
|
||||||
minerva_periodic_training();
|
minerva_periodic_training();
|
||||||
for (u32 j = 0; j < buf_size; j += 0x20) {
|
for (u32 j = 0; j < buf_size; j += 0x20) {
|
||||||
if (buffer[j] == 0xff && buffer[j+1] == 0xff && buffer[j+2] == 0xff && buffer[j+3] == 0xff) break;
|
if (buffer[j] == 0xff && buffer[j+1] == 0xff && buffer[j+2] == 0xff && buffer[j+3] == 0xff)
|
||||||
|
break;
|
||||||
file_tkey_count++;
|
file_tkey_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!save_hierarchical_file_table_get_file_entry_by_path(&save_ctx->save_filesystem_core.file_table, ticket_bin_path, &entry)) {
|
|
||||||
|
if (!save_open_file(save_ctx, &ticket_file, ticket_bin_path, OPEN_MODE_READ)) {
|
||||||
EPRINTF("Unable to locate ticket.bin in e2 save.");
|
EPRINTF("Unable to locate ticket.bin in e2 save.");
|
||||||
f_close(&fp);
|
f_close(&fp);
|
||||||
goto dismount;
|
goto dismount;
|
||||||
}
|
}
|
||||||
|
|
||||||
save_open_fat_storage(&save_ctx->save_filesystem_core, &fat_storage, entry.value.save_file_info.start_block);
|
offset = 0;
|
||||||
|
|
||||||
total_br = 0;
|
|
||||||
pct = 0;
|
pct = 0;
|
||||||
last_pct = 0;
|
last_pct = 0;
|
||||||
while (br == buf_size && total_br < entry.value.save_file_info.length) {
|
br = buf_size;
|
||||||
br = save_allocation_table_storage_read(&fat_storage, buffer, total_br, buf_size);
|
while (br == buf_size && offset < ticket_file.size) {
|
||||||
if (buffer[0] == 0) break;
|
if (!save_data_file_read(&ticket_file, &br, offset, buffer, buf_size) || buffer[0] == 0)
|
||||||
total_br += br;
|
break;
|
||||||
|
offset += br;
|
||||||
for (u32 j = 0; j < buf_size; j += 0x400) {
|
for (u32 j = 0; j < buf_size; j += 0x400) {
|
||||||
pct = (_titlekey_count - common_titlekey_count) * 100 / file_tkey_count;
|
pct = (_titlekey_count - common_titlekey_count) * 100 / file_tkey_count;
|
||||||
if (pct > last_pct && pct <= 100) {
|
if (pct > last_pct && pct <= 100) {
|
||||||
|
@ -947,7 +961,7 @@ get_titlekeys:
|
||||||
TPRINTFARGS("\n%kPersonalized... ", colors[(color_idx++) % 6]);
|
TPRINTFARGS("\n%kPersonalized... ", colors[(color_idx++) % 6]);
|
||||||
gfx_printf("\n%k Found %d titlekeys.\n", colors[(color_idx++) % 6], _titlekey_count);
|
gfx_printf("\n%k Found %d titlekeys.\n", colors[(color_idx++) % 6], _titlekey_count);
|
||||||
|
|
||||||
dismount:;
|
dismount: ;
|
||||||
if (save_process_success)
|
if (save_process_success)
|
||||||
save_free_contexts(save_ctx);
|
save_free_contexts(save_ctx);
|
||||||
|
|
||||||
|
@ -1068,9 +1082,11 @@ out_wait:
|
||||||
emummc_load_cfg();
|
emummc_load_cfg();
|
||||||
// Ignore whether emummc is enabled.
|
// Ignore whether emummc is enabled.
|
||||||
h_cfg.emummc_force_disable = emu_cfg.sector == 0 && !emu_cfg.path;
|
h_cfg.emummc_force_disable = emu_cfg.sector == 0 && !emu_cfg.path;
|
||||||
|
emu_cfg.enabled = !h_cfg.emummc_force_disable;
|
||||||
emummc_storage_end(&emmc_storage);
|
emummc_storage_end(&emmc_storage);
|
||||||
gfx_printf("\n%kPress any key to return to the main menu.", colors[(color_idx) % 6], colors[(color_idx + 1) % 6], colors[(color_idx + 2) % 6]);
|
gfx_printf("\n%kPress a button to return to the menu.", colors[(color_idx) % 6], colors[(color_idx + 1) % 6], colors[(color_idx + 2) % 6]);
|
||||||
btn_wait();
|
btn_wait();
|
||||||
|
gfx_clear_grey(0x1B);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _save_key(const char *name, const void *data, u32 len, char *outbuf) {
|
static void _save_key(const char *name, const void *data, u32 len, char *outbuf) {
|
||||||
|
|
|
@ -265,6 +265,7 @@ out:
|
||||||
void dump_sysnand()
|
void dump_sysnand()
|
||||||
{
|
{
|
||||||
h_cfg.emummc_force_disable = true;
|
h_cfg.emummc_force_disable = true;
|
||||||
|
emu_cfg.enabled = false;
|
||||||
b_cfg.extra_cfg &= ~EXTRA_CFG_DUMP_EMUMMC;
|
b_cfg.extra_cfg &= ~EXTRA_CFG_DUMP_EMUMMC;
|
||||||
dump_keys();
|
dump_keys();
|
||||||
}
|
}
|
||||||
|
@ -273,7 +274,7 @@ void dump_emunand()
|
||||||
{
|
{
|
||||||
if (h_cfg.emummc_force_disable)
|
if (h_cfg.emummc_force_disable)
|
||||||
return;
|
return;
|
||||||
emu_cfg.enabled = 1;
|
emu_cfg.enabled = true;
|
||||||
b_cfg.extra_cfg |= EXTRA_CFG_DUMP_EMUMMC;
|
b_cfg.extra_cfg |= EXTRA_CFG_DUMP_EMUMMC;
|
||||||
dump_keys();
|
dump_keys();
|
||||||
}
|
}
|
||||||
|
@ -366,11 +367,14 @@ void ipl_main()
|
||||||
emummc_load_cfg();
|
emummc_load_cfg();
|
||||||
// Ignore whether emummc is enabled.
|
// Ignore whether emummc is enabled.
|
||||||
h_cfg.emummc_force_disable = emu_cfg.sector == 0 && !emu_cfg.path;
|
h_cfg.emummc_force_disable = emu_cfg.sector == 0 && !emu_cfg.path;
|
||||||
|
emu_cfg.enabled = !h_cfg.emummc_force_disable;
|
||||||
|
|
||||||
if (b_cfg.boot_cfg & BOOT_CFG_SEPT_RUN)
|
if (b_cfg.boot_cfg & BOOT_CFG_SEPT_RUN)
|
||||||
{
|
{
|
||||||
if (!(b_cfg.extra_cfg & EXTRA_CFG_DUMP_EMUMMC))
|
if (!(b_cfg.extra_cfg & EXTRA_CFG_DUMP_EMUMMC)) {
|
||||||
h_cfg.emummc_force_disable = true;
|
h_cfg.emummc_force_disable = true;
|
||||||
|
emu_cfg.enabled = false;
|
||||||
|
}
|
||||||
dump_keys();
|
dump_keys();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -276,7 +276,7 @@ int emummc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition)
|
||||||
emu_cfg.active_part = partition;
|
emu_cfg.active_part = partition;
|
||||||
|
|
||||||
if (!emu_cfg.enabled || h_cfg.emummc_force_disable)
|
if (!emu_cfg.enabled || h_cfg.emummc_force_disable)
|
||||||
sdmmc_storage_set_mmc_partition(storage, partition);
|
return sdmmc_storage_set_mmc_partition(storage, partition);
|
||||||
else if (emu_cfg.sector)
|
else if (emu_cfg.sector)
|
||||||
return 1;
|
return 1;
|
||||||
else
|
else
|
||||||
|
|
|
@ -21,12 +21,13 @@
|
||||||
|
|
||||||
#include <memory_map.h>
|
#include <memory_map.h>
|
||||||
|
|
||||||
|
#include <mem/heap.h>
|
||||||
#include <sec/se.h>
|
#include <sec/se.h>
|
||||||
#include "../storage/nx_emmc.h"
|
#include "../storage/nx_emmc.h"
|
||||||
#include <storage/sdmmc.h>
|
#include <storage/sdmmc.h>
|
||||||
#include <utils/types.h>
|
#include <utils/types.h>
|
||||||
|
|
||||||
#define MAX_CLUSTER_CACHE_ENTRIES 128
|
#define MAX_CLUSTER_CACHE_ENTRIES 32768
|
||||||
#define CLUSTER_LOOKUP_EMPTY_ENTRY 0xFFFFFFFF
|
#define CLUSTER_LOOKUP_EMPTY_ENTRY 0xFFFFFFFF
|
||||||
#define XTS_CLUSTER_SIZE 0x4000
|
#define XTS_CLUSTER_SIZE 0x4000
|
||||||
#define SECTORS_PER_CLUSTER 0x20
|
#define SECTORS_PER_CLUSTER 0x20
|
||||||
|
@ -46,7 +47,8 @@ static u32 cluster_cache_end_index = 0;
|
||||||
static emmc_part_t *system_part = NULL;
|
static emmc_part_t *system_part = NULL;
|
||||||
static u8 *emmc_buffer = (u8 *)NX_BIS_CACHE_ADDR;
|
static u8 *emmc_buffer = (u8 *)NX_BIS_CACHE_ADDR;
|
||||||
static cluster_cache_t *cluster_cache = (cluster_cache_t *)(NX_BIS_CACHE_ADDR + XTS_CLUSTER_SIZE);
|
static cluster_cache_t *cluster_cache = (cluster_cache_t *)(NX_BIS_CACHE_ADDR + XTS_CLUSTER_SIZE);
|
||||||
static u32 *cluster_lookup = (u32 *)(NX_BIS_CACHE_ADDR + XTS_CLUSTER_SIZE + MAX_CLUSTER_CACHE_ENTRIES * sizeof(cluster_cache_t));
|
static u32 *cluster_lookup_buf = NULL;
|
||||||
|
static u32 *cluster_lookup = NULL;
|
||||||
static bool lock_cluster_cache = false;
|
static bool lock_cluster_cache = false;
|
||||||
|
|
||||||
static void _gf256_mul_x_le(void *block)
|
static void _gf256_mul_x_le(void *block)
|
||||||
|
@ -125,6 +127,7 @@ static int nx_emmc_bis_read_block(u32 sector, u32 count, void *buff)
|
||||||
static u32 prev_cluster = -1;
|
static u32 prev_cluster = -1;
|
||||||
static u32 prev_sector = 0;
|
static u32 prev_sector = 0;
|
||||||
static u8 tweak[0x10];
|
static u8 tweak[0x10];
|
||||||
|
u8 cache_tweak[0x10];
|
||||||
|
|
||||||
u32 tweak_exp = 0;
|
u32 tweak_exp = 0;
|
||||||
bool regen_tweak = true;
|
bool regen_tweak = true;
|
||||||
|
@ -144,10 +147,8 @@ static int nx_emmc_bis_read_block(u32 sector, u32 count, void *buff)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only cache single-sector reads as these are most likely to be repeated, such as boot block and FAT directory tables.
|
// Only cache single-sector reads as these are most likely to be repeated, such as boot block and FAT directory tables.
|
||||||
if (count == 1 &&
|
if (!lock_cluster_cache &&
|
||||||
!lock_cluster_cache &&
|
cluster_cache_end_index < MAX_CLUSTER_CACHE_ENTRIES)
|
||||||
cluster_cache_end_index < MAX_CLUSTER_CACHE_ENTRIES &&
|
|
||||||
cluster_lookup_index == CLUSTER_LOOKUP_EMPTY_ENTRY)
|
|
||||||
{
|
{
|
||||||
cluster_cache[cluster_cache_end_index].cluster_num = cluster;
|
cluster_cache[cluster_cache_end_index].cluster_num = cluster;
|
||||||
cluster_cache[cluster_cache_end_index].visit_count = 1;
|
cluster_cache[cluster_cache_end_index].visit_count = 1;
|
||||||
|
@ -157,14 +158,12 @@ static int nx_emmc_bis_read_block(u32 sector, u32 count, void *buff)
|
||||||
// Read and decrypt the whole cluster the sector resides in.
|
// Read and decrypt the whole cluster the sector resides in.
|
||||||
if (!nx_emmc_part_read(&emmc_storage, system_part, aligned_sector, SECTORS_PER_CLUSTER, emmc_buffer))
|
if (!nx_emmc_part_read(&emmc_storage, system_part, aligned_sector, SECTORS_PER_CLUSTER, emmc_buffer))
|
||||||
return 1; // R/W error.
|
return 1; // R/W error.
|
||||||
if (!_nx_aes_xts_crypt_sec(ks_tweak, ks_crypt, 0, tweak, true, 0, cluster, emmc_buffer, emmc_buffer, XTS_CLUSTER_SIZE))
|
if (!_nx_aes_xts_crypt_sec(ks_tweak, ks_crypt, 0, cache_tweak, true, 0, cluster, emmc_buffer, emmc_buffer, XTS_CLUSTER_SIZE))
|
||||||
return 1; // R/W error.
|
return 1; // R/W error.
|
||||||
|
|
||||||
// Copy to cluster cache.
|
// Copy to cluster cache.
|
||||||
memcpy(cluster_cache[cluster_cache_end_index].cluster, emmc_buffer, XTS_CLUSTER_SIZE);
|
memcpy(cluster_cache[cluster_cache_end_index].cluster, emmc_buffer, XTS_CLUSTER_SIZE);
|
||||||
memcpy(buff, emmc_buffer + sector_index_in_cluster * NX_EMMC_BLOCKSIZE, NX_EMMC_BLOCKSIZE);
|
memcpy(buff, emmc_buffer + sector_index_in_cluster * NX_EMMC_BLOCKSIZE, NX_EMMC_BLOCKSIZE * count);
|
||||||
prev_cluster = -1;
|
|
||||||
prev_sector = 0;
|
|
||||||
cluster_cache_end_index++;
|
cluster_cache_end_index++;
|
||||||
return 0; // Success.
|
return 0; // Success.
|
||||||
}
|
}
|
||||||
|
@ -218,8 +217,26 @@ int nx_emmc_bis_read(u32 sector, u32 count, void *buff)
|
||||||
|
|
||||||
void nx_emmc_bis_cluster_cache_init()
|
void nx_emmc_bis_cluster_cache_init()
|
||||||
{
|
{
|
||||||
|
u32 cluster_lookup_size = (system_part->lba_end - system_part->lba_start + 1) / SECTORS_PER_CLUSTER * sizeof(*cluster_lookup);
|
||||||
|
|
||||||
|
if (cluster_lookup_buf)
|
||||||
|
free(cluster_lookup_buf);
|
||||||
|
|
||||||
|
// Check if carveout protected, in case of old hwinit (pre 4.0.0) chainload.
|
||||||
|
*(vu32 *)NX_BIS_LOOKUP_ADR = 0;
|
||||||
|
if (*(vu32 *)NX_BIS_LOOKUP_ADR != 0)
|
||||||
|
{
|
||||||
|
cluster_lookup_buf = (u32 *)malloc(cluster_lookup_size + 0x2000);
|
||||||
|
cluster_lookup = (u32 *)ALIGN((u32)cluster_lookup_buf, 0x1000);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cluster_lookup_buf = NULL;
|
||||||
|
cluster_lookup = (u32 *)NX_BIS_LOOKUP_ADR;
|
||||||
|
}
|
||||||
|
|
||||||
// Clear cluster lookup table and reset end index.
|
// Clear cluster lookup table and reset end index.
|
||||||
memset(cluster_lookup, -1, (system_part->lba_end - system_part->lba_start + 1) / SECTORS_PER_CLUSTER * sizeof(*cluster_lookup));
|
memset(cluster_lookup, -1, cluster_lookup_size);
|
||||||
cluster_cache_end_index = 0;
|
cluster_cache_end_index = 0;
|
||||||
lock_cluster_cache = false;
|
lock_cluster_cache = false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue