Compare commits

...

12 Commits

Author SHA1 Message Date
suchmememanyskill
5adb95095e create some helper functions in gfx.c 2020-08-04 01:16:50 +02:00
suchmememanyskill
0146f0ddb0 Bump version 2020-08-03 13:10:02 +02:00
SuchMemeManySkill
b42b52eb43 Include a (bad) method to dump with .cnmt.nca 2020-07-14 17:38:56 +02:00
Such Meme, Many Skill
81cf8c201c Fix a few bugs in the arg parser 2020-05-29 00:07:19 +02:00
Such Meme, Many Skill
34abed91a9 Bump version 2020-05-28 23:26:01 +02:00
suchmememanyskill
0382a17f87 Add fancy badges to readme 2020-05-28 23:14:16 +02:00
suchmememanyskill
d44178a863 Update README.md 2020-05-23 22:43:35 +02:00
Such Meme, Many Skill
abf814686d Change menu around a bit 2020-05-20 02:28:43 +02:00
Such Meme, Many Skill
f8394ae323 Merge branch 'Script_Fuckery' 2020-05-20 00:20:02 +02:00
Such Meme, Many Skill
fc69dc36ee Merge lockpickrcm changes 2020-05-19 18:20:19 +02:00
Such Meme, Many Skill
f61fcfea32 Empty strings should be valid 2020-05-17 01:04:33 +02:00
Such Meme, Many Skill
a872b90597 Change arg parser, add some commands, may break shit 2020-05-17 00:46:53 +02:00
41 changed files with 1078 additions and 291 deletions

View File

@@ -8,10 +8,10 @@ include $(DEVKITARM)/base_rules
################################################################################ ################################################################################
IPL_LOAD_ADDR := 0x40008000 IPL_LOAD_ADDR := 0x40003000
LPVERSION_MAJOR := 3 LPVERSION_MAJOR := 3
LPVERSION_MINOR := 0 LPVERSION_MINOR := 0
LPVERSION_BUGFX := 2 LPVERSION_BUGFX := 4
################################################################################ ################################################################################

View File

