Add emmc mounting, Add waitmenu()

This commit is contained in:
Such Meme, Many Skill
2019-12-11 13:18:57 +01:00
parent e837e2e6ed
commit ae225abb75
17 changed files with 347 additions and 2725 deletions

201
source/tegraexplorer/emmc.c Normal file
View File

@@ -0,0 +1,201 @@
#include <string.h>
#include "../mem/heap.h"
#include "gfx.h"
#include "fs.h"
#include "emmc.h"
#include "../utils/types.h"
#include "../libs/fatfs/ff.h"
#include "../utils/sprintf.h"
#include "../utils/btn.h"
#include "../gfx/gfx.h"
#include "../utils/util.h"
#include "../hos/pkg1.h"
#include "../storage/sdmmc.h"
#include "../storage/nx_emmc.h"
#include "../sec/tsec.h"
#include "../soc/t210.h"
#include "../soc/fuse.h"
#include "../mem/mc.h"
#include "../sec/se.h"
#include "../soc/hw_init.h"
#include "../mem/emc.h"
#include "../mem/sdram.h"
sdmmc_storage_t storage;
emmc_part_t *system_part;
sdmmc_t sdmmc;
__attribute__ ((aligned (16))) FATFS emmc;
LIST_INIT(gpt);
u8 bis_key[4][32];
short pkg1ver;
static bool _key_exists(const void *data) { return memcmp(data, zeros, 0x10); };
static void _generate_kek(u32 ks, const void *key_source, void *master_key, const void *kek_seed, const void *key_seed) {
if (!_key_exists(key_source) || !_key_exists(master_key) || !_key_exists(kek_seed))
return;
se_aes_key_set(ks, master_key, 0x10);
se_aes_unwrap_key(ks, ks, kek_seed);
se_aes_unwrap_key(ks, ks, key_source);
if (key_seed && _key_exists(key_seed))
se_aes_unwrap_key(ks, ks, key_seed);
}
void print_biskeys(){
gfx_printf("\n");
gfx_hexdump(0, bis_key[0], 32);
gfx_hexdump(0, bis_key[1], 32);
gfx_hexdump(0, bis_key[2], 32);
}
int mount_emmc(char *partition, int biskeynumb){
f_unmount("emmc:");
se_aes_key_set(8, bis_key[biskeynumb] + 0x00, 0x10);
se_aes_key_set(9, bis_key[biskeynumb] + 0x10, 0x10);
system_part = nx_emmc_part_find(&gpt, partition);
if (!system_part) {
gfx_printf("Failed to locate %s partition.", partition);
return -1;
}
if (f_mount(&emmc, "emmc:", 1)) {
gfx_printf("Mount failed of %s.", partition);
return -1;
}
return 0;
}
int dump_biskeys(){
u8 temp_key[0x10], device_key[0x10] = {0};
tsec_ctxt_t tsec_ctxt;
int retries = 0;
sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4);
// Read package1.
u8 *pkg1 = (u8 *)malloc(0x40000);
sdmmc_storage_set_mmc_partition(&storage, 1);
sdmmc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1);
if (!pkg1_id) {
EPRINTF("Unknown pkg1 version.");
return -1;
}
bool found_tsec_fw = false;
for (const u32 *pos = (const u32 *)pkg1; (u8 *)pos < pkg1 + 0x40000; pos += 0x100 / sizeof(u32)) {
if (*pos == 0xCF42004D) {
tsec_ctxt.fw = (u8 *)pos;
found_tsec_fw = true;
break;
}
}
if (!found_tsec_fw) {
EPRINTF("Failed to locate TSEC firmware.");
return -1;
}
u8 tsec_keys[0x10] = {0};
tsec_key_data_t *key_data = (tsec_key_data_t *)(tsec_ctxt.fw + TSEC_KEY_DATA_ADDR);
tsec_ctxt.pkg1 = pkg1;
tsec_ctxt.size = 0x100 + key_data->blob0_size + key_data->blob1_size + key_data->blob2_size + key_data->blob3_size + key_data->blob4_size;
if (pkg1_id->kb >= KB_FIRMWARE_VERSION_700) {
// Exit after TSEC key generation.
*((vu16 *)((u32)tsec_ctxt.fw + 0x2DB5)) = 0x02F8;
}
int res = 0;
mc_disable_ahb_redirect();
while (tsec_query(tsec_keys, 0, &tsec_ctxt) < 0) {
memset(tsec_keys, 0x00, 0x10);
retries++;
if (retries > 15) {
res = -1;
break;
}
}
free(pkg1);
mc_enable_ahb_redirect();
if (res < 0) {
gfx_printf("ERROR %x dumping TSEC.\n", res);
return -1;
}
u32 sbk[4] = {FUSE(FUSE_PRIVATE_KEY0), FUSE(FUSE_PRIVATE_KEY1),
FUSE(FUSE_PRIVATE_KEY2), FUSE(FUSE_PRIVATE_KEY3)};
se_aes_key_set(8, tsec_keys, 0x10);
se_aes_key_set(9, sbk, 0x10);
se_aes_crypt_block_ecb(8, 0, temp_key, keyblob_key_source);
se_aes_crypt_block_ecb(9, 0, temp_key, temp_key);
se_aes_key_set(7, temp_key, 0x10);
se_aes_crypt_block_ecb(7, 0, device_key, per_console_key_source);
/* key = unwrap(source, wrapped_key):
key_set(ks, wrapped_key), block_ecb(ks, 0, key, source) -> final key in key
*/
if (_key_exists(device_key)) {
se_aes_key_set(8, device_key, 0x10);
se_aes_unwrap_key(8, 8, retail_specific_aes_key_source); // kek = unwrap(rsaks, devkey)
se_aes_crypt_block_ecb(8, 0, bis_key[0] + 0x00, bis_key_source[0] + 0x00); // bkey = unwrap(bkeys, kek)
se_aes_crypt_block_ecb(8, 0, bis_key[0] + 0x10, bis_key_source[0] + 0x10);
// kek = generate_kek(bkeks, devkey, aeskek, aeskey)
_generate_kek(8, bis_kek_source, device_key, aes_kek_generation_source, aes_key_generation_source);
se_aes_crypt_block_ecb(8, 0, bis_key[1] + 0x00, bis_key_source[1] + 0x00); // bkey = unwrap(bkeys, kek)
se_aes_crypt_block_ecb(8, 0, bis_key[1] + 0x10, bis_key_source[1] + 0x10);
se_aes_crypt_block_ecb(8, 0, bis_key[2] + 0x00, bis_key_source[2] + 0x00);
se_aes_crypt_block_ecb(8, 0, bis_key[2] + 0x10, bis_key_source[2] + 0x10);
memcpy(bis_key[3], bis_key[2], 0x20);
}
sdmmc_storage_set_mmc_partition(&storage, 0);
// Parse eMMC GPT.
nx_emmc_gpt_parse(&gpt, &storage);
/*
char part_name[37] = "SYSTEM";
// todo: menu selection for this
u32 bis_key_index = 0;
if (strcmp(part_name, "PRODINFOF") == 0)
bis_key_index = 0;
else if (strcmp(part_name, "SAFE") == 0)
bis_key_index = 1;
else if (strcmp(part_name, "SYSTEM") == 0)
bis_key_index = 2;
else if (strcmp(part_name, "USER") == 0)
bis_key_index = 3;
else {
gfx_printf("Partition name %s unrecognized.", part_name);
return;
}
*/
se_aes_key_set(8, bis_key[2] + 0x00, 0x10);
se_aes_key_set(9, bis_key[2] + 0x10, 0x10);
/*
system_part = nx_emmc_part_find(&gpt, "SYSTEM");
if (!system_part) {
gfx_printf("Failed to locate SYSTEM partition.");
return -1;
}
if (f_mount(&emmc_sys, "system:", 1)) {
gfx_printf("Mount failed of SYSTEM.");
return -1;
}
*/
pkg1ver = pkg1_id->kb;
return 0;
}

View File

@@ -0,0 +1,41 @@
#pragma once
//int mount_emmc_partition(const char *part, int logicnumb);
int dump_biskeys();
void print_biskeys();
int mount_emmc(char *partition, int biskeynumb);
static const u8 zeros[0x10] = {0};
static const u8 keyblob_key_source[0x10] = {
0xDF, 0x20, 0x6F, 0x59, 0x44, 0x54, 0xEF, 0xDC, 0x70, 0x74, 0x48, 0x3B, 0x0D, 0xED, 0x9F, 0xD3};
//======================================Keys======================================//
// from Package1 -> Secure_Monitor
static const u8 aes_kek_generation_source[0x10] = {
0x4D, 0x87, 0x09, 0x86, 0xC4, 0x5D, 0x20, 0x72, 0x2F, 0xBA, 0x10, 0x53, 0xDA, 0x92, 0xE8, 0xA9};
static const u8 retail_specific_aes_key_source[0x10] = {
0xE2, 0xD6, 0xB8, 0x7A, 0x11, 0x9C, 0xB8, 0x80, 0xE8, 0x22, 0x88, 0x8A, 0x46, 0xFB, 0xA1, 0x95};
// from Package1ldr (or Secure_Monitor on 6.2.0)
static const u8 per_console_key_source[0x10] = {
0x4F, 0x02, 0x5F, 0x0E, 0xB6, 0x6D, 0x11, 0x0E, 0xDC, 0x32, 0x7D, 0x41, 0x86, 0xC2, 0xF4, 0x78};
// from SPL
static const u8 aes_key_generation_source[0x10] = {
0x89, 0x61, 0x5E, 0xE0, 0x5C, 0x31, 0xB6, 0x80, 0x5F, 0xE5, 0x8F, 0x3D, 0xA2, 0x4F, 0x7A, 0xA8};
// from FS
static const u8 bis_kek_source[0x10] = {
0x34, 0xC1, 0xA0, 0xC4, 0x82, 0x58, 0xF8, 0xB4, 0xFA, 0x9E, 0x5E, 0x6A, 0xDA, 0xFC, 0x7E, 0x4F};
static const u8 bis_key_source[3][0x20] = {
{
0xF8, 0x3F, 0x38, 0x6E, 0x2C, 0xD2, 0xCA, 0x32, 0xA8, 0x9A, 0xB9, 0xAA, 0x29, 0xBF, 0xC7, 0x48,
0x7D, 0x92, 0xB0, 0x3A, 0xA8, 0xBF, 0xDE, 0xE1, 0xA7, 0x4C, 0x3B, 0x6E, 0x35, 0xCB, 0x71, 0x06},
{
0x41, 0x00, 0x30, 0x49, 0xDD, 0xCC, 0xC0, 0x65, 0x64, 0x7A, 0x7E, 0xB4, 0x1E, 0xED, 0x9C, 0x5F,
0x44, 0x42, 0x4E, 0xDA, 0xB4, 0x9D, 0xFC, 0xD9, 0x87, 0x77, 0x24, 0x9A, 0xDC, 0x9F, 0x7C, 0xA4},
{
0x52, 0xC2, 0xE9, 0xEB, 0x09, 0xE3, 0xEE, 0x29, 0x32, 0xA1, 0x0C, 0x1F, 0xB6, 0xA0, 0x92, 0x6C,
0x4D, 0x12, 0xE1, 0x4B, 0x2A, 0x47, 0x4C, 0x1C, 0x09, 0xCB, 0x03, 0x59, 0xF0, 0x15, 0xF4, 0xE4}
};