@@ -1,24 +1,28 @@
# TegraExplorer # TegraExplorer
A payload-based file explorer for your switch!
![TegraExplorer builder](https://github.com/suchmememanyskill/TegraExplorer/workflows/TegraExplorer%20builder/badge.svg) [![TegraExplorer builder](https://github.com/suchmememanyskill/TegraExplorer/workflows/TegraExplorer%20builder/badge.svg)](https://github.com/suchmememanyskill/TegraExplorer/actions)
[![Downloads](https://img.shields.io/github/downloads/suchmememanyskill/TegraExplorer/total)](https://github.com/suchmememanyskill/TegraExplorer/releases)
[![Version](https://img.shields.io/github/v/release/suchmememanyskill/tegraexplorer)](https://github.com/suchmememanyskill/TegraExplorer/releases)
[![Donations](https://img.shields.io/badge/Support%20on-Ko--Fi-red)](https://ko-fi.com/suchmememanyskill)
A payload-based file explorer for your switch!
## Usage ## Usage
1. Get your favorite payload injector 1. Get your favorite payload injector
2. Inject TegraExplorer as a payload 2. Inject TegraExplorer as a payload
Navigate around the menus using the joycons. Navigate around the menus using the joycons.
A: Select - A: Select
B: Back - B: Back
Left Joystick up/down (Dpad or joystick): navigate menus up/down - Left Joystick up/down (Dpad or joystick): navigate menus up/down
Right Joystick up/down: fast menu navigation up/down - Right Joystick up/down: fast menu navigation up/down
Capture (Minerva only): Take a screenshot - Capture (Minerva only): Take a screenshot
L3/R3 (Press joysticks in): Recalibrate centerpoint - L3/R3 (Press joysticks in): Recalibrate centerpoint
If you do not have your joycons connected: If you do not have your joycons connected:
Power -> A - Power -> A
Vol+ -> Left Joystick up - Vol+ -> Left Joystick up
Vol- -> Left Joystick down - Vol- -> Left Joystick down
## Functions ## Functions
- Navigate the SD card - Navigate the SD card
@@ -56,7 +60,8 @@ Other awesome people:
- Huhen - Huhen
- Bleck9999 - Bleck9999
- Exelix - Exelix
- Emmo
## Screenshots ## Screenshots
![Preview](/preview.png) ![Preview](/preview.png)

View File

@@ -1,9 +1,9 @@
/* /*
* Common Gfx Header * Common Gfx Header
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer * Copyright (C) 2018 CTCaer
* Copyright (c) 2018 M4xw * Copyright (C) 2018 M4xw
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation. * version 2, as published by the Free Software Foundation.

View File

@@ -1,6 +1,6 @@
/* /*
* Common Module Header * Common Module Header
* Copyright (c) 2018 M4xw * Copyright (C) 2018 M4xw
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,

View File

@@ -19,8 +19,8 @@
//#define IPL_STACK_TOP 0x4003FF00 //#define IPL_STACK_TOP 0x4003FF00
/* --- BIT/BCT: 0x40000000 - 0x40003000 --- */ /* --- BIT/BCT: 0x40000000 - 0x40003000 --- */
/* --- IPL: 0x40008000 - 0x40028000 --- */ /* --- IPL: 0x40003000 - 0x40028000 --- */
#define IPL_LOAD_ADDR 0x40008000 #define IPL_LOAD_ADDR 0x40003000
#define IPL_SZ_MAX 0x20000 // 128KB. #define IPL_SZ_MAX 0x20000 // 128KB.
//#define IRAM_LIB_ADDR 0x4002B000 //#define IRAM_LIB_ADDR 0x4002B000
#define SDRAM_PARAMS_ADDR 0x40030000 // SDRAM extraction buffer during sdram init. #define SDRAM_PARAMS_ADDR 0x40030000 // SDRAM extraction buffer during sdram init.

View File

@@ -180,6 +180,8 @@ void gfx_con_setpos(u32 x, u32 y)
gfx_con.y = YLEFT - x; gfx_con.y = YLEFT - x;
} }
u32 YLeftConfig = YLEFT;
void gfx_putc(char c) void gfx_putc(char c)
{ {
// Duplicate code for performance reasons. // Duplicate code for performance reasons.
@@ -231,13 +233,13 @@ void gfx_putc(char c)
*/ */
gfx_con.y -= 16; gfx_con.y -= 16;
if (gfx_con.y < 16){ if (gfx_con.y < 16){
gfx_con.y = YLEFT; gfx_con.y = YLeftConfig;
gfx_con.x += 16; gfx_con.x += 16;
} }
} }
else if (c == '\n') else if (c == '\n')
{ {
gfx_con.y = YLEFT; gfx_con.y = YLeftConfig;
gfx_con.x += 16; gfx_con.x += 16;
if (gfx_con.x > gfx_ctxt.width - 16) if (gfx_con.x > gfx_ctxt.width - 16)
gfx_con.x = 0; gfx_con.x = 0;
@@ -247,7 +249,7 @@ void gfx_putc(char c)
else if (c == '\a') else if (c == '\a')
gfx_con.y = 639; gfx_con.y = 639;
else if (c == '\r') else if (c == '\r')
gfx_con.y = YLEFT; gfx_con.y = YLeftConfig;
break; break;
case 8: case 8:
@@ -273,14 +275,14 @@ void gfx_putc(char c)
gfx_con.y -= 8; gfx_con.y -= 8;
if (gfx_con.y < 8){ if (gfx_con.y < 8){
gfx_con.y = YLEFT; gfx_con.y = YLeftConfig;
gfx_con.x += 8; gfx_con.x += 8;
} }
} }
else if (c == '\n') else if (c == '\n')
{ {
gfx_con.y = YLEFT; gfx_con.y = YLeftConfig;
gfx_con.x += 8; gfx_con.x += 8;
if (gfx_con.x > gfx_ctxt.width - 8) if (gfx_con.x > gfx_ctxt.width - 8)
gfx_con.x = 0; gfx_con.x = 0;
@@ -290,7 +292,7 @@ void gfx_putc(char c)
else if (c == '\a') else if (c == '\a')
gfx_con.y = 639; gfx_con.y = 639;
else if (c == '\r') else if (c == '\r')
gfx_con.y = YLEFT; gfx_con.y = YLeftConfig;
break; break;
} }
@@ -305,6 +307,46 @@ void gfx_puts(const char *s)
gfx_putc(*s); gfx_putc(*s);
} }
u32 _strLenLimit(const char *s, u32 limit){
u32 len = 0;
for (; *s; s++){
len++;
if (len >= limit)
return len;
}
return len;
}
void gfx_puts_limit(const char *s, u32 limit)
{
if (!s || gfx_con.mute)
return;
for (u32 i = 0; i < limit; i++){
if (i == limit - 3){
if (_strLenLimit(&s[i], 4) >= 4){
gfx_puts("...");
return;
}
}
gfx_putc(s[i]);
}
/*
for (u32 i = 0; *s && i < limit; s++, i++){
if (i == limit - 3){
if (!(!(*s) || !(*(s + 1)) || !(*(s + 2)))){
gfx_puts("...");
return;
}
}
gfx_putc(*s);
}
*/
}
static void _gfx_putn(u32 v, int base, char fill, int fcnt) static void _gfx_putn(u32 v, int base, char fill, int fcnt)
{ {
char buf[65]; char buf[65];
@@ -381,6 +423,11 @@ void gfx_vprintf(const char *fmt, va_list ap)
} }
switch(*fmt) switch(*fmt)
{ {
case 'b':;
u32 begin = YLEFT - va_arg(ap, u32);
YLeftConfig = begin;
gfx_con.y = begin;
break;
case 'c': case 'c':
gfx_putc(va_arg(ap, u32)); gfx_putc(va_arg(ap, u32));
break; break;

View File

@@ -53,6 +53,7 @@ void gfx_set_rect_argb(const u32 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 po
void gfx_render_bmp_argb(const u32 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y); void gfx_render_bmp_argb(const u32 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y);
void gfx_box(int x0, int y0, int x1, int y1, u32 color); void gfx_box(int x0, int y0, int x1, int y1, u32 color);
void gfx_boxGrey(int x0, int y0, int x1, int y1, u8 shade); void gfx_boxGrey(int x0, int y0, int x1, int y1, u8 shade);
void gfx_puts_limit(const char *s, u32 limit);
/* /*
#define GFX_SETPOSCORRECTED(x, y) gfx_con_setpos(y - YLEFT, x) #define GFX_SETPOSCORRECTED(x, y) gfx_con_setpos(y - YLEFT, x)

220
source/hos/fss.c Normal file
View File

@@ -0,0 +1,220 @@
/*
* Atmosphère Fusée Secondary Storage parser.
*
* Copyright (c) 2019-2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "fss.h"
// #include "hos.h"
#include "../config/config.h"
#include "../libs/fatfs/ff.h"
#include "../mem/heap.h"
#include "../storage/emummc.h"
#include "../storage/nx_sd.h"
#include "../gfx/gfx.h"
#define DPRINTF(...)
extern hekate_config h_cfg;
extern bool is_ipl_updated(void *buf, char *path, bool force);
// FSS0 Magic and Meta header offset.
#define FSS0_MAGIC 0x30535346
#define FSS0_META_OFFSET 0x4
// FSS0 Content Types.
#define CNT_TYPE_FSP 0
#define CNT_TYPE_EXO 1 // Exosphere (Secure Monitor).
#define CNT_TYPE_WBT 2 // Warmboot (SC7Exit fw).
#define CNT_TYPE_RBT 3 // Rebootstub (Warmboot based reboot fw).
#define CNT_TYPE_SP1 4 // Sept Primary (TSEC and Sept Secondary loader).
#define CNT_TYPE_SP2 5 // Sept Secondary (Acts as pkg11 and derives keys).
#define CNT_TYPE_KIP 6 // KIP1 (Used for replacement or addition).
#define CNT_TYPE_BMP 7
#define CNT_TYPE_EMC 8
#define CNT_TYPE_KLD 9 // Kernel Loader.
#define CNT_TYPE_KRN 10 // Kernel.
// FSS0 Content Flags.
#define CNT_FLAG0_EXPERIMENTAL (1 << 0)
// FSS0 Meta Header.
typedef struct _fss_meta_t
{
u32 magic;
u32 size;
u32 crt0_off;
u32 cnt_off;
u32 cnt_count;
u32 hos_ver;
u32 version;
u32 git_rev;
} fss_meta_t;
// FSS0 Content Header.
typedef struct _fss_content_t
{
u32 offset;
u32 size;
u8 type;
u8 flags0;
u8 flags1;
u8 flags2;
u32 rsvd1;
char name[0x10];
} fss_content_t;
int parse_fss(launch_ctxt_t *ctxt, const char *path, fss0_sept_t *sept_ctxt)
{
FIL fp;
bool stock = false;
int sept_used = 0;
if (!sept_ctxt)
{
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ctxt->cfg->kvs, link)
{
if (!strcmp("stock", kv->key))
if (kv->val[0] == '1')
stock = true;
}
if (stock && ctxt->pkg1_id->kb <= KB_FIRMWARE_VERSION_620 && (!emu_cfg.enabled || h_cfg.emummc_force_disable))
return 1;
}
if (f_open(&fp, path, FA_READ) != FR_OK)
return 0;
void *fss = malloc(f_size(&fp));
// Read first 1024 bytes of the fss file.
f_read(&fp, fss, 1024, NULL);
// Get FSS0 Meta header offset.
u32 fss_meta_addr = *(u32 *)(fss + FSS0_META_OFFSET);
fss_meta_t *fss_meta = (fss_meta_t *)(fss + fss_meta_addr);
// Check if valid FSS0 and parse it.
if (fss_meta->magic == FSS0_MAGIC)
{
gfx_printf("Found FSS0, Atmosphere %d.%d.%d-%08x\n"
"Max HOS supported: %d.%d.%d\n"
"Unpacking and loading components.. ",
fss_meta->version >> 24, (fss_meta->version >> 16) & 0xFF, (fss_meta->version >> 8) & 0xFF, fss_meta->git_rev,
fss_meta->hos_ver >> 24, (fss_meta->hos_ver >> 16) & 0xFF, (fss_meta->hos_ver >> 8) & 0xFF);
if (!sept_ctxt)
{
ctxt->atmosphere = true;
ctxt->fss0_hosver = fss_meta->hos_ver;
}
// Parse FSS0 contents.
fss_content_t *curr_fss_cnt = (fss_content_t *)(fss + fss_meta->cnt_off);
void *content;
for (u32 i = 0; i < fss_meta->cnt_count; i++)
{
content = (void *)(fss + curr_fss_cnt[i].offset);
// Check if offset is inside limits.
if ((curr_fss_cnt[i].offset + curr_fss_cnt[i].size) > fss_meta->size)
continue;
// If content is experimental and experimental flag is not enabled, skip it.
if ((curr_fss_cnt[i].flags0 & CNT_FLAG0_EXPERIMENTAL) && !ctxt->fss0_enable_experimental)
continue;
// Parse content.
if (!sept_ctxt)
{
// Prepare content context.
switch (curr_fss_cnt[i].type)
{
case CNT_TYPE_KIP:
if (stock)
continue;
merge_kip_t *mkip1 = (merge_kip_t *)malloc(sizeof(merge_kip_t));
mkip1->kip1 = content;
list_append(&ctxt->kip1_list, &mkip1->link);
DPRINTF("Loaded %s.kip1 from FSS0 (size %08X)\n", curr_fss_cnt[i].name, curr_fss_cnt[i].size);
break;
case CNT_TYPE_EXO:
ctxt->secmon_size = curr_fss_cnt[i].size;
ctxt->secmon = content;
break;
case CNT_TYPE_WBT:
ctxt->warmboot_size = curr_fss_cnt[i].size;
ctxt->warmboot = content;
break;
default:
continue;
}
// Load content to launch context.
f_lseek(&fp, curr_fss_cnt[i].offset);
f_read(&fp, content, curr_fss_cnt[i].size, NULL);
}
else
{
// Load sept content directly to launch context.
switch (curr_fss_cnt[i].type)
{
case CNT_TYPE_SP1:
f_lseek(&fp, curr_fss_cnt[i].offset);
f_read(&fp, sept_ctxt->sept_primary, curr_fss_cnt[i].size, NULL);
break;
case CNT_TYPE_SP2:
if (!memcmp(curr_fss_cnt[i].name, (sept_ctxt->kb < KB_FIRMWARE_VERSION_810) ? "septsecondary00" : "septsecondary01", 15))
{
f_lseek(&fp, curr_fss_cnt[i].offset);
f_read(&fp, sept_ctxt->sept_secondary, curr_fss_cnt[i].size, NULL);
sept_used = 1;
goto out;
}
break;
default:
break;
}
}
}
out:
gfx_printf("Done!\n");
f_close(&fp);
return (!sept_ctxt ? 1 : sept_used);
}
f_close(&fp);
free(fss);
return 0;
}
int load_sept_from_ffs0(fss0_sept_t *sept_ctxt)
{
LIST_FOREACH_ENTRY(ini_kv_t, kv, &sept_ctxt->cfg_sec->kvs, link)
{
if (!strcmp("fss0", kv->key))
return parse_fss(NULL, kv->val, sept_ctxt);
}
return 0;
}

34
source/hos/fss.h Normal file
View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2019 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _FSS_H_
#define _FSS_H_
#include "hos.h"
typedef struct _fss0_sept_t
{
u32 kb;
ini_sec_t *cfg_sec;
void *sept_primary;
void *sept_secondary;
} fss0_sept_t;
int parse_fss(launch_ctxt_t *ctxt, const char *path, fss0_sept_t *sept_ctxt);
int load_sept_from_ffs0(fss0_sept_t *sept_ctxt);
#endif

120
source/hos/hos.h Normal file
View File

@@ -0,0 +1,120 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _HOS_H_
#define _HOS_H_
#include "pkg1.h"
#include "pkg2.h"
#include "../utils/types.h"
#include "../config/ini.h"
#include "../sec/tsec.h"
#include <assert.h>
#define KB_FIRMWARE_VERSION_100_200 0
#define KB_FIRMWARE_VERSION_300 1
#define KB_FIRMWARE_VERSION_301 2
#define KB_FIRMWARE_VERSION_400 3
#define KB_FIRMWARE_VERSION_500 4
#define KB_FIRMWARE_VERSION_600 5
#define KB_FIRMWARE_VERSION_620 6
#define KB_FIRMWARE_VERSION_700 7
#define KB_FIRMWARE_VERSION_810 8
#define KB_FIRMWARE_VERSION_900 9
#define KB_FIRMWARE_VERSION_910 10
#define KB_FIRMWARE_VERSION_MAX KB_FIRMWARE_VERSION_910
#define HOS_PKG11_MAGIC 0x31314B50
#define HOS_EKS_MAGIC 0x30534B45
typedef struct _exo_ctxt_t
{
bool no_user_exceptions;
bool user_pmu;
bool *cal0_blank;
bool *cal0_allow_writes_sys;
} exo_ctxt_t;
typedef struct _hos_eks_keys_t
{
u8 dkg[0x10];
u8 mkk[0x10];
u8 fdk[0x10];
u8 dkk[0x10];
} hos_eks_keys_t;
typedef struct _hos_eks_mbr_t
{
u32 magic;
u32 enabled;
u32 sbk_low[2];
hos_eks_keys_t keys[6];
u32 magic2;
u32 rsvd2[3];
} hos_eks_mbr_t;
static_assert(sizeof(hos_eks_mbr_t) == 416, "HOS EKS storage bigger than MBR!");
typedef struct _launch_ctxt_t
{
void *keyblob;
void *pkg1;
const pkg1_id_t *pkg1_id;
const pkg2_kernel_id_t *pkg2_kernel_id;
void *warmboot;
u32 warmboot_size;
void *secmon;
u32 secmon_size;
void *pkg2;
u32 pkg2_size;
bool new_pkg2;
void *kernel;
u32 kernel_size;
link_t kip1_list;
char* kip1_patches;
u32 fss0_hosver;
bool svcperm;
bool debugmode;
bool stock;
bool atmosphere;
bool fss0_enable_experimental;
bool emummc_forced;
exo_ctxt_t exo_cfg;
ini_sec_t *cfg;
} launch_ctxt_t;
typedef struct _merge_kip_t
{
void *kip1;
link_t link;
} merge_kip_t;
void hos_eks_get();
void hos_eks_save(u32 kb);
void hos_eks_clear(u32 kb);
int hos_launch(ini_sec_t *cfg);
int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt);
#endif

View File

@@ -26,15 +26,15 @@
#include "../gfx/gfx.h" #include "../gfx/gfx.h"
u32 pkg2_newkern_ini1_val;
u32 pkg2_newkern_ini1_start;
u32 pkg2_newkern_ini1_end;
/*#include "util.h" /*#include "util.h"
#define DPRINTF(...) gfx_printf(__VA_ARGS__) #define DPRINTF(...) gfx_printf(__VA_ARGS__)
#define DEBUG_PRINTING*/ #define DEBUG_PRINTING*/
#define DPRINTF(...) #define DPRINTF(...)
u32 pkg2_newkern_ini1_val;
u32 pkg2_newkern_ini1_start;
u32 pkg2_newkern_ini1_end;
static u32 _pkg2_calc_kip1_size(pkg2_kip1_t *kip1) static u32 _pkg2_calc_kip1_size(pkg2_kip1_t *kip1)
{ {
u32 size = sizeof(pkg2_kip1_t); u32 size = sizeof(pkg2_kip1_t);

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (C) 2018-2020 CTCaer * Copyright (c) 2018-2020 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -32,6 +32,14 @@ extern u32 pkg2_newkern_ini1_val;
extern u32 pkg2_newkern_ini1_start; extern u32 pkg2_newkern_ini1_start;
extern u32 pkg2_newkern_ini1_end; extern u32 pkg2_newkern_ini1_end;
typedef struct _kernel_patch_t
{
u32 id;
u32 off;
u32 val;
u32 *ptr;
} kernel_patch_t;
typedef struct _pkg2_hdr_t typedef struct _pkg2_hdr_t
{ {
u8 ctr[0x10]; u8 ctr[0x10];
@@ -87,6 +95,12 @@ typedef struct _pkg2_kip1_info_t
link_t link; link_t link;
} pkg2_kip1_info_t; } pkg2_kip1_info_t;
typedef struct _pkg2_kernel_id_t
{
u8 hash[8];
kernel_patch_t *kernel_patchset;
} pkg2_kernel_id_t;
bool pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2, bool *new_pkg2); bool pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2, bool *new_pkg2);
int pkg2_decompress_kip(pkg2_kip1_info_t* ki, u32 sectsToDecomp); int pkg2_decompress_kip(pkg2_kip1_info_t* ki, u32 sectsToDecomp);
pkg2_hdr_t *pkg2_decrypt(void *data); pkg2_hdr_t *pkg2_decrypt(void *data);

View File

@@ -17,15 +17,20 @@
#include <string.h> #include <string.h>
#include "sept.h" #include "sept.h"
#include "../config/ini.h"
#include "../gfx/di.h" #include "../gfx/di.h"
#include "../hos/fss.h"
#include "../hos/hos.h"
#include "../libs/fatfs/ff.h" #include "../libs/fatfs/ff.h"
#include "../mem/heap.h" #include "../mem/heap.h"
#include "../soc/hw_init.h" #include "../soc/hw_init.h"
#include "../soc/pmc.h" #include "../soc/pmc.h"
#include "../soc/t210.h" #include "../soc/t210.h"
#include "../storage/nx_emmc.h" #include "../storage/nx_emmc.h"
#include "../storage/nx_sd.h"
#include "../storage/sdmmc.h" #include "../storage/sdmmc.h"
#include "../utils/btn.h" #include "../utils/btn.h"
#include "../utils/list.h"
#include "../utils/types.h" #include "../utils/types.h"
#include "../gfx/gfx.h" #include "../gfx/gfx.h"
@@ -58,48 +63,81 @@ u8 warmboot_reboot[] = {
extern u32 color_idx; extern u32 color_idx;
extern boot_cfg_t b_cfg; extern boot_cfg_t b_cfg;
extern void sd_unmount();
extern void reloc_patcher(u32 payload_dst, u32 payload_src, u32 payload_size); extern void reloc_patcher(u32 payload_dst, u32 payload_src, u32 payload_size);
int reboot_to_sept(const u8 *tsec_fw, const u32 tsec_size, const u32 kb) int reboot_to_sept(const u8 *tsec_fw, const u32 tsec_size, const u32 kb)
{ {
FIL fp; FIL fp;
bool fss0_sept_used = false;
// Copy warmboot reboot code and TSEC fw. // Copy warmboot reboot code and TSEC fw.
memcpy((u8 *)(SEPT_PK1T_ADDR - WB_RST_SIZE), (u8 *)warmboot_reboot, sizeof(warmboot_reboot)); memcpy((u8 *)(SEPT_PK1T_ADDR - WB_RST_SIZE), (u8 *)warmboot_reboot, sizeof(warmboot_reboot));
memcpy((void *)SEPT_PK1T_ADDR, tsec_fw, tsec_size); memcpy((void *)SEPT_PK1T_ADDR, tsec_fw, tsec_size);
*(vu32 *)SEPT_TCSZ_ADDR = tsec_size; *(vu32 *)SEPT_TCSZ_ADDR = tsec_size;
// Copy sept-primary. LIST_INIT(ini_sections);
if (f_open(&fp, "sd:/sept/sept-primary.bin", FA_READ)) if (ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false))
goto error; {
bool found = false;
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
{
// Only parse non config sections.
if (ini_sec->type == INI_CHOICE && strcmp(ini_sec->name, "config"))
{
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
{
if (!strcmp("fss0", kv->key))
{
fss0_sept_t sept_ctxt;
sept_ctxt.kb = kb;
sept_ctxt.sept_primary = (void *)SEPT_STG1_ADDR;
sept_ctxt.sept_secondary = (void *)SEPT_STG2_ADDR;
fss0_sept_used = parse_fss(NULL, kv->val, &sept_ctxt);
if (f_read(&fp, (u8 *)SEPT_STG1_ADDR, f_size(&fp), NULL)) found = true;
{ break;
f_close(&fp); }
goto error; }
}
if (found)
break;
}
} }
f_close(&fp);
// Copy sept-secondary.
if (kb < KB_FIRMWARE_VERSION_810) if (!fss0_sept_used)
{ {
if (f_open(&fp, "sd:/sept/sept-secondary_00.enc", FA_READ)) // Copy sept-primary.
if (f_open(&fp, "sd:/sept/sept-secondary.enc", FA_READ)) // Try the deprecated version. if (f_open(&fp, "sd:/sept/sept-primary.bin", FA_READ))
goto error;
}
else
{
if (f_open(&fp, "sd:/sept/sept-secondary_01.enc", FA_READ))
goto error; goto error;
}
if (f_read(&fp, (u8 *)SEPT_STG2_ADDR, f_size(&fp), NULL)) if (f_read(&fp, (u8 *)SEPT_STG1_ADDR, f_size(&fp), NULL))
{ {
f_close(&fp);
goto error;
}
f_close(&fp);
// Copy sept-secondary.
if (kb < KB_FIRMWARE_VERSION_810)
{
if (f_open(&fp, "sd:/sept/sept-secondary_00.enc", FA_READ))
if (f_open(&fp, "sd:/sept/sept-secondary.enc", FA_READ)) // Try the deprecated version.
goto error;
}
else
{
if (f_open(&fp, "sd:/sept/sept-secondary_01.enc", FA_READ))
goto error;
}
if (f_read(&fp, (u8 *)SEPT_STG2_ADDR, f_size(&fp), NULL))
{
f_close(&fp);
goto error;
}
f_close(&fp); f_close(&fp);
goto error;
} }
f_close(&fp);
// Save auto boot config to sept payload, if any. // Save auto boot config to sept payload, if any.
boot_cfg_t *tmp_cfg = malloc(sizeof(boot_cfg_t)); boot_cfg_t *tmp_cfg = malloc(sizeof(boot_cfg_t));
@@ -107,7 +145,8 @@ int reboot_to_sept(const u8 *tsec_fw, const u32 tsec_size, const u32 kb)
tmp_cfg->boot_cfg |= BOOT_CFG_SEPT_RUN; tmp_cfg->boot_cfg |= BOOT_CFG_SEPT_RUN;
if (f_open(&fp, "sd:/sept/payload.bin", FA_READ | FA_WRITE)) { if (f_open(&fp, "sd:/sept/payload.bin", FA_READ | FA_WRITE))
{
free(tmp_cfg); free(tmp_cfg);
goto error; goto error;
} }

View File

@@ -81,8 +81,10 @@ static inline void _gf256_mul_x_le(void *block) {
static inline int _emmc_xts(u32 ks1, u32 ks2, u32 enc, u8 *tweak, bool regen_tweak, u32 tweak_exp, u64 sec, void *dst, void *src, u32 secsize) { static inline int _emmc_xts(u32 ks1, u32 ks2, u32 enc, u8 *tweak, bool regen_tweak, u32 tweak_exp, u64 sec, void *dst, void *src, u32 secsize) {
int res = 0; int res = 0;
u8 *pdst = (u8 *)dst; u8 *temptweak = (u8 *)malloc(0x10);
u8 *psrc = (u8 *)src; u32 *pdst = (u32 *)dst;
u32 *psrc = (u32 *)src;
u32 *ptweak = (u32 *)tweak;
if (regen_tweak) { if (regen_tweak) {
for (int i = 0xF; i >= 0; i--) { for (int i = 0xF; i >= 0; i--) {
@@ -96,34 +98,33 @@ static inline int _emmc_xts(u32 ks1, u32 ks2, u32 enc, u8 *tweak, bool regen_twe
for (u32 i = 0; i < tweak_exp * 0x20; i++) for (u32 i = 0; i < tweak_exp * 0x20; i++)
_gf256_mul_x_le(tweak); _gf256_mul_x_le(tweak);
u8 temptweak[0x10];
memcpy(temptweak, tweak, 0x10); memcpy(temptweak, tweak, 0x10);
//We are assuming a 0x10-aligned sector size in this implementation. //We are assuming a 0x10-aligned sector size in this implementation.
for (u32 i = 0; i < secsize / 0x10; i++) { for (u32 i = 0; i < secsize / 0x10; i++) {
for (u32 j = 0; j < 0x10; j++) for (u32 j = 0; j < 4; j++)
pdst[j] = psrc[j] ^ tweak[j]; pdst[j] = psrc[j] ^ ptweak[j];
_gf256_mul_x_le(tweak); _gf256_mul_x_le(tweak);
psrc += 0x10; psrc += 4;
pdst += 0x10; pdst += 4;
} }
se_aes_crypt_ecb(ks2, enc, dst, secsize, dst, secsize); se_aes_crypt_ecb(ks2, enc, dst, secsize, dst, secsize);
pdst = (u8 *)dst; pdst = (u32 *)dst;
memcpy(tweak, temptweak, 0x10); memcpy(tweak, temptweak, 0x10);
for (u32 i = 0; i < secsize / 0x10; i++) { for (u32 i = 0; i < secsize / 0x10; i++) {
for (u32 j = 0; j < 0x10; j++) for (u32 j = 0; j < 4; j++)
pdst[j] = pdst[j] ^ tweak[j]; pdst[j] = pdst[j] ^ ptweak[j];
_gf256_mul_x_le(tweak); _gf256_mul_x_le(tweak);
pdst += 0x10; pdst += 4;
} }
res = 1; res = 1;
out:; out:;
free(temptweak);
return res; return res;
} }

View File

@@ -42,8 +42,8 @@
#include "../../storage/sdmmc.h" #include "../../storage/sdmmc.h"
extern sdmmc_storage_t sd_storage; extern sdmmc_storage_t sd_storage;
#define EFSPRINTF(text, ...) print_error(); gfx_printf("%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF); //#define EFSPRINTF(text, ...) print_error(); gfx_printf("%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF);
//#define EFSPRINTF(...) #define EFSPRINTF(...)
/*-------------------------------------------------------------------------- /*--------------------------------------------------------------------------

View File

@@ -136,7 +136,7 @@ void *malloc(u32 size)
void *calloc(u32 num, u32 size) void *calloc(u32 num, u32 size)
{ {
void *res = (void *)_heap_alloc(&_heap, num * size); void *res = (void *)_heap_alloc(&_heap, num * size);
memset(res, 0, num * size); memset(res, 0, ALIGN(num * size, sizeof(hnode_t))); // Clear the aligned size.
return res; return res;
} }
@@ -164,7 +164,7 @@ void heap_monitor(heap_monitor_t *mon, bool print_node_stats)
count, node->used, (u32)node + sizeof(hnode_t), node->size); count, node->used, (u32)node + sizeof(hnode_t), node->size);
count++; count++;
if (node->next) if (node->next)
node = node->next; node = node->next;
else else

View File

@@ -2,7 +2,7 @@
* PMIC Real Time Clock driver for Nintendo Switch's MAX77620-RTC * PMIC Real Time Clock driver for Nintendo Switch's MAX77620-RTC
* *
* Copyright (c) 2018-2019 CTCaer * Copyright (c) 2018-2019 CTCaer
* Copyright (c) 2019 shchmue * Copyright (c) 2019-2020 shchmue
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -35,10 +35,10 @@ void max77620_rtc_get_time(rtc_time_t *time)
// Get time. // Get time.
time->sec = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_SEC_REG) & 0x7F; time->sec = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_SEC_REG) & 0x7F;
time->min = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_MIN_REG) & 0x7F; time->min = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_MIN_REG) & 0x7F;
u8 hour = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_HOUR_REG);
time->hour = hour & 0x1F;
if (!(val & MAX77620_RTC_24H) && (hour & MAX77620_RTC_HOUR_PM_MASK)) time->hour = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_HOUR_REG) & 0x1F;
if (!(val & MAX77620_RTC_24H) && time->hour & MAX77620_RTC_HOUR_PM_MASK)
time->hour = (time->hour & 0xF) + 12; time->hour = (time->hour & 0xF) + 12;
// Get day of week. 1: Monday to 7: Sunday. // Get day of week. 1: Monday to 7: Sunday.

View File

@@ -19,6 +19,7 @@
#include <string.h> #include <string.h>
#include "../../common/memory_map.h"
#include "../sec/se.h" #include "../sec/se.h"
#include "../mem/heap.h" #include "../mem/heap.h"
#include "../soc/bpmp.h" #include "../soc/bpmp.h"
@@ -94,7 +95,12 @@ static int _se_wait()
static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size) static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size)
{ {
se_ll_t *ll_dst = (se_ll_t *)0xECFFFFE0, *ll_src = (se_ll_t *)0xECFFFFF0; static se_ll_t *ll_dst = NULL, *ll_src = NULL;
if (!ll_dst)
{
ll_dst = (se_ll_t *)malloc(sizeof(se_ll_t));
ll_src = (se_ll_t *)malloc(sizeof(se_ll_t));
}
if (dst) if (dst)
{ {
@@ -234,6 +240,16 @@ void se_aes_key_set(u32 ks, const void *key, u32 size)
} }
} }
void se_aes_iv_set(u32 ks, const void *iv, u32 size)
{
u32 *data = (u32 *)iv;
for (u32 i = 0; i < size / 4; i++)
{
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | 8 | i;
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data[i];
}
}
void se_aes_key_read(u32 ks, void *key, u32 size) void se_aes_key_read(u32 ks, void *key, u32 size)
{ {
u32 *data = (u32 *)key; u32 *data = (u32 *)key;
@@ -320,12 +336,90 @@ int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_s
return 1; return 1;
} }
// random calls were derived from Atmosphère's
int se_initialize_rng(u32 ks)
{
u8 *output_buf = (u8 *)malloc(0x10);
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) |
SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_MODE(RNG_MODE_FORCE_INSTANTION) | SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY);
SE(SE_RNG_RESEED_INTERVAL_REG_OFFSET) = 70001;
SE(SE_RNG_SRC_CONFIG_REG_OFFSET) = SE_RNG_SRC_CONFIG_ENT_SRC_LOCK(RNG_SRC_RO_ENT_LOCK_ENABLE);
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0;
int res =_se_execute(OP_START, output_buf, 0x10, NULL, 0);
free(output_buf);
return res;
}
int se_generate_random(u32 ks, void *dst, u32 size)
{
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) |
SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_MODE(RNG_MODE_NORMAL) | SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY);
u32 num_blocks = size >> 4;
u32 aligned_size = num_blocks << 4;
if (num_blocks)
{
SE(SE_BLOCK_COUNT_REG_OFFSET) = num_blocks - 1;
if (!_se_execute(OP_START, dst, aligned_size, NULL, 0))
return 0;
}
if (size > aligned_size)
return _se_execute_one_block(OP_START, dst + aligned_size, size - aligned_size, NULL, 0);
return 1;
}
int se_generate_random_key(u32 ks_dst, u32 ks_src)
{
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) |
SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_MODE(RNG_MODE_NORMAL) | SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY);
SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst);
if (!_se_execute(OP_START, NULL, 0, NULL, 0))
return 0;
SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst) | 1;
if (!_se_execute(OP_START, NULL, 0, NULL, 0))
return 0;
return 1;
}
int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size)
{
if (enc)
{
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) |
SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_XOR_POS(XOR_TOP) | SE_CRYPTO_INPUT_SEL(INPUT_AHB) |
SE_CRYPTO_IV_SEL(IV_ORIGINAL);
}
else
{
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVAHB) |
SE_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM) | SE_CRYPTO_INPUT_SEL(INPUT_AHB) |
SE_CRYPTO_IV_SEL(IV_ORIGINAL);
}
SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1;
return _se_execute(OP_START, dst, dst_size, src, src_size);
}
int se_aes_xts_crypt_sec(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, const void *src, u32 secsize) int se_aes_xts_crypt_sec(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, const void *src, u32 secsize)
{ {
int res = 0; int res = 0;
u8 *tweak = (u8 *)malloc(0x10); u8 *tweak = (u8 *)malloc(0x10);
u8 *pdst = (u8 *)dst; u8 *temptweak = (u8 *)malloc(0x10);
u8 *psrc = (u8 *)src; u32 *pdst = (u32 *)dst;
u32 *psrc = (u32 *)src;
u32 *ptweak = (u32 *)tweak;
//Generate tweak. //Generate tweak.
for (int i = 0xF; i >= 0; i--) for (int i = 0xF; i >= 0; i--)
@@ -336,23 +430,35 @@ int se_aes_xts_crypt_sec(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, const vo
if (!se_aes_crypt_block_ecb(ks1, 1, tweak, tweak)) if (!se_aes_crypt_block_ecb(ks1, 1, tweak, tweak))
goto out; goto out;
memcpy(temptweak, tweak, 0x10);
//We are assuming a 0x10-aligned sector size in this implementation. //We are assuming a 0x10-aligned sector size in this implementation.
for (u32 i = 0; i < secsize / 0x10; i++) for (u32 i = 0; i < secsize / 0x10; i++)
{ {
for (u32 j = 0; j < 0x10; j++) for (u32 j = 0; j < 4; j++)
pdst[j] = psrc[j] ^ tweak[j]; pdst[j] = psrc[j] ^ ptweak[j];
if (!se_aes_crypt_block_ecb(ks2, enc, pdst, pdst))
goto out;
for (u32 j = 0; j < 0x10; j++)
pdst[j] = pdst[j] ^ tweak[j];
_gf256_mul_x_le(tweak); _gf256_mul_x_le(tweak);
psrc += 0x10; psrc += 4;
pdst += 0x10; pdst += 4;
}
se_aes_crypt_ecb(ks2, enc, dst, secsize, dst, secsize);
pdst = (u32 *)dst;
memcpy(tweak, temptweak, 0x10);
for (u32 i = 0; i < secsize / 0x10; i++)
{
for (u32 j = 0; j < 4; j++)
pdst[j] = pdst[j] ^ ptweak[j];
_gf256_mul_x_le(tweak);
pdst += 4;
} }
res = 1; res = 1;
out:; out:;
free(temptweak);
free(tweak); free(tweak);
return res; return res;
} }
@@ -390,17 +496,21 @@ int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size)
se_aes_key_iv_clear(ks); se_aes_key_iv_clear(ks);
u32 num_blocks = (src_size + 0xf) >> 4; u32 num_blocks = (src_size + 0xf) >> 4;
if (num_blocks > 1) { if (num_blocks > 1)
{
SE(SE_BLOCK_COUNT_REG_OFFSET) = num_blocks - 2; SE(SE_BLOCK_COUNT_REG_OFFSET) = num_blocks - 2;
if (!_se_execute(OP_START, NULL, 0, src, src_size)) if (!_se_execute(OP_START, NULL, 0, src, src_size))
goto out; goto out;
SE(SE_CRYPTO_REG_OFFSET) |= SE_CRYPTO_IV_SEL(IV_UPDATED); SE(SE_CRYPTO_REG_OFFSET) |= SE_CRYPTO_IV_SEL(IV_UPDATED);
} }
if (src_size & 0xf) { if (src_size & 0xf)
{
memcpy(last_block, src + (src_size & ~0xf), src_size & 0xf); memcpy(last_block, src + (src_size & ~0xf), src_size & 0xf);
last_block[src_size & 0xf] = 0x80; last_block[src_size & 0xf] = 0x80;
} else if (src_size >= 0x10) { }
else if (src_size >= 0x10)
{
memcpy(last_block, src + src_size - 0x10, 0x10); memcpy(last_block, src + src_size - 0x10, 0x10);
} }
@@ -447,7 +557,8 @@ int se_calc_sha256(void *dst, const void *src, u32 src_size)
return res; return res;
} }
int se_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *key, u32 key_size) { int se_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *key, u32 key_size)
{
int res = 0; int res = 0;
u8 *secret = (u8 *)malloc(0x40); u8 *secret = (u8 *)malloc(0x40);
u8 *ipad = (u8 *)malloc(0x40 + src_size); u8 *ipad = (u8 *)malloc(0x40 + src_size);

View File

@@ -25,12 +25,17 @@ void se_rsa_key_clear(u32 ks);
int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size); int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size);
void se_key_acc_ctrl(u32 ks, u32 flags); void se_key_acc_ctrl(u32 ks, u32 flags);
void se_aes_key_set(u32 ks, const void *key, u32 size); void se_aes_key_set(u32 ks, const void *key, u32 size);
void se_aes_iv_set(u32 ks, const void *iv, u32 size);
void se_aes_key_read(u32 ks, void *key, u32 size); void se_aes_key_read(u32 ks, void *key, u32 size);
void se_aes_key_clear(u32 ks); void se_aes_key_clear(u32 ks);
int se_initialize_rng(u32 ks);
int se_generate_random(u32 ks, void *dst, u32 size);
int se_generate_random_key(u32 ks_dst, u32 ks_src);
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input); int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input);
int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size); int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size);
int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src); int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src);
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr); int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr);
int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size);
int se_aes_xts_crypt_sec(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, const void *src, u32 secsize); int se_aes_xts_crypt_sec(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, const void *src, u32 secsize);
int se_aes_xts_crypt(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, const void *src, u32 secsize, u32 num_secs); int se_aes_xts_crypt(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, const void *src, u32 secsize, u32 num_secs);
int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size); int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size);

View File

@@ -18,6 +18,7 @@
#include <string.h> #include <string.h>
#include "../hos/hos.h"
#include "../sec/tsec.h" #include "../sec/tsec.h"
#include "../sec/tsec_t210.h" #include "../sec/tsec_t210.h"
#include "../sec/se_t210.h" #include "../sec/se_t210.h"
@@ -80,7 +81,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
kfuse_wait_ready(); kfuse_wait_ready();
// Configure Falcon. //Configure Falcon.
TSEC(TSEC_DMACTL) = 0; TSEC(TSEC_DMACTL) = 0;
TSEC(TSEC_IRQMSET) = TSEC(TSEC_IRQMSET) =
TSEC_IRQMSET_EXT(0xFF) | TSEC_IRQMSET_EXT(0xFF) |
@@ -102,7 +103,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
goto out; goto out;
} }
// Load firmware or emulate memio environment for newer TSEC fw. //Load firmware or emulate memio environment for newer TSEC fw.
if (kb == KB_FIRMWARE_VERSION_620) if (kb == KB_FIRMWARE_VERSION_620)
TSEC(TSEC_DMATRFBASE) = (u32)tsec_ctxt->fw >> 8; TSEC(TSEC_DMATRFBASE) = (u32)tsec_ctxt->fw >> 8;
else else
@@ -126,7 +127,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
{ {
// Init SMMU translation for TSEC. // Init SMMU translation for TSEC.
pdir = smmu_init_for_tsec(); pdir = smmu_init_for_tsec();
smmu_init(tsec_ctxt->secmon_base); smmu_init(0x4002B000);
// Enable SMMU // Enable SMMU
if (!smmu_is_used()) if (!smmu_is_used())
smmu_enable(); smmu_enable();
@@ -169,7 +170,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
iram = page_alloc(0x30); iram = page_alloc(0x30);
memcpy(iram, tsec_ctxt->pkg1, 0x30000); memcpy(iram, tsec_ctxt->pkg1, 0x30000);
// PKG1.1 magic offset. // PKG1.1 magic offset.
pkg11_magic_off = (u32 *)(iram + ((tsec_ctxt->pkg11_off + 0x20) / 4)); pkg11_magic_off = (u32 *)(iram + (0x7000 / 4));
smmu_map(pdir, 0x40010000, (u32)iram, 0x30, _READABLE | _WRITABLE | _NONSECURE); smmu_map(pdir, 0x40010000, (u32)iram, 0x30, _READABLE | _WRITABLE | _NONSECURE);
// Exception vectors // Exception vectors
@@ -177,7 +178,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
smmu_map(pdir, EXCP_VEC_BASE, (u32)evec, 1, _READABLE | _WRITABLE | _NONSECURE); smmu_map(pdir, EXCP_VEC_BASE, (u32)evec, 1, _READABLE | _WRITABLE | _NONSECURE);
} }
// Execute firmware. //Execute firmware.
HOST1X(HOST1X_CH0_SYNC_SYNCPT_160) = 0x34C2E1DA; HOST1X(HOST1X_CH0_SYNC_SYNCPT_160) = 0x34C2E1DA;
TSEC(TSEC_STATUS) = 0; TSEC(TSEC_STATUS) = 0;
TSEC(TSEC_BOOTKEYVER) = 1; // HOS uses key version 1. TSEC(TSEC_BOOTKEYVER) = 1; // HOS uses key version 1.
@@ -254,7 +255,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
goto out_free; goto out_free;
} }
// Fetch result. //Fetch result.
HOST1X(HOST1X_CH0_SYNC_SYNCPT_160) = 0; HOST1X(HOST1X_CH0_SYNC_SYNCPT_160) = 0;
u32 buf[4]; u32 buf[4];
buf[0] = SOR1(SOR_NV_PDISP_SOR_DP_HDCP_BKSV_LSB); buf[0] = SOR1(SOR_NV_PDISP_SOR_DP_HDCP_BKSV_LSB);
@@ -274,7 +275,7 @@ out_free:;
out:; out:;
// Disable clocks. //Disable clocks.
clock_disable_kfuse(); clock_disable_kfuse();
clock_disable_sor1(); clock_disable_sor1();
clock_disable_sor0(); clock_disable_sor0();

View File

@@ -27,8 +27,6 @@ typedef struct _tsec_ctxt_t
void *fw; void *fw;
u32 size; u32 size;
void *pkg1; void *pkg1;
u32 pkg11_off;
u32 secmon_base;
} tsec_ctxt_t; } tsec_ctxt_t;
typedef struct _tsec_key_data_t typedef struct _tsec_key_data_t

View File

@@ -26,7 +26,6 @@
#include "pinmux.h" #include "pinmux.h"
#include "pmc.h" #include "pmc.h"
#include "t210.h" #include "t210.h"
#include "uart.h"
#include "../gfx/di.h" #include "../gfx/di.h"
#include "../mem/mc.h" #include "../mem/mc.h"
#include "../mem/minerva.h" #include "../mem/minerva.h"
@@ -102,7 +101,7 @@ void _config_gpios()
pinmux_config_i2c(I2C_1); pinmux_config_i2c(I2C_1);
pinmux_config_i2c(I2C_5); pinmux_config_i2c(I2C_5);
pinmux_config_uart(UART_A); pinmux_config_uart(0);
// Configure volume up/down as inputs. // Configure volume up/down as inputs.
gpio_config(GPIO_PORT_X, GPIO_PIN_6, GPIO_MODE_GPIO); gpio_config(GPIO_PORT_X, GPIO_PIN_6, GPIO_MODE_GPIO);
@@ -295,11 +294,6 @@ void config_hw()
APB_MISC(APB_MISC_PP_PINMUX_GLOBAL) = 0; APB_MISC(APB_MISC_PP_PINMUX_GLOBAL) = 0;
_config_gpios(); _config_gpios();
#ifdef DEBUG_UART_PORT
clock_enable_uart(DEBUG_UART_PORT);
uart_init(DEBUG_UART_PORT, 115200);
#endif
clock_enable_cl_dvfs(); clock_enable_cl_dvfs();
clock_enable_i2c(I2C_1); clock_enable_i2c(I2C_1);
@@ -319,6 +313,7 @@ void config_hw()
sdram_init(); sdram_init();
bpmp_mmu_enable(); bpmp_mmu_enable();
mc_enable_ahb_redirect();
// Clear flags from PMC_SCRATCH0 // Clear flags from PMC_SCRATCH0
PMC(APBDEV_PMC_SCRATCH0) &= ~PMC_SCRATCH0_MODE_PAYLOAD; PMC(APBDEV_PMC_SCRATCH0) &= ~PMC_SCRATCH0_MODE_PAYLOAD;
@@ -334,7 +329,7 @@ void reconfig_hw_workaround(bool extra_reconfig, u32 magic)
// Re-enable clocks to Audio Processing Engine as a workaround to hanging. // Re-enable clocks to Audio Processing Engine as a workaround to hanging.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= (1 << 10); // Enable AHUB clock. CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= (1 << 10); // Enable AHUB clock.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= (1 << 6); // Enable APE clock. CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= (1 << 6); // Enable APE clock.
if (extra_reconfig) if (extra_reconfig)
{ {
@@ -357,7 +352,7 @@ void reconfig_hw_workaround(bool extra_reconfig, u32 magic)
if (magic == 0xBAADF00D) if (magic == 0xBAADF00D)
{ {
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) |= (1 << 22); CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) |= (1 << 22);
sdmmc_init(&sd_sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_SD_ID, 0); sdmmc_init(&sd_sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, 5, 0);
clock_disable_cl_dvfs(); clock_disable_cl_dvfs();
msleep(200); msleep(200);

View File

@@ -116,3 +116,5 @@ extern gpt_entry_rule gpt_fs_rules[];
extern menu_entry mmcmenu_start[]; extern menu_entry mmcmenu_start[];
extern menu_entry mmcmenu_filemenu[]; extern menu_entry mmcmenu_filemenu[];
extern menu_entry fwDump_typeMenu[];

View File

@@ -92,4 +92,11 @@ menu_entry mmcmenu_filemenu[] = {
{NULL, COLOR_VIOLET, {ISSKIP | ISMENU}}, {NULL, COLOR_VIOLET, {ISSKIP | ISMENU}},
{"\nBack", COLOR_WHITE, {ISMENU}}, {"\nBack", COLOR_WHITE, {ISMENU}},
{"Dump to SD", COLOR_YELLOW, {ISMENU}} {"Dump to SD", COLOR_YELLOW, {ISMENU}}
};
menu_entry fwDump_typeMenu[] = {
{"Back\n", COLOR_WHITE, {ISMENU}},
{"Firmware format type:", COLOR_WHITE, {ISMENU | ISSKIP}},
{"Daybreak (prod.keys required!)", COLOR_BLUE, {ISMENU}},
{"ChoiNX", COLOR_VIOLET, {ISMENU}}
}; };

View File

@@ -218,9 +218,6 @@ int dump_biskeys(){
//sdmmc_storage_set_mmc_partition(&storage, 0); //sdmmc_storage_set_mmc_partition(&storage, 0);
//nx_emmc_gpt_parse(&sys_gpt, &storage); //nx_emmc_gpt_parse(&sys_gpt, &storage);
se_aes_key_set(8, bis_key[2] + 0x00, 0x10);
se_aes_key_set(9, bis_key[2] + 0x10, 0x10);
pkg1inf.ver = pkg1_id->kb; pkg1inf.ver = pkg1_id->kb;
strcpy(pkg1inf.id, pkg1_id->id); strcpy(pkg1inf.id, pkg1_id->id);

View File

@@ -15,7 +15,6 @@ int fsact_copy(const char *locin, const char *locout, u8 options){
FIL in, out; FIL in, out;
FILINFO in_info; FILINFO in_info;
u64 sizeRemaining, toCopy; u64 sizeRemaining, toCopy;
UINT temp1, temp2;
u8 *buff, toPrint = options & COPY_MODE_PRINT, toCancel = options & COPY_MODE_CANCEL; u8 *buff, toPrint = options & COPY_MODE_PRINT, toCancel = options & COPY_MODE_CANCEL;
u32 x, y, i = 11; u32 x, y, i = 11;
int res; int res;
@@ -56,19 +55,14 @@ int fsact_copy(const char *locin, const char *locout, u8 options){
while (sizeRemaining > 0){ while (sizeRemaining > 0){
toCopy = MIN(sizeRemaining, BUFSIZE); toCopy = MIN(sizeRemaining, BUFSIZE);
if ((res = f_read(&in, buff, toCopy, &temp1))){ if ((res = f_read(&in, buff, toCopy, NULL))){
gfx_errDisplay("copy", res, 5); gfx_errDisplay("copy", res, 5);
return 1; break;
} }
if ((res = f_write(&out, buff, toCopy, &temp2))){ if ((res = f_write(&out, buff, toCopy, NULL))){
gfx_errDisplay("copy", res, 6); gfx_errDisplay("copy", res, 6);
return 1; break;
}
if (temp1 != temp2){
gfx_errDisplay("copy", ERR_DISK_WRITE_FAILED, 7);
return 1;
} }
sizeRemaining -= toCopy; sizeRemaining -= toCopy;
@@ -100,13 +94,10 @@ int fsact_copy(const char *locin, const char *locout, u8 options){
f_close(&out); f_close(&out);
free(buff); free(buff);
if ((res = f_chmod(locout, in_info.fattrib, 0x3A))){ f_chmod(locout, in_info.fattrib, 0x3A);
gfx_errDisplay("copy", res, 8);
return 1;
}
f_stat(locin, &in_info); //somehow stops fatfs from being weird f_stat(locin, &in_info); //somehow stops fatfs from being weird
return 0; return res;
} }
int fsact_del_recursive(char *path){ int fsact_del_recursive(char *path){

View File

@@ -0,0 +1,62 @@
#include "keys.h"
#include "../../utils/types.h"
#include "../../libs/fatfs/ff.h"
#include "../../sec/se.h"
#include "../../mem/heap.h"
#include "../gfx/gfxutils.h"
#include "../../config/ini.h"
#include "../common/common.h"
#include <string.h>
char *getKey(const char *search, link_t *inilist){
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, inilist, link){
if (ini_sec->type == INI_CHOICE){
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
{
if (!strcmp(search, kv->key))
return kv->val;
}
}
}
return NULL;
}
u8 getHexSingle(const char c) {
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
}
u8 *getHex(const char *in){
u32 len = strlen(in), count = 0;
u8 *out = calloc(len / 2, sizeof(u8));
for (u32 i = 0; i < len; i += 2){
out[count++] = (u8)(getHexSingle(in[i]) << 4) | (getHexSingle(in[i + 1]));
}
return out;
}
u8 *GetKey(const char *keypath, const char *keyName){
LIST_INIT(inilist);
char *key;
u8 *hex = NULL;
if (!ini_parse(&inilist, keypath, false)){
gfx_errDisplay("GetKey", ERR_INI_PARSE_FAIL, 1);
goto out_free;
}
if ((key = getKey(keyName, &inilist)) == NULL){
gfx_errDisplay("GetKey", ERR_INI_PARSE_FAIL, 2);
goto out_free;
}
hex = getHex(key);
out_free:;
list_empty(&inilist);
return hex;
}

View File

@@ -0,0 +1,4 @@
#pragma once
#include "../../utils/types.h"
u8 *GetKey(const char *keypath, const char *keyName);

View File

@@ -0,0 +1,46 @@
#include "nca.h"
#include "keys.h"
#include "../../utils/types.h"
#include "../../libs/fatfs/ff.h"
#include "../../sec/se.h"
#include "../../mem/heap.h"
#include "../gfx/gfxutils.h"
#include "../../config/ini.h"
#include "../common/common.h"
#include <string.h>
int SetHeaderKey(){
u8 *header_key = GetKey("sd:/switch/prod.keys", "header_key");
if (header_key == NULL)
return -1;
se_aes_key_set(4, header_key + 0x00, 0x10);
se_aes_key_set(5, header_key + 0x10, 0x10);
return 0;
}
int GetNcaType(char *ncaPath){
FIL fp;
u32 read_bytes = 0;
if (f_open(&fp, ncaPath, FA_READ | FA_OPEN_EXISTING))
return -1;
u8 *dec_header = (u8*)malloc(0x600);
if (f_lseek(&fp, 0x200) || f_read(&fp, dec_header, 32, &read_bytes) || read_bytes != 32){
f_close(&fp);
free(dec_header);
return -1;
}
se_aes_xts_crypt(5,4,0,1,dec_header + 0x200, dec_header, 32, 1);
u8 ContentType = dec_header[0x205];
f_close(&fp);
free(dec_header);
return ContentType;
}

View File

@@ -0,0 +1,4 @@
#pragma once
int GetNcaType(char *ncaPath);
int SetHeaderKey();

View File

@@ -1,4 +1,5 @@
#include "savesign.h" #include "savesign.h"
#include "keys.h"
#include "../../utils/types.h" #include "../../utils/types.h"
#include "../../libs/fatfs/ff.h" #include "../../libs/fatfs/ff.h"
#include "../../sec/se.h" #include "../../sec/se.h"
@@ -62,62 +63,15 @@ out_free:;
return success; return success;
} }
char *getKey(const char *search, link_t *inilist){
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, inilist, link){
if (ini_sec->type == INI_CHOICE){
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
{
if (!strcmp(search, kv->key))
return kv->val;
}
}
}
return NULL;
}
u8 getHexSingle(const char c) {
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
}
u8 *getHex(const char *in){
u32 len = strlen(in), count = 0;
u8 *out = calloc(len / 2, sizeof(u8));
for (u32 i = 0; i < len; i += 2){
out[count++] = (u8)(getHexSingle(in[i]) << 4) | (getHexSingle(in[i + 1]));
}
return out;
}
bool save_sign(const char *keypath, const char *savepath){ bool save_sign(const char *keypath, const char *savepath){
LIST_INIT(inilist); u8 *key = GetKey(keypath, "save_mac_key");
char *key;
u8 *hex;
bool success = false;
if (!ini_parse(&inilist, keypath, false)){ if (key == NULL){
gfx_errDisplay("save_sign", ERR_INI_PARSE_FAIL, 1); return false;
goto out_free;
} }
if ((key = getKey("save_mac_key", &inilist)) == NULL){ if (!save_commit(savepath, key))
gfx_errDisplay("save_sign", ERR_INI_PARSE_FAIL, 2); return false;
goto out_free;
}
hex = getHex(key); return true;
if (!save_commit(savepath, hex))
goto out_free;
success = true;
out_free:;
list_empty(&inilist);
return success;
} }

View File

@@ -23,7 +23,7 @@ void gfx_clearscreen(){
gfx_boxGrey(0, 703, 1279, 719, 0xFF); gfx_boxGrey(0, 703, 1279, 719, 0xFF);
gfx_boxGrey(0, 0, 1279, 15, 0xFF); gfx_boxGrey(0, 0, 1279, 15, 0xFF);
gfx_con_setpos(0, 0); gfx_con_setpos(0, 0);
gfx_printf("Tegraexplorer v2.0.2 | Battery: %3d%%\n", battery >> 8); gfx_printf("Tegraexplorer v2.0.4 | Battery: %3d%%\n", battery >> 8);
RESETCOLOR; RESETCOLOR;
} }

View File

@@ -18,6 +18,9 @@ extern bool sd_inited;
#pragma GCC optimize ("O2") #pragma GCC optimize ("O2")
void _printentry(menu_entry *entry, bool highlighted, bool refresh, const char *path){ void _printentry(menu_entry *entry, bool highlighted, bool refresh, const char *path){
if (entry->isHide)
return;
u32 color = (entry->isMenu) ? entry->storage : ((entry->isDir) ? COLOR_WHITE : COLOR_VIOLET); u32 color = (entry->isMenu) ? entry->storage : ((entry->isDir) ? COLOR_WHITE : COLOR_VIOLET);
SWAPALLCOLOR((highlighted) ? COLOR_DEFAULT : color, (highlighted) ? color : COLOR_DEFAULT); SWAPALLCOLOR((highlighted) ? COLOR_DEFAULT : color, (highlighted) ? color : COLOR_DEFAULT);
@@ -62,7 +65,7 @@ void _printentry(menu_entry *entry, bool highlighted, bool refresh, const char *
bool disableB = false; bool disableB = false;
int menu_make(menu_entry *entries, int amount, const char *toptext){ int menu_make(menu_entry *entries, int amount, const char *toptext){
int currentpos = 0, offset = 0, delay = 300, minscreen = 0, maxscreen = 39, calculatedamount = 0; int currentpos = 0, offset = 0, delay = 300, minscreen = 0, calculatedamount = 0, cursub = 0, temp;
u32 scrolltimer, timer, sideY; u32 scrolltimer, timer, sideY;
bool refresh = true; bool refresh = true;
Inputs *input = hidRead(); Inputs *input = hidRead();
@@ -95,56 +98,53 @@ int menu_make(menu_entry *entries, int amount, const char *toptext){
gfx_sideprintf("\n\n\n"); gfx_sideprintf("\n\n\n");
} }
gfx_drawScrollBar(minscreen, maxscreen, amount); for (;;){
while (!(input->a)){
gfx_con_setpos(0, 48); gfx_con_setpos(0, 48);
timer = get_tmr_ms(); timer = get_tmr_ms();
if (!currentpos){ if (!currentpos)
while (currentpos < amount && entries[currentpos].property & (ISSKIP | ISHIDE)) cursub = 1;
currentpos++; else if (currentpos == amount - 1)
} cursub = -1;
if (currentpos == amount - 1){ else
while (currentpos >= 1 && entries[currentpos].property & (ISSKIP | ISHIDE)) cursub = 0;
currentpos--;
} while (entries[currentpos].property & (ISSKIP | ISHIDE))
currentpos += cursub;
if (currentpos > maxscreen){ if (currentpos > (minscreen + SCREENMAXOFFSET)){
offset += currentpos - maxscreen; offset += currentpos - (minscreen + SCREENMAXOFFSET);
minscreen += currentpos - maxscreen; minscreen += currentpos - (minscreen + SCREENMAXOFFSET);
maxscreen += currentpos - maxscreen;
refresh = true; refresh = true;
} }
else if (currentpos < minscreen){
if (currentpos < minscreen){
offset -= minscreen - currentpos; offset -= minscreen - currentpos;
maxscreen -= minscreen - currentpos; minscreen -= minscreen - currentpos;
minscreen -= minscreen - currentpos; refresh = true;
refresh = true;
} }
if (refresh || currentfolder == NULL || !calculatedamount){ if (refresh || currentfolder == NULL || !calculatedamount){
for (int i = 0 + offset; i < amount && i < 40 + offset; i++) for (int i = 0 + offset; i < amount && i < SCREENMAXOFFSET + 1 + offset; i++)
if (!(entries[i].isHide)) _printentry(&entries[i], (i == currentpos), refresh, toptext);
_printentry(&entries[i], (i == currentpos), refresh, toptext);
} }
else { else {
if (currentpos - minscreen > 0){ temp = (currentpos - minscreen > 0) ? 0 : 16;
gfx_con_setpos(0, 32 + (currentpos - minscreen) * 16); gfx_con_setpos(0, 32 + temp + (currentpos - minscreen) * 16);
if (!temp)
_printentry(&entries[currentpos - 1], false, false, toptext); _printentry(&entries[currentpos - 1], false, false, toptext);
}
else
gfx_con_setpos(0, 48 + (currentpos - minscreen) * 16);
_printentry(&entries[currentpos], true, false, toptext); _printentry(&entries[currentpos], true, false, toptext);
if (currentpos < amount - 1 && currentpos < maxscreen) if (currentpos < MIN(amount - 1, minscreen + SCREENMAXOFFSET))
_printentry(&entries[currentpos + 1], false, false, toptext); _printentry(&entries[currentpos + 1], false, false, toptext);
} }
RESETCOLOR; RESETCOLOR;
sideY = gfx_sideGetY(); sideY = gfx_sideGetY();
if (!(entries[currentpos].isMenu)){ if (!(entries[currentpos].isMenu)){
gfx_sideprintf("Current selection:\n"); gfx_sideprintf("Current selection:\n");
@@ -158,12 +158,14 @@ int menu_make(menu_entry *entries, int amount, const char *toptext){
gfx_boxGrey(800, sideY, 1279, sideY + 48, 0x1B); gfx_boxGrey(800, sideY, 1279, sideY + 48, 0x1B);
gfx_con_setpos(0, 703); gfx_con_setpos(0, 703);
SWAPCOLOR(COLOR_DEFAULT); SWAPALLCOLOR(COLOR_DEFAULT, COLOR_WHITE);
SWAPBGCOLOR(COLOR_WHITE);
gfx_printf("Time taken for screen draw: %dms ", get_tmr_ms() - timer); gfx_printf("Time taken for screen draw: %dms ", get_tmr_ms() - timer);
if (refresh) if (refresh)
gfx_drawScrollBar(minscreen, maxscreen, amount); gfx_drawScrollBar(minscreen, minscreen + SCREENMAXOFFSET, amount);
refresh = false;
while (hidRead()->buttons & (KEY_B | KEY_A)); while (hidRead()->buttons & (KEY_B | KEY_A));
@@ -181,14 +183,12 @@ int menu_make(menu_entry *entries, int amount, const char *toptext){
delay = 300; delay = 300;
continue; continue;
} }
if (input->buttons & (KEY_RDOWN | KEY_RUP)){ if (input->buttons & (KEY_RDOWN | KEY_RUP)){
delay = 1; delay = 1;
input->Lup = input->Rup; input->Lup = input->Rup;
input->Ldown = input->Rdown; input->Ldown = input->Rdown;
} }
if (delay < 300){ if (delay < 300){
if (scrolltimer + delay < get_tmr_ms()){ if (scrolltimer + delay < get_tmr_ms()){
@@ -200,27 +200,32 @@ int menu_make(menu_entry *entries, int amount, const char *toptext){
} }
} }
if (delay > 46)
delay -= 45;
if (input->Lup && currentpos >= 1){ if (input->a){
currentpos--; break;
while(entries[currentpos].property & (ISSKIP | ISHIDE) && currentpos >= 1) }
currentpos--; if (input->b && !disableB){
}
else if (input->Ldown && currentpos < amount - 1){
currentpos++;
while(entries[currentpos].property & (ISSKIP | ISHIDE) && currentpos < amount - 1)
currentpos++;
}
else if (input->b && !disableB){
currentpos = 0; currentpos = 0;
break; break;
} }
refresh = false;
if (delay > 46)
delay -= 45;
if (input->Lup && currentpos > 0)
cursub = -1;
else if (input->Ldown && currentpos < amount - 1)
cursub = 1;
else
cursub = 0;
if (cursub){
do {
currentpos += cursub;
} while (currentpos < amount - 1 && currentpos > 0 && entries[currentpos].property & (ISSKIP | ISHIDE));
}
} }
minerva_periodic_training(); minerva_periodic_training();

View File

@@ -1,4 +1,6 @@
#pragma once #pragma once
#include "../common/types.h" #include "../common/types.h"
#define SCREENMAXOFFSET 39
int menu_make(menu_entry *entries, int amount, const char *toptext); int menu_make(menu_entry *entries, int amount, const char *toptext);

View File

@@ -60,7 +60,10 @@ void MainMenu_Tools(){
displaygpio(); displaygpio();
break; break;
case TOOLS_DUMPFIRMWARE: case TOOLS_DUMPFIRMWARE:
dumpfirmware(SYSMMC); res = menu_make(fwDump_typeMenu, 4, "-- Fw Type --");
if (res >= 2)
dumpfirmware(SYSMMC, (res == 2));
break; break;
} }
} }

View File

@@ -288,6 +288,7 @@ int part_Pause(){
str_int_add("@BTN_DOWN", input->Ldown); str_int_add("@BTN_DOWN", input->Ldown);
str_int_add("@BTN_LEFT", input->Lleft); str_int_add("@BTN_LEFT", input->Lleft);
str_int_add("@BTN_RIGHT", input->Lright); str_int_add("@BTN_RIGHT", input->Lright);
str_int_add("@JOYCONN", hidConnected());
return input->buttons; return input->buttons;
} }
@@ -550,7 +551,59 @@ int part_getPos(){
return (int)f_tell(&scriptin); return (int)f_tell(&scriptin);
} }
int part_subString(){
char *str, *sub;
int start, size;
if (parseStringInput(argv[0], &str))
return INFUNC_FAIL;
if (parseIntInput(argv[1], &start))
return INFUNC_FAIL;
if (parseIntInput(argv[2], &size))
return INFUNC_FAIL;
if (argv[3][0] != '$')
return INFUNC_FAIL;
if (start >= strlen(str))
return INFUNC_FAIL;
sub = utils_copyStringSize(str + start, size);
str_str_add(argv[3], sub);
free(sub);
return 0;
}
int part_inputString(){
char *start, *out;
int len;
if (parseStringInput(argv[0], &start))
return INFUNC_FAIL;
if (parseIntInput(argv[1], &len))
return INFUNC_FAIL;
if (argv[2][0] != '$')
return INFUNC_FAIL;
if (len > 39)
return INFUNC_FAIL;
out = utils_InputText(start, len);
if (out == NULL)
return 1;
str_str_add(argv[2], out);
free(out);
return 0;
}
int part_strLen(){
char *in;
if (parseStringInput(argv[0], &in))
return INFUNC_FAIL;
return strlen(in);
}
str_fnc_struct functions[] = { str_fnc_struct functions[] = {
{"printf", part_printf, 255}, {"printf", part_printf, 255},
@@ -568,6 +621,9 @@ str_fnc_struct functions[] = {
{"setColor", part_setColor, 1}, {"setColor", part_setColor, 1},
{"combineStrings", part_addstrings, 3}, {"combineStrings", part_addstrings, 3},
{"compareStrings", part_stringcompare, 2}, {"compareStrings", part_stringcompare, 2},
{"subString", part_subString, 4},
{"inputString", part_inputString, 3},
{"stringLength", part_strLen, 1},
{"invert", part_invert, 1}, {"invert", part_invert, 1},
{"fs_exists", part_fs_exists, 1}, {"fs_exists", part_fs_exists, 1},
{"fs_move", part_fs_Move, 2}, {"fs_move", part_fs_Move, 2},

View File

@@ -16,15 +16,15 @@
#include "variables.h" #include "variables.h"
#include "../fs/fsreader.h" #include "../fs/fsreader.h"
#include "../utils/utils.h" #include "../utils/utils.h"
#include "../../hid/hid.h"
u32 countchars(char* in, char target) { int countchars(const char* in, char target) {
u32 len = strlen(in); u32 len = strlen(in);
u32 count = 0; u32 count = 0;
for (u32 i = 0; i < len; i++) { for (u32 i = 0; i < len; i++) {
if (in[i] == '"'){ if (in[i] == '"'){
i++; while (in[++i] != '"'){
while (in[i] != '"'){
i++;
if (i >= len) if (i >= len)
return -1; return -1;
} }
@@ -32,55 +32,55 @@ u32 countchars(char* in, char target) {
if (in[i] == target) if (in[i] == target)
count++; count++;
} }
return count; return count;
} }
char **argv = NULL; char **argv = NULL;
u32 argc; u32 argc;
u32 splitargs(char* in) { u32 splitargs(const char* in) {
// arg like '5, "6", @arg7' // arg like '5, "6", @arg7'
u32 i, current = 0, count = 1, len = strlen(in), curcount = 0; u32 i = 0, count = 1, len = strlen(in), curcount = 0, begin, end;
if ((count += countchars(in, ',')) < 0){ count += countchars(in, ',');
if (!count)
return 0; return 0;
}
/*
if (argv != NULL) {
for (i = 0; argv[i] != NULL; i++)
free(argv[i]);
free(argv);
}
*/
argv = calloc(count + 1, sizeof(char*));
for (i = 0; i < count; i++)
argv[i] = calloc(96, sizeof(char));
argv = calloc(count + 1, sizeof(char*));
for (i = 0; i < len && curcount < count; i++) {
if (in[i] == ',') { while (i < len && curcount < count) {
curcount++; if (in[i] == ' ' || in[i] == ','){
current = 0;
}
else if (in[i] == '@' || in[i] == '$') {
while (strrchr(", )", in[i]) == NULL && i < len) {
argv[curcount][current++] = in[i++];
}
i--;
}
//else if ((in[i] >= '0' && in[i] <= '9') || (in[i] >= '<' && in[i] <= '>') || in[i] == '+' || in[i] == '-' || in[i] == '*' || in[i] == '/')
else if (strrchr("0123456789<=>+-*/", in[i]) != NULL)
argv[curcount][current++] = in[i];
else if (in[i] == '"') {
i++; i++;
while (in[i] != '"') { continue;
argv[curcount][current++] = in[i++];
}
} }
begin = i;
while (strrchr(" ,)", in[i]) == NULL){
if (in[i] == '"'){
begin = i + 1;
while (in[++i] != '"'){
if (in[i] == '\0')
return 0;
}
}
if (in[i] == '\0')
return 0;
i++;
}
end = i;
if (in[i - 1] == '"'){
end--;
}
argv[curcount++] = utils_copyStringSize(in + begin, (u32)(end - begin));
} }
return count; return curcount;
} }
FIL scriptin; FIL scriptin;
@@ -202,17 +202,6 @@ void mainparser(){
getnextvalidchar(); getnextvalidchar();
} }
/*
if (currentchar == '?'){
char *jumpname;
jumpname = readtilchar(';', ' ');
getnextchar();
str_jmp_add(jumpname, f_tell(&scriptin));
getfollowingchar('\n');
return;
}
*/
functionparser(); functionparser();
res = run_function(funcbuff, &out); res = run_function(funcbuff, &out);
@@ -297,6 +286,7 @@ void runScript(char *path){
//add builtin vars //add builtin vars
str_int_add("@EMUMMC", emu_cfg.enabled); str_int_add("@EMUMMC", emu_cfg.enabled);
str_int_add("@RESULT", 0); str_int_add("@RESULT", 0);
str_int_add("@JOYCONN", hidConnected());
str_str_add("$CURRENTPATH", currentpath); str_str_add("$CURRENTPATH", currentpath);
//str_int_printall(); //str_int_printall();

View File

@@ -17,6 +17,7 @@
#include "../fs/fsutils.h" #include "../fs/fsutils.h"
#include "../../mem/heap.h" #include "../../mem/heap.h"
#include "../utils/utils.h" #include "../utils/utils.h"
#include "../fs/nca.h"
extern bool sd_mount(); extern bool sd_mount();
extern void sd_unmount(); extern void sd_unmount();
@@ -93,7 +94,9 @@ void displaygpio(){
} }
} }
int dumpfirmware(int mmc){
// bad code ahead aaaa
int dumpfirmware(int mmc, bool daybreak){
DIR dir; DIR dir;
FILINFO fno; FILINFO fno;
bool fail = false; bool fail = false;
@@ -107,6 +110,22 @@ int dumpfirmware(int mmc){
connect_mmc(mmc); connect_mmc(mmc);
mount_mmc("SYSTEM", 2); mount_mmc("SYSTEM", 2);
if (daybreak){
if (!fsutil_checkfile("sd:/switch/prod.keys")){
SWAPCOLOR(COLOR_RED);
gfx_printf("prod.keys not found.\nPress any button to exit");
hidWait();
return true;
}
if (SetHeaderKey()){
SWAPCOLOR(COLOR_RED);
gfx_printf("Failed to find header key.\nPress any button to exit");
hidWait();
return true;
}
}
gfx_printf("PKG1 version: %d\n", pkg1.ver); gfx_printf("PKG1 version: %d\n", pkg1.ver);
gfx_printf("Creating folders...\n"); gfx_printf("Creating folders...\n");
@@ -115,7 +134,24 @@ int dumpfirmware(int mmc){
sdbase = calloc(32 + strlen(pkg1.id), sizeof(char)); sdbase = calloc(32 + strlen(pkg1.id), sizeof(char));
sprintf(sdbase, "sd:/tegraexplorer/Firmware/%d (%s)", pkg1.ver, pkg1.id); sprintf(sdbase, "sd:/tegraexplorer/Firmware/%d (%s)", pkg1.ver, pkg1.id);
gfx_printf("Out: %s\n", sdbase);
if (fsutil_checkfile(sdbase)){
SWAPCOLOR(COLOR_RED);
gfx_printf("Destination folder already exists.\nPress X to delete this folder, any other button to cancel\nPath: %s", sdbase);
Inputs *input = hidWait();
if (!input->x){
free(sdbase);
return true;
}
else {
SWAPCOLOR(COLOR_WHITE);
gfx_printf("\nDeleting folder..\n");
fsact_del_recursive(sdbase);
}
}
gfx_printf("\rOut: %s\n", sdbase);
f_mkdir(sdbase); f_mkdir(sdbase);
if ((ret = f_opendir(&dir, sysbase))) if ((ret = f_opendir(&dir, sysbase)))
@@ -127,16 +163,39 @@ int dumpfirmware(int mmc){
printerrors = 0; printerrors = 0;
while(!f_readdir(&dir, &fno) && fno.fname[0] && !fail){ while(!f_readdir(&dir, &fno) && fno.fname[0] && !fail){
utils_copystring(fsutil_getnextloc(sdbase, fno.fname), &sdpath);
utils_copystring(fsutil_getnextloc(sysbase, fno.fname), &syspathtemp); utils_copystring(fsutil_getnextloc(sysbase, fno.fname), &syspathtemp);
if (fno.fattrib & AM_DIR){ if (fno.fattrib & AM_DIR){
utils_copystring(fsutil_getnextloc(syspathtemp, "00"), &syspath); utils_copystring(fsutil_getnextloc(syspathtemp, "00"), &syspath);
free(syspathtemp);
} }
else else
syspath = syspathtemp; syspath = syspathtemp;
if (daybreak){
u8 ContentType = GetNcaType(syspath);
if (ContentType < 0){
fail = true;
continue;
}
char *temp;
utils_copystring(fsutil_getnextloc(sdbase, fno.fname), &temp);
if (ContentType == 0x01){
sdpath = calloc(strlen(temp) + 6, 1);
strcpy(sdpath, temp);
memcpy(sdpath + strlen(temp) - 4, ".cnmt.nca", 10);
free(temp);
}
else {
sdpath = temp;
}
}
else
utils_copystring(fsutil_getnextloc(sdbase, fno.fname), &sdpath);
ret = fsact_copy(syspath, sdpath, 0); ret = fsact_copy(syspath, sdpath, 0);
gfx_printf("%d %s\r", ++amount, fno.fname); gfx_printf("%d %s\r", ++amount, fno.fname);
@@ -145,7 +204,9 @@ int dumpfirmware(int mmc){
fail = true; fail = true;
free(sdpath); free(sdpath);
free(syspath); free(syspathtemp);
if (syspath != syspathtemp)
free(syspath);
} }
printerrors = 1; printerrors = 1;

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include "../../utils/types.h"
void displayinfo(); void displayinfo();
void displaygpio(); void displaygpio();
int format(int mode); int format(int mode);
int dumpfirmware(int mmc); int dumpfirmware(int mmc, bool daybreak);

View File

@@ -192,4 +192,14 @@ char *utils_InputText(char *start, int maxLen){
} }
return buff; return buff;
}
char *utils_copyStringSize(const char *in, int size){
if (size > strlen(in) || size < 0)
size = strlen(in);
char *out = calloc(size + 1, 1);
//strncpy(out, in, size);
memcpy(out, in, size);
return out;
} }

View File

@@ -23,4 +23,5 @@ typedef struct _bmp_t
int utils_mmcMenu(); int utils_mmcMenu();
void utils_copystring(const char *in, char **out); void utils_copystring(const char *in, char **out);
char *utils_InputText(char *start, int maxLen); char *utils_InputText(char *start, int maxLen);
void utils_takeScreenshot(); void utils_takeScreenshot();
char *utils_copyStringSize(const char *in, int size);