View File

@@ -221,7 +221,10 @@ void copyfile(const char *path, const char *outfolder){
gfx_printf("Note:\nTo stop the transfer hold Vol-\n\n%s\nProgress: ", outstring);
if (clipboardhelper & OPERATIONMOVE){
f_rename(path, outstring);
if (strcmp(rootpath, "emmc:/"))
f_rename(path, outstring);
else
message("\nMoving in emummc is not allowed!", COLOR_RED);
}
else if (clipboardhelper & OPERATIONCOPY) {
@@ -301,30 +304,17 @@ int readfolder(const char *path){
}
int delfile(const char *path, const char *filename){
clearscreen();
int res;
int amount = -1;
u32 start = get_tmr_s();
char *tempmessage;
size_t tempmessagesize = strlen(filename) + 65;
tempmessage = (char*) malloc (tempmessagesize);
gfx_printf("Are you sure you want to delete:\n%s\n\nPress vol+/- to cancel\n", filename);
while(1){
res = btn_read();
if (res & BTN_VOL_UP || res & BTN_VOL_DOWN)
break;
if (start + 3 > get_tmr_s()){
gfx_printf("\r<Wait %d seconds>", 3 + start - get_tmr_s());
}
else if (res & BTN_POWER){
f_unlink(path);
amount = readfolder(currentpath);
break;
}
else {
gfx_printf("\r%kPress power to delete%k", COLOR_RED, COLOR_WHITE);
}
sprintf(tempmessage, "Are you sure you want to delete:\n%s\n\nPress vol+/- to cancel\n", filename);
if (makewaitmenu(tempmessage, "Press power to delete", 3)){
f_unlink(path);
return readfolder(currentpath);
}
return amount;
else
return -1;
}
void filemenu(const char *startpath){
@@ -334,6 +324,11 @@ void filemenu(const char *startpath){
writecurpath(startpath);
amount = readfolder(currentpath);
if (strcmp(rootpath, "emmc:/"))
explfilemenu[5].property = 1;
else
explfilemenu[5].property = -1;
while (1){
res = makefilemenu(fileobjects, amount, currentpath);
if (res < 1){

View File

@@ -12,7 +12,7 @@
const char fixedoptions[3][50] = {
"Folder -> previous folder ",
"Clipboard -> Current folder ",
"Folder options "
"Return to main menu "
};
const char sizevalues[4][3] = {
@@ -85,6 +85,30 @@ void printbytes(u8 print[], u32 size, u32 offset){
gfx_hexdump(offset, print, size * sizeof(u8));
}
int makewaitmenu(char *initialmessage, char *hiddenmessage, int timer){
clearscreen();
int res;
u32 start = get_tmr_s();
gfx_printf(initialmessage);
while(1){
res = btn_read();
if (res & BTN_VOL_DOWN || res & BTN_VOL_UP)
return 0;
if (start + timer > get_tmr_s())
gfx_printf("\r<Wait %d seconds>", timer + start - get_tmr_s());
else if (res & BTN_POWER)
return 1;
else
gfx_printf("\r%k%s%k", COLOR_RED, hiddenmessage, COLOR_WHITE);
}
}
void printfsentry(fs_entry file, bool highlight, bool refresh){
int size = 0;
char *display;

View File

@@ -6,4 +6,5 @@ int makemenu(menu_item menu[], int menuamount);
int message(char* message, u32 color);
void clearscreen();
int makefilemenu(fs_entry *files, int amount, char *path);
void printbytes(u8 print[], u32 size, u32 offset);
void printbytes(u8 print[], u32 size, u32 offset);
int makewaitmenu(char *initialmessage, char *hiddenmessage, int timer);

View File

@@ -5,6 +5,8 @@
#include "../utils/util.h"
#include "tools.h"
#include "fs.h"
#include "../utils/btn.h"
#include "emmc.h"
extern bool sd_mount();
extern void sd_unmount();
@@ -13,9 +15,10 @@ bool sd_mounted;
menu_item mainmenu[MAINMENU_AMOUNT] = {
{"[SD:/] SD CARD", COLOR_GREEN, SD_CARD, 1},
{"[EMMC:/] ?", COLOR_GREEN, EMMC, 1},
{"[SYSTEM:/] EMMC", COLOR_GREEN, EMMC_SYS, 1},
{"\nMount/Unmount SD", COLOR_WHITE, MOUNT_SD, 1},
{"Tools", COLOR_VIOLET, TOOLS, 1},
{"SD format", COLOR_VIOLET, SD_FORMAT, 1},
{"\nCredits", COLOR_WHITE, CREDITS, 1},
{"Exit", COLOR_WHITE, EXIT, 1}
};
@@ -59,6 +62,12 @@ void fillmainmenu(){
strcpy(mainmenu[i].name, "\nMount SD");
}
break;
case 5:
if (sd_mounted)
mainmenu[i].property = 1;
else
mainmenu[i].property = -1;
break;
}
}
}
@@ -66,6 +75,9 @@ void fillmainmenu(){
void te_main(){
int res;
dump_biskeys();
mount_emmc("SYSTEM", 2);
sd_mounted = sd_mount();
while (1){
@@ -76,8 +88,16 @@ void te_main(){
case SD_CARD:
filemenu("SD:/");
break;
case EMMC:
case EMMC_SYS:
if (makewaitmenu("You're about to enter EMMC\nModifying anything here\n can result in a BRICK!\n\nPlease only continue\n if you know what you're doing\n\nPress Vol+/- to return\n", "Press Power to enter", 4))
filemenu("emmc:/");
break;
/*
case EMMC_USR:
mount_emmc("USER", 2);
filemenu("emmc:/");
break;
*/
case MOUNT_SD:
if (sd_mounted){
sd_mounted = false;

View File

@@ -1,7 +1,7 @@
#pragma once
#include "../utils/types.h"
#define MAINMENU_AMOUNT 6
#define MAINMENU_AMOUNT 7
#define CREDITS_MESSAGE "\nTegraexplorer, made by:\nSuch Meme, Many Skill\n\nProject based on:\nLockpick_RCM\nHekate\n\nCool people:\nshchmue\ndennthecafebabe\nDax"
typedef struct _menu_item {
@@ -13,9 +13,11 @@ typedef struct _menu_item {
enum mainmenu_return {
SD_CARD = 1,
EMMC,
EMMC_SYS,
EMMC_USR,
MOUNT_SD,
TOOLS,
SD_FORMAT,
CREDITS,
EXIT
};

View File

@@ -8,6 +8,7 @@
#include "../utils/types.h"
#include "../libs/fatfs/diskio.h"
#include "../storage/sdmmc.h"
#include "emmc.h"
extern bool sd_mount();
extern void sd_unmount();
@@ -16,31 +17,34 @@ extern sdmmc_storage_t sd_storage;
void displayinfo(){
clearscreen();
FATFS *fs;
DWORD fre_clust, fre_sect, tot_sect, temp_sect, sz_disk;
s64 capacity;
DWORD fre_clust, fre_sect, tot_sect;
u32 capacity;
int res;
gfx_printf("Getting storage info: please wait...");
gfx_printf("Biskeys:\n");
print_biskeys();
res = f_getfree("sd:", &fre_clust, &fs);
gfx_printf("\nResult getfree: %d\n\n", res);
if (!sd_mount()){
gfx_printf("SD mount failed!\nFailed to display SD info\n");
}
else {
gfx_printf("Getting storage info: please wait...");
tot_sect = (fs->n_fatent - 2) * fs->csize;
fre_sect = fre_clust * fs->csize;
res = f_getfree("sd:", &fre_clust, &fs);
gfx_printf("\nResult getfree: %d\n\n", res);
gfx_printf("%d KiB total\n%d KiB free\n\nPress any key to continue\n", tot_sect / 2, fre_sect / 2);
tot_sect = (fs->n_fatent - 2) * fs->csize;
fre_sect = fre_clust * fs->csize;
capacity = sd_storage.csd.capacity;
temp_sect = tot_sect;
temp_sect -= 61145088;
gfx_printf("\n%k1st part: %d\n2nd part: 61145088\n\n%k", COLOR_RED, temp_sect, COLOR_WHITE);
capacity = sd_storage.csd.capacity;
capacity -= 61145088;
gfx_printf("\n%k1st part: %d\n2nd part: 61145088\n\n%k", COLOR_RED, capacity, COLOR_WHITE);
gfx_printf("Entire sd:\nSectors: %d\nSpace total: %d MB\n\n", capacity, capacity / 2048);
gfx_printf("First partition on SD:\nSectors: %d\nSpace total: %d MB\nSpace free: %d MB\n\n", tot_sect, tot_sect / 2048, fre_sect / 2048);
}
gfx_printf("Press any key to continue");
btn_wait();
}
@@ -76,7 +80,7 @@ void format(){
DWORD clustsize = 16 * 512;
BYTE formatoptions = 0;
formatoptions |= (FM_FAT32);
formatoptions |= (FM_SFD);
//formatoptions |= (FM_SFD);
timer = get_tmr_s();