Compare commits

..

30 Commits
2.0.1 ... dev

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
a8e86c2de3 Don't forget to take results 2020-05-17 23:42:53 +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
Such Meme, Many Skill
6934e1422f Various improvements to scripting lang
- Errors will now be more precise, there are now 2 separate errors for a function lookup failure and a failure inside a function
- Errors will now show which line number they failed at, instead of the character offset
- Minus values are not considered errors anymore, however, printing them does not work well
- Gotos now make a @RETURN variable to make making functions easier
2020-05-15 20:17:31 +02:00
Such Meme, Many Skill
f49245e4ab Fix hidden copies messing with screen positions 2020-05-15 16:20:52 +02:00
Such Meme, Many Skill
9075f20854 Clean up bisfile extraction 2020-05-15 16:07:23 +02:00
Such Meme, Many Skill
6bc474a981 Bump version 2020-05-10 21:56:11 +02:00
Such Meme, Many Skill
91536268ad Fix compiling issues (hopefully) 2020-05-10 21:51:30 +02:00
Such Meme, Many Skill
b484dc11d8 Hopefully fix partitioning issues & clean up menu control code 2020-05-10 11:41:16 +02:00
Such Meme, Many Skill
14a3a39c01 Remove dumping user saves from tools
This has been replaced by a script: https://github.com/suchmememanyskill/TegraScript/blob/master/scripts/savedumper.te
2020-05-09 13:52:46 +02:00
Such Meme, Many Skill
6868ef3536 Reset print pos after copying a file 2020-05-09 12:21:34 +02:00
Such Meme, Many Skill
97810335ed fix a bug that basically has no effect
thanks shchmue for pointing that out :smug:
2020-05-09 00:26:02 +02:00
Such Meme, Many Skill
43617ef511 Add save signing 2020-05-09 00:22:35 +02:00
Such Meme, Many Skill
19fe7f15a9 Fix (not) asking to make sure to flash in scripts 2020-05-08 20:57:26 +02:00
Such Meme, Many Skill
73ca98c6a8 Merge remote-tracking branch 'origin/master' 2020-05-04 22:36:13 +02:00
Such Meme, Many Skill
12eecd2466 Update readme 2020-05-04 22:36:07 +02:00
suchmememanyskill
40cb293db3 Try no.4 2020-05-04 21:54:39 +02:00
suchmememanyskill
f09a098c77 Try no.3 2020-05-04 21:35:29 +02:00
suchmememanyskill
30f0e88d0a Attempt no.2 2020-05-04 21:32:05 +02:00
suchmememanyskill
c4c5d57af3 Test github actions 2020-05-04 21:24:49 +02:00
63 changed files with 1436 additions and 418 deletions

36
.github/workflows/builder.yml vendored Normal file
View File

@@ -0,0 +1,36 @@
name: TegraExplorer builder
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install devkitpro
run: |
wget https://github.com/devkitPro/pacman/releases/download/devkitpro-pacman-1.0.1/devkitpro-pacman.deb
sudo dpkg -i devkitpro-pacman.deb
sudo dkp-pacman -S switch-dev --noconfirm
sudo dkp-pacman -S devkitARM --noconfirm
- name: Build TegraExplorer
run: |
echo # SETTING PATH #
export DEVKITPRO=/opt/devkitpro
export DEVKITARM=${DEVKITPRO}/devkitARM
export DEVKITPPC=${DEVKITPRO}/devkitPPC
export PATH=${DEVKITPRO}/tools/bin:$PATH
echo # MAKE #
make -j$(nproc)
- uses: actions/upload-artifact@master
with:
name: TegraExplorer
path: output/TegraExplorer.bin

View File

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

View File

@@ -1,33 +1,67 @@
# TegraExplorer
[![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
1. Get your favorite payload injector
2. Inject TegraExplorer as a payload
Navigate around the menus using the vol+, vol- and power buttons
Navigate around the menus using the joycons.
- A: Select
- B: Back
- Left Joystick up/down (Dpad or joystick): navigate menus up/down
- Right Joystick up/down: fast menu navigation up/down
- Capture (Minerva only): Take a screenshot
- L3/R3 (Press joysticks in): Recalibrate centerpoint
If you do not have your joycons connected:
- Power -> A
- Vol+ -> Left Joystick up
- Vol- -> Left Joystick down
## Functions
- Navigate the SD card
- Navigate the System partition of your sysnand/sysmmc
- Navigate the System partition of your sysmmc and emummc
- Interact with files
- Deleting, copying or moving files
- Deleting, copying, renaming and moving files
- Launching payloads files
- Viewing the hex data of a file
- Launching special [TegraScript](https://github.com/suchmememanyskill/TegraScript) files
- Renaming files
- Interacting with folders
- Deleting or copying folders
- Deleting, copying or renaming folders
- Creating folders
- Dumping your current firmware to sd
- Formatting the sd card
*and more*
## Support
For general CFW support, go to the [Nintendo Homebrew](https://discord.gg/C29hYvh) discord
For question specifically for TegraExplorer, go to [my discord](https://discord.gg/aH9rsuP)
# Credits
## Credits
Based on [Lockpick_RCM](https://github.com/shchmue/Lockpick_RCM), and thus also based on [Hekate](https://github.com/CTCaer/hekate)
Lots of help from:
Awesome people who helped with this project:
- shchmue
- Denn
- Dennthecafebabe
Other awesome people:
- PhazonicRidley
- Dax
- Huhen
- Bleck9999
- Exelix
- Emmo
## Screenshots
![Preview](/preview.png)

View File

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

View File

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

View File

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

BIN
preview.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -64,7 +64,7 @@ ini_sec_t *_ini_create_section(link_t *dst, ini_sec_t *csec, char *name, u8 type
return csec;
}
int ini_parse(link_t *dst, char *ini_path, bool is_dir)
int ini_parse(link_t *dst, const char *ini_path, bool is_dir)
{
u32 lblen;
u32 pathlen = strlen(ini_path);
@@ -73,6 +73,7 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir)
char *filelist = NULL;
FIL fp;
ini_sec_t *csec = NULL;
bool firstIniRun = true;
char *filename = (char *)malloc(256);
@@ -116,10 +117,17 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir)
do
{
if (firstIniRun){
firstIniRun = false;
strcpy(lbuf, "[Unknown]");
lblen = 9;
}
else {
// Fetch one line.
lbuf[0] = 0;
f_gets(lbuf, 512, &fp);
lblen = strlen(lbuf);
}
// Remove trailing newline. Depends on 'FF_USE_STRFUNC 2' that removes \r.
if (lblen && lbuf[lblen - 1] == '\n')

View File

@@ -43,7 +43,7 @@ typedef struct _ini_sec_t
u32 color;
} ini_sec_t;
int ini_parse(link_t *dst, char *ini_path, bool is_dir);
int ini_parse(link_t *dst, const char *ini_path, bool is_dir);
char *ini_check_payload_section(ini_sec_t *cfg);
#endif

View File

@@ -20,6 +20,9 @@
#include <string.h>
#include "gfx.h"
gfx_ctxt_t gfx_ctxt;
gfx_con_t gfx_con;
static const u8 _gfx_font[] = {
0x00, 0x0C, 0x12, 0x7E, 0x42, 0x42, 0x7E, 0x00, // Char 030 (folder)
0x00, 0x0E, 0x12, 0x22, 0x22, 0x22, 0x3E, 0x00, // Char 031 (file)
@@ -177,6 +180,8 @@ void gfx_con_setpos(u32 x, u32 y)
gfx_con.y = YLEFT - x;
}
u32 YLeftConfig = YLEFT;
void gfx_putc(char c)
{
// Duplicate code for performance reasons.
@@ -228,13 +233,13 @@ void gfx_putc(char c)
*/
gfx_con.y -= 16;
if (gfx_con.y < 16){
gfx_con.y = YLEFT;
gfx_con.y = YLeftConfig;
gfx_con.x += 16;
}
}
else if (c == '\n')
{
gfx_con.y = YLEFT;
gfx_con.y = YLeftConfig;
gfx_con.x += 16;
if (gfx_con.x > gfx_ctxt.width - 16)
gfx_con.x = 0;
@@ -244,7 +249,7 @@ void gfx_putc(char c)
else if (c == '\a')
gfx_con.y = 639;
else if (c == '\r')
gfx_con.y = YLEFT;
gfx_con.y = YLeftConfig;
break;
case 8:
@@ -270,14 +275,14 @@ void gfx_putc(char c)
gfx_con.y -= 8;
if (gfx_con.y < 8){
gfx_con.y = YLEFT;
gfx_con.y = YLeftConfig;
gfx_con.x += 8;
}
}
else if (c == '\n')
{
gfx_con.y = YLEFT;
gfx_con.y = YLeftConfig;
gfx_con.x += 8;
if (gfx_con.x > gfx_ctxt.width - 8)
gfx_con.x = 0;
@@ -287,7 +292,7 @@ void gfx_putc(char c)
else if (c == '\a')
gfx_con.y = 639;
else if (c == '\r')
gfx_con.y = YLEFT;
gfx_con.y = YLeftConfig;
break;
}
@@ -302,6 +307,46 @@ void gfx_puts(const char *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)
{
char buf[65];
@@ -378,6 +423,11 @@ void gfx_vprintf(const char *fmt, va_list ap)
}
switch(*fmt)
{
case 'b':;
u32 begin = YLEFT - va_arg(ap, u32);
YLeftConfig = begin;
gfx_con.y = begin;
break;
case 'c':
gfx_putc(va_arg(ap, u32));
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_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_puts_limit(const char *s, u32 limit);
/*
#define GFX_SETPOSCORRECTED(x, y) gfx_con_setpos(y - YLEFT, x)
@@ -61,7 +62,7 @@ void gfx_boxGrey(int x0, int y0, int x1, int y1, u8 shade);
*/
// Global gfx console and context.
gfx_ctxt_t gfx_ctxt;
gfx_con_t gfx_con;
extern gfx_ctxt_t gfx_ctxt;
extern gfx_con_t gfx_con;
#endif

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,6 +26,10 @@
#include "../gfx/gfx.h"
u32 pkg2_newkern_ini1_val;
u32 pkg2_newkern_ini1_start;
u32 pkg2_newkern_ini1_end;
/*#include "util.h"
#define DPRINTF(...) gfx_printf(__VA_ARGS__)
#define DEBUG_PRINTING*/

View File

@@ -1,6 +1,6 @@
/*
* 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
* under the terms and conditions of the GNU General Public License,
@@ -28,9 +28,17 @@
#define PKG2_NEWKERN_GET_INI1_HEURISTIC 0xD2800015 // Offset of OP + 12 is the INI1 offset.
u32 pkg2_newkern_ini1_val;
u32 pkg2_newkern_ini1_start;
u32 pkg2_newkern_ini1_end;
extern u32 pkg2_newkern_ini1_val;
extern u32 pkg2_newkern_ini1_start;
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
{
@@ -87,6 +95,12 @@ typedef struct _pkg2_kip1_info_t
link_t link;
} 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);
int pkg2_decompress_kip(pkg2_kip1_info_t* ki, u32 sectsToDecomp);
pkg2_hdr_t *pkg2_decrypt(void *data);

View File

@@ -17,15 +17,20 @@
#include <string.h>
#include "sept.h"
#include "../config/ini.h"
#include "../gfx/di.h"
#include "../hos/fss.h"
#include "../hos/hos.h"
#include "../libs/fatfs/ff.h"
#include "../mem/heap.h"
#include "../soc/hw_init.h"
#include "../soc/pmc.h"
#include "../soc/t210.h"
#include "../storage/nx_emmc.h"
#include "../storage/nx_sd.h"
#include "../storage/sdmmc.h"
#include "../utils/btn.h"
#include "../utils/list.h"
#include "../utils/types.h"
#include "../gfx/gfx.h"
@@ -58,18 +63,50 @@ u8 warmboot_reboot[] = {
extern u32 color_idx;
extern boot_cfg_t b_cfg;
extern void sd_unmount();
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)
{
FIL fp;
bool fss0_sept_used = false;
// Copy warmboot reboot code and TSEC fw.
memcpy((u8 *)(SEPT_PK1T_ADDR - WB_RST_SIZE), (u8 *)warmboot_reboot, sizeof(warmboot_reboot));
memcpy((void *)SEPT_PK1T_ADDR, tsec_fw, tsec_size);
*(vu32 *)SEPT_TCSZ_ADDR = tsec_size;
LIST_INIT(ini_sections);
if (ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false))
{
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);
found = true;
break;
}
}
}
if (found)
break;
}
}
if (!fss0_sept_used)
{
// Copy sept-primary.
if (f_open(&fp, "sd:/sept/sept-primary.bin", FA_READ))
goto error;
@@ -100,6 +137,7 @@ int reboot_to_sept(const u8 *tsec_fw, const u32 tsec_size, const u32 kb)
goto error;
}
f_close(&fp);
}
// Save auto boot config to sept payload, if any.
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;
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);
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) {
int res = 0;
u8 *pdst = (u8 *)dst;
u8 *psrc = (u8 *)src;
u8 *temptweak = (u8 *)malloc(0x10);
u32 *pdst = (u32 *)dst;
u32 *psrc = (u32 *)src;
u32 *ptweak = (u32 *)tweak;
if (regen_tweak) {
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++)
_gf256_mul_x_le(tweak);
u8 temptweak[0x10];
memcpy(temptweak, tweak, 0x10);
//We are assuming a 0x10-aligned sector size in this implementation.
for (u32 i = 0; i < secsize / 0x10; i++) {
for (u32 j = 0; j < 0x10; j++)
pdst[j] = psrc[j] ^ tweak[j];
for (u32 j = 0; j < 4; j++)
pdst[j] = psrc[j] ^ ptweak[j];
_gf256_mul_x_le(tweak);
psrc += 0x10;
pdst += 0x10;
psrc += 4;
pdst += 4;
}
se_aes_crypt_ecb(ks2, enc, dst, secsize, src, secsize);
se_aes_crypt_ecb(ks2, enc, dst, secsize, dst, secsize);
pdst = (u8 *)dst;
pdst = (u32 *)dst;
memcpy(tweak, temptweak, 0x10);
for (u32 i = 0; i < secsize / 0x10; i++) {
for (u32 j = 0; j < 0x10; j++)
pdst[j] = pdst[j] ^ tweak[j];
for (u32 j = 0; j < 4; j++)
pdst[j] = pdst[j] ^ ptweak[j];
_gf256_mul_x_le(tweak);
pdst += 0x10;
pdst += 4;
}
res = 1;
out:;
free(temptweak);
return res;
}

View File

@@ -42,8 +42,8 @@
#include "../../storage/sdmmc.h"
extern sdmmc_storage_t sd_storage;
#define EFSPRINTF(text, ...) print_error(); gfx_printf("%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF);
//#define EFSPRINTF(...)
//#define EFSPRINTF(text, ...) print_error(); gfx_printf("%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF);
#define EFSPRINTF(...)
/*--------------------------------------------------------------------------
@@ -6114,9 +6114,6 @@ FRESULT f_fdisk (
DWORD sz_disk, p_sect, b_cyl, b_sect;
FRESULT res;
BYTE *empty_buff;
empty_buff = ff_memcalloc(sizeof(BYTE), 16384);
stat = disk_initialize(pdrv);
if (stat & STA_NOINIT) return FR_NOT_READY;
if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
@@ -6169,14 +6166,14 @@ FRESULT f_fdisk (
st_dword(p + 8, b_sect); /* Start sector in LBA */
st_dword(p + 12, p_sect); /* Number of sectors */
/* Next partition */
b_sect += p_sect;
for (int cursect = 0; cursect < 1024; cursect++){
disk_write(pdrv, empty_buff, b_sect + (32 * cursect), 32);
for (u32 cursect = 0; cursect < 512; cursect++){
disk_write(pdrv, buf + 0x4000, b_sect + (64 * cursect), 64);
}
b_sect += p_sect;
}
st_word(p, 0xAA55); /* MBR signature (always at offset 510) */
ff_memfree(empty_buff);
/* Write it to the MBR */
res = (disk_write(pdrv, buf, 0, 1) == RES_OK && disk_ioctl(pdrv, CTRL_SYNC, 0) == RES_OK) ? FR_OK : FR_DISK_ERR;

View File

@@ -44,10 +44,10 @@
//#include "keys/keys.h"
sdmmc_t sd_sdmmc;
sdmmc_storage_t sd_storage;
__attribute__ ((aligned (16))) FATFS sd_fs;
bool sd_mounted, sd_inited;
//sdmmc_t sd_sdmmc;
//sdmmc_storage_t sd_storage;
//__attribute__ ((aligned (16))) FATFS sd_fs;
//bool sd_mounted, sd_inited;
volatile nyx_storage_t *nyx_str = (nyx_storage_t *)NYX_STORAGE_ADDR;
hekate_config h_cfg;
boot_cfg_t __attribute__((section ("._boot_cfg"))) b_cfg;

View File

@@ -136,7 +136,7 @@ void *malloc(u32 size)
void *calloc(u32 num, u32 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;
}

View File

@@ -27,6 +27,7 @@
#include "../soc/t210.h"
extern volatile nyx_storage_t *nyx_str;
void (*minerva_cfg)(mtc_config_t *mtc_cfg, void *);
u32 minerva_init()
{

View File

@@ -57,7 +57,7 @@ typedef enum
FREQ_1600 = 1600000
} minerva_freq_t;
void (*minerva_cfg)(mtc_config_t *mtc_cfg, void *);
extern void (*minerva_cfg)(mtc_config_t *mtc_cfg, void *);
u32 minerva_init();
void minerva_change_freq(minerva_freq_t freq);
void minerva_periodic_training();

View File

@@ -2,7 +2,7 @@
* PMIC Real Time Clock driver for Nintendo Switch's MAX77620-RTC
*
* 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
* 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.
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;
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;
// Get day of week. 1: Monday to 7: Sunday.

View File

@@ -19,6 +19,7 @@
#include <string.h>
#include "../../common/memory_map.h"
#include "../sec/se.h"
#include "../mem/heap.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)
{
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)
{
@@ -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)
{
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;
}
// 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 res = 0;
u8 *tweak = (u8 *)malloc(0x10);
u8 *pdst = (u8 *)dst;
u8 *psrc = (u8 *)src;
u8 *temptweak = (u8 *)malloc(0x10);
u32 *pdst = (u32 *)dst;
u32 *psrc = (u32 *)src;
u32 *ptweak = (u32 *)tweak;
//Generate tweak.
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))
goto out;
memcpy(temptweak, tweak, 0x10);
//We are assuming a 0x10-aligned sector size in this implementation.
for (u32 i = 0; i < secsize / 0x10; i++)
{
for (u32 j = 0; j < 0x10; j++)
pdst[j] = psrc[j] ^ tweak[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];
for (u32 j = 0; j < 4; j++)
pdst[j] = psrc[j] ^ ptweak[j];
_gf256_mul_x_le(tweak);
psrc += 0x10;
pdst += 0x10;
psrc += 4;
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;
out:;
free(temptweak);
free(tweak);
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);
u32 num_blocks = (src_size + 0xf) >> 4;
if (num_blocks > 1) {
if (num_blocks > 1)
{
SE(SE_BLOCK_COUNT_REG_OFFSET) = num_blocks - 2;
if (!_se_execute(OP_START, NULL, 0, src, src_size))
goto out;
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);
last_block[src_size & 0xf] = 0x80;
} else if (src_size >= 0x10) {
}
else if (src_size >= 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;
}
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;
u8 *secret = (u8 *)malloc(0x40);
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);
void se_key_acc_ctrl(u32 ks, u32 flags);
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_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_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_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(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);

View File

@@ -18,6 +18,7 @@
#include <string.h>
#include "../hos/hos.h"
#include "../sec/tsec.h"
#include "../sec/tsec_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();
// Configure Falcon.
//Configure Falcon.
TSEC(TSEC_DMACTL) = 0;
TSEC(TSEC_IRQMSET) =
TSEC_IRQMSET_EXT(0xFF) |
@@ -102,7 +103,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
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)
TSEC(TSEC_DMATRFBASE) = (u32)tsec_ctxt->fw >> 8;
else
@@ -126,7 +127,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
{
// Init SMMU translation for TSEC.
pdir = smmu_init_for_tsec();
smmu_init(tsec_ctxt->secmon_base);
smmu_init(0x4002B000);
// Enable SMMU
if (!smmu_is_used())
smmu_enable();
@@ -169,7 +170,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
iram = page_alloc(0x30);
memcpy(iram, tsec_ctxt->pkg1, 0x30000);
// 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);
// 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);
}
// Execute firmware.
//Execute firmware.
HOST1X(HOST1X_CH0_SYNC_SYNCPT_160) = 0x34C2E1DA;
TSEC(TSEC_STATUS) = 0;
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;
}
// Fetch result.
//Fetch result.
HOST1X(HOST1X_CH0_SYNC_SYNCPT_160) = 0;
u32 buf[4];
buf[0] = SOR1(SOR_NV_PDISP_SOR_DP_HDCP_BKSV_LSB);
@@ -274,7 +275,7 @@ out_free:;
out:;
// Disable clocks.
//Disable clocks.
clock_disable_kfuse();
clock_disable_sor1();
clock_disable_sor0();

View File

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

View File

@@ -26,7 +26,6 @@
#include "pinmux.h"
#include "pmc.h"
#include "t210.h"
#include "uart.h"
#include "../gfx/di.h"
#include "../mem/mc.h"
#include "../mem/minerva.h"
@@ -102,7 +101,7 @@ void _config_gpios()
pinmux_config_i2c(I2C_1);
pinmux_config_i2c(I2C_5);
pinmux_config_uart(UART_A);
pinmux_config_uart(0);
// Configure volume up/down as inputs.
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;
_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_i2c(I2C_1);
@@ -319,6 +313,7 @@ void config_hw()
sdram_init();
bpmp_mmu_enable();
mc_enable_ahb_redirect();
// Clear flags from PMC_SCRATCH0
PMC(APBDEV_PMC_SCRATCH0) &= ~PMC_SCRATCH0_MODE_PAYLOAD;
@@ -357,7 +352,7 @@ void reconfig_hw_workaround(bool extra_reconfig, u32 magic)
if (magic == 0xBAADF00D)
{
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();
msleep(200);

View File

@@ -32,6 +32,7 @@ extern sdmmc_storage_t sd_storage;
extern FATFS sd_fs;
extern hekate_config h_cfg;
emummc_cfg_t emu_cfg;
extern bool sd_mount();
extern void sd_unmount();

View File

@@ -47,7 +47,7 @@ typedef struct _emummc_cfg_t
int fs_ver;
} emummc_cfg_t;
emummc_cfg_t emu_cfg;
extern emummc_cfg_t emu_cfg;
bool emummc_load_cfg();
int emummc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc);

View File

@@ -25,6 +25,10 @@
bool sd_mounted = false, sd_inited = false;
static u32 sd_mode = SD_UHS_SDR82;
sdmmc_t sd_sdmmc;
sdmmc_storage_t sd_storage;
FATFS sd_fs;
u32 sd_get_mode()
{
return sd_mode;

View File

@@ -30,9 +30,9 @@ enum
SD_UHS_SDR82 = 3,
};
sdmmc_t sd_sdmmc;
sdmmc_storage_t sd_storage;
FATFS sd_fs;
extern sdmmc_t sd_sdmmc;
extern sdmmc_storage_t sd_storage;
extern FATFS sd_fs;
u32 sd_get_mode();
int sd_init_retry(bool power_cycle);

View File

@@ -21,7 +21,7 @@
#include "../utils/types.h"
#include "sdmmc_driver.h"
u32 sd_power_cycle_time_start;
extern u32 sd_power_cycle_time_start;
typedef enum _sdmmc_type
{

View File

@@ -29,6 +29,11 @@
#include "../soc/t210.h"
#include "../utils/util.h"
#pragma GCC push_options
#pragma GCC optimize ("Os")
u32 sd_power_cycle_time_start;
//#define DPRINTF(...) gfx_printf(__VA_ARGS__)
#define DPRINTF(...)
@@ -1158,6 +1163,8 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int a
return 0;
}
#pragma GCC pop_options
void sdmmc_end(sdmmc_t *sdmmc)
{
if (!sdmmc->clock_stopped)

View File

@@ -21,9 +21,11 @@ enum utils_err_codes_te_call {
ERR_EMMC_WRITE_FAILED,
ERR_FILE_TOO_BIG_FOR_DEST,
ERR_SD_EJECTED,
ERR_PARSE_FAIL,
ERR_SCRIPT_LOOKUP_FAIL,
ERR_CANNOT_COPY_FILE_TO_FS_PART,
ERR_NO_DESTINATION
ERR_NO_DESTINATION,
ERR_INI_PARSE_FAIL,
ERR_IN_FUNC
};
extern const char *utils_err_codes_te[];
@@ -58,8 +60,7 @@ extern menu_entry mainmenu_shutdown[];
enum mainmenu_tools_return {
TOOLS_DISPLAY_INFO = 1,
TOOLS_DISPLAY_GPIO,
TOOLS_DUMPFIRMWARE,
TOOLS_DUMPUSERSAVE
TOOLS_DUMPFIRMWARE
};
extern menu_entry mainmenu_tools[];
@@ -86,7 +87,8 @@ enum fs_menu_file_return {
FILE_PAYLOAD,
FILE_SCRIPT,
FILE_HEXVIEW,
FILE_DUMPBIS
FILE_DUMPBIS,
FILE_SIGN
};
extern menu_entry fs_menu_file[];
@@ -114,3 +116,5 @@ extern gpt_entry_rule gpt_fs_rules[];
extern menu_entry mmcmenu_start[];
extern menu_entry mmcmenu_filemenu[];
extern menu_entry fwDump_typeMenu[];

View File

@@ -50,9 +50,11 @@ const char *utils_err_codes_te[] = { // these start at 50
"EMMC WRITE FAILED",
"FILE TOO BIG FOR DEST",
"SD EJECTED",
"PARSING FAILED",
"FUNC LOOKUP FAIL",
"CANNOT COPY FILE TO FS PART",
"NO DESTINATION"
"NO DESTINATION",
"INI PARSE FAIL",
"ERR IN FUNC"
};
/*
const char *pkg2names[] = {

View File

@@ -25,8 +25,7 @@ menu_entry mainmenu_tools[] = {
{"Back", COLOR_WHITE, {ISMENU}},
{"\nDisplay Console Info", COLOR_GREEN, {ISMENU}},
{"Display GPIO pins", COLOR_VIOLET, {ISMENU}},
{"Dump Firmware", COLOR_BLUE, {ISMENU}},
{"Dump User Saves", COLOR_YELLOW, {ISMENU}}
{"Dump Firmware", COLOR_BLUE, {ISMENU}}
};
menu_entry mainmenu_format[] = {
@@ -53,7 +52,8 @@ menu_entry fs_menu_file[] = {
{"Launch Payload", COLOR_ORANGE, {ISMENU}},
{"Launch Script", COLOR_YELLOW, {ISMENU}},
{"View Hex", COLOR_GREEN, {ISMENU}},
{"\nExtract BIS", COLOR_YELLOW, {ISMENU}}
{"\nExtract BIS", COLOR_YELLOW, {ISMENU}},
{"Sign Save", COLOR_ORANGE, {ISMENU}}
};
menu_entry fs_menu_folder[] = {
@@ -93,3 +93,10 @@ menu_entry mmcmenu_filemenu[] = {
{"\nBack", COLOR_WHITE, {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

@@ -219,9 +219,6 @@ int dump_biskeys(){
//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;
strcpy(pkg1inf.id, pkg1_id->id);
return 0;

View File

@@ -159,7 +159,7 @@ int makeMmcMenu(short mmcType){
case 2:
if (!(clipboardhelper & ISDIR) && (clipboardhelper & OPERATIONCOPY)){
gfx_clearscreen();
if (!mmcFlashFile(clipboard, mmcType)){
if (!mmcFlashFile(clipboard, mmcType, true)){
gfx_printf("\nDone!");
hidWait();
}

View File

@@ -4,7 +4,7 @@
int emmcDumpSpecific(char *part, char *path);
int emmcDumpBoot(char *basePath);
int mmcFlashFile(char *path, short mmcType);
int mmcFlashFile(char *path, short mmcType, bool warnings);
int emmcDumpPart(char *path, sdmmc_storage_t *mmcstorage, emmc_part_t *part);
int emmcRestorePart(char *path, sdmmc_storage_t *mmcstorage, emmc_part_t *part);
int emmcRestorePart(char *path, sdmmc_storage_t *mmcstorage, emmc_part_t *part, bool warnings);

View File

@@ -17,7 +17,7 @@
extern sdmmc_storage_t storage;
extern emmc_part_t *system_part;
int emmcRestorePart(char *path, sdmmc_storage_t *mmcstorage, emmc_part_t *part){
int emmcRestorePart(char *path, sdmmc_storage_t *mmcstorage, emmc_part_t *part, bool warnings){
FIL fp;
FILINFO fno;
u8 *buf;
@@ -54,10 +54,10 @@ int emmcRestorePart(char *path, sdmmc_storage_t *mmcstorage, emmc_part_t *part){
gfx_printf("Flashing %s\n", part->name);
if (totalSize < totalSizeDest){
if (totalSize < totalSizeDest && warnings){
SWAPCOLOR(COLOR_ORANGE);
gfx_printf("File is too small for destination.\nDo you want to flash it anyway?\n\nB to Cancel\n");
u8 btnres = gfx_makewaitmenu(
u32 btnres = gfx_makewaitmenu(
"A to Confirm",
3
);
@@ -214,13 +214,13 @@ emmc_part_t *mmcFindPart(char *path, short mmcType){
return NULL;
}
int mmcFlashFile(char *path, short mmcType){
int mmcFlashFile(char *path, short mmcType, bool warnings){
emmc_part_t *part;
int res;
part = mmcFindPart(path, mmcType);
if (part != NULL){
res = emmcRestorePart(path, &storage, part);
res = emmcRestorePart(path, &storage, part, warnings);
emummc_storage_set_mmc_partition(&storage, 0);
return res;
}

View File

@@ -16,6 +16,7 @@
#include "../emmc/emmcoperations.h"
#include "../../hid/hid.h"
#include "../utils/menuUtils.h"
#include "savesign.h"
extern char *currentpath;
extern char *clipboard;
@@ -150,6 +151,7 @@ int filemenu(menu_entry file){
fs_menu_file[8].isHide = (!(strstr(file.name, ".bin") != NULL && file.size == 1) && strstr(file.name, ".rom") == NULL);
fs_menu_file[9].isHide = (strstr(file.name, ".te") == NULL);
fs_menu_file[11].isHide = (strstr(file.name, ".bis") == NULL);
fs_menu_file[12].isHide = (!!strcmp(currentpath, "emmc:/save"));
/*
SETBIT(fs_menu_file[6].property, ISHIDE, !hidConnected());
@@ -158,7 +160,7 @@ int filemenu(menu_entry file){
SETBIT(fs_menu_file[11].property, ISHIDE, strstr(file.name, ".bis") == NULL);
*/
temp = menu_make(fs_menu_file, 12, "-- File Menu --");
temp = menu_make(fs_menu_file, 13, "-- File Menu --");
switch (temp){
case FILE_COPY:
fsreader_writeclipboard(fsutil_getnextloc(currentpath, file.name), OPERATIONCOPY);
@@ -213,6 +215,17 @@ int filemenu(menu_entry file){
extract_bis_file(fsutil_getnextloc(currentpath, file.name), currentpath);
fsreader_readfolder(currentpath);
hidWait();
break;
case FILE_SIGN:
if (gfx_defaultWaitMenu("WARNING!\n\nThis should only be used if you know what signing and a save is\nDo not do this if you don't know what this does\n\nRequires you to have a prod.keys located in the switch folder\n", 5)){
gfx_clearscreen();
gfx_printf("Signing save...\n");
if (save_sign("sd:/switch/prod.keys", fsutil_getnextloc(currentpath, file.name))){
gfx_printf("Done!\nPress any key to exit");
hidWait();
}
}
break;
case -1:
return -1;

View File

@@ -15,7 +15,6 @@ int fsact_copy(const char *locin, const char *locout, u8 options){
FIL in, out;
FILINFO in_info;
u64 sizeRemaining, toCopy;
UINT temp1, temp2;
u8 *buff, toPrint = options & COPY_MODE_PRINT, toCancel = options & COPY_MODE_CANCEL;
u32 x, y, i = 11;
int res;
@@ -32,12 +31,12 @@ int fsact_copy(const char *locin, const char *locout, u8 options){
return 1;
}
if (f_stat(locin, &in_info)){
if ((res = f_stat(locin, &in_info))){
gfx_errDisplay("copy", res, 3);
return 1;
}
if (f_open(&out, locout, FA_CREATE_ALWAYS | FA_WRITE)){
if ((res = f_open(&out, locout, FA_CREATE_ALWAYS | FA_WRITE))){
gfx_errDisplay("copy", res, 4);
return 1;
}
@@ -56,19 +55,14 @@ int fsact_copy(const char *locin, const char *locout, u8 options){
while (sizeRemaining > 0){
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);
return 1;
break;
}
if ((res = f_write(&out, buff, toCopy, &temp2))){
if ((res = f_write(&out, buff, toCopy, NULL))){
gfx_errDisplay("copy", res, 6);
return 1;
}
if (temp1 != temp2){
gfx_errDisplay("copy", ERR_DISK_WRITE_FAILED, 7);
return 1;
break;
}
sizeRemaining -= toCopy;
@@ -91,19 +85,19 @@ int fsact_copy(const char *locin, const char *locout, u8 options){
}
}
if (toPrint){
RESETCOLOR;
gfx_con_setpos(x - 16, y);
}
f_close(&in);
f_close(&out);
free(buff);
if ((res = f_chmod(locout, in_info.fattrib, 0x3A))){
gfx_errDisplay("copy", res, 8);
return 1;
}
f_chmod(locout, in_info.fattrib, 0x3A);
f_stat(locin, &in_info); //somehow stops fatfs from being weird
return 0;
return res;
}
int fsact_del_recursive(char *path){

View File

@@ -13,25 +13,15 @@
#include "../utils/utils.h"
#include "fsactions.h"
u32 DecodeInt(u8* data) {
u32 out = 0;
for (int i = 0; i < 4; i++) {
out |= (data[i] << ((3 - i) * 8));
}
return out;
}
void copy_fil_size(FIL* in_src, FIL* out_src, int size_src){
u8* buff;
buff = calloc(16384, sizeof(u8));
buff = calloc(BUFSIZE, sizeof(u8));
int size = size_src;
int copysize;
while (size > 0){
copysize = MIN(16834, size);
copysize = MIN(BUFSIZE, size);
f_read(in_src, buff, copysize, NULL);
f_write(out_src, buff, copysize, NULL);
size -= copysize;
@@ -48,56 +38,50 @@ void gen_part(int size, FIL* in, char *path){
f_close(&out);
}
const char *filenames[] = {
"BOOT0.bin",
"BOOT1.bin",
"BCPKG2-1-Normal-Main",
"BCPKG2-3-SafeMode-Main",
"BCPKG2-2-Normal-Sub",
"BCPKG2-4-SafeMode-Sub"
};
int extract_bis_file(char *path, char *outfolder){
FIL in;
int res;
u8 version[0x10];
u8 args;
u8 temp[0x4];
u32 filesizes[4];
char *tempPath;
BisFile header;
if ((res = f_open(&in, path, FA_READ | FA_OPEN_EXISTING))){
gfx_errDisplay("extract_bis_file", res, 0);
return -1;
}
f_read(&in, version, 0x10, NULL);
f_read(&in, &args, 1, NULL);
f_read(&in, &header, sizeof(BisFile), NULL);
for (int i = 0; i < 4; i++)
header.sizes[i] = FLIPU32(header.sizes[i]);
gfx_printf("Version: %s\n\n", header.version);
// Loop to actually extract stuff
for (int i = 0; i < 4; i++){
f_read(&in, temp, 4, NULL);
filesizes[i] = DecodeInt(temp);
if (!(header.args & (BIT((7 - i)))))
continue;
gfx_printf("Extracting %s\n", filenames[i]);
gen_part(header.sizes[i], &in, fsutil_getnextloc(outfolder, filenames[i]));
}
gfx_printf("Version: %s\n\n", version);
// Loop to copy pkg2_1->2 and pkg2_3->4
for (int i = 4; i < 6; i++){
if (!(header.args & BIT((9 - i))))
continue;
if (args & BOOT0_ARG){
gfx_printf("\nExtracting BOOT0\n");
gen_part(filesizes[0], &in, fsutil_getnextloc(outfolder, "BOOT0.bin"));
}
if (args & BOOT1_ARG){
gfx_printf("Extracting BOOT1\n");
gen_part(filesizes[1], &in, fsutil_getnextloc(outfolder, "BOOT1.bin"));
}
if (args & BCPKG2_1_ARG){
utils_copystring(fsutil_getnextloc(outfolder, "BCPKG2-1-Normal-Main"), &tempPath);
gfx_printf("Extracting BCPKG2_1/2\n");
gen_part(filesizes[2], &in, tempPath);
fsact_copy(tempPath, fsutil_getnextloc(outfolder, "BCPKG2-2-Normal-Sub"), COPY_MODE_PRINT);
RESETCOLOR;
free(tempPath);
}
if (args & BCPKG2_3_ARG){
utils_copystring(fsutil_getnextloc(outfolder, "BCPKG2-3-SafeMode-Main"), &tempPath);
gfx_printf("Extracting BCPKG2_3/4\n");
gen_part(filesizes[3], &in, tempPath);
fsact_copy(tempPath, fsutil_getnextloc(outfolder, "BCPKG2-4-SafeMode-Sub"), COPY_MODE_PRINT);
utils_copystring(fsutil_getnextloc(outfolder, filenames[i - 2]), &tempPath);
gfx_printf("Copying %s\n", filenames[i]);
fsact_copy(tempPath, fsutil_getnextloc(outfolder, filenames[i]), COPY_MODE_PRINT);
RESETCOLOR;
free(tempPath);
}

View File

@@ -2,6 +2,14 @@
#include "../common/types.h"
#include "../../utils/types.h"
typedef struct {
u8 version[0x10];
u8 args;
u32 sizes[4];
} __attribute__((__packed__)) BisFile;
#define FLIPU32(in) ((in >> 24) & 0xFF) | ((in >> 8) & 0xFF00) | ((in << 8) & 0xFF0000) | ((in << 24) & 0xFF000000)
char *fsutil_getnextloc(const char *current, const char *add);
char *fsutil_getprevloc(char *current);
bool fsutil_checkfile(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

@@ -0,0 +1,77 @@
#include "savesign.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>
bool save_commit(const char *path, u8 *save_mac_key){
FIL file;
int res;
u8 *buf, hash[0x20], *cmac_data, cmac[0x10];
const u32 hashed_data_size = 0x3D00, cmac_data_size = 0x200;
bool success = false;
buf = malloc(hashed_data_size);
cmac_data = malloc(cmac_data_size);
if ((res = f_open(&file, path, FA_OPEN_EXISTING | FA_READ | FA_WRITE))){
gfx_errDisplay("save_commit", res, 1);
goto out_free;
}
f_lseek(&file, 0x300);
if ((res = f_read(&file, buf, hashed_data_size, NULL))){
gfx_errDisplay("save_commit", res, 2);
goto out_free;
}
se_calc_sha256(hash, buf, hashed_data_size);
f_lseek(&file, 0x108);
if ((res = f_write(&file, hash, sizeof(hash), NULL))){
gfx_errDisplay("save_commit", res, 3);
goto out_free;
}
f_lseek(&file, 0x100);
if ((res = f_read(&file, cmac_data, cmac_data_size, NULL))){
gfx_errDisplay("save_commit", res, 4);
goto out_free;
}
se_aes_key_set(3, save_mac_key, 0x10);
se_aes_cmac(3, cmac, 0x10, cmac_data, cmac_data_size);
f_lseek(&file, 0);
if ((res = f_write(&file, cmac, sizeof(cmac), NULL))){
gfx_errDisplay("save_commit", res, 5);
goto out_free;
}
success = true;
out_free:;
free(buf);
free(cmac_data);
f_close(&file);
return success;
}
bool save_sign(const char *keypath, const char *savepath){
u8 *key = GetKey(keypath, "save_mac_key");
if (key == NULL){
return false;
}
if (!save_commit(savepath, key))
return false;
return true;
}

View File

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

View File

@@ -23,7 +23,7 @@ void gfx_clearscreen(){
gfx_boxGrey(0, 703, 1279, 719, 0xFF);
gfx_boxGrey(0, 0, 1279, 15, 0xFF);
gfx_con_setpos(0, 0);
gfx_printf("Tegraexplorer v2.0.1 | Battery: %3d%%\n", battery >> 8);
gfx_printf("Tegraexplorer v2.0.4 | Battery: %3d%%\n", battery >> 8);
RESETCOLOR;
}
@@ -52,7 +52,7 @@ u32 gfx_errDisplay(const char *src_func, int err, int loc){
if (err < 15)
gfx_printf("Desc: %s\n", utils_err_codes[err]);
else if (err >= ERR_SAME_LOC && err <= ERR_NO_DESTINATION)
else if (err >= ERR_SAME_LOC && err <= ERR_IN_FUNC)
gfx_printf("Desc: %s\n", utils_err_codes_te[err - 50]);
if (loc)

View File

@@ -18,6 +18,9 @@ extern bool sd_inited;
#pragma GCC optimize ("O2")
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);
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;
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;
bool refresh = true;
Inputs *input = hidRead();
@@ -95,56 +98,53 @@ int menu_make(menu_entry *entries, int amount, const char *toptext){
gfx_sideprintf("\n\n\n");
}
gfx_drawScrollBar(minscreen, maxscreen, amount);
while (!(input->a)){
for (;;){
gfx_con_setpos(0, 48);
timer = get_tmr_ms();
if (!currentpos){
while (currentpos < amount && entries[currentpos].property & (ISSKIP | ISHIDE))
currentpos++;
}
if (currentpos == amount - 1){
while (currentpos >= 1 && entries[currentpos].property & (ISSKIP | ISHIDE))
currentpos--;
}
if (!currentpos)
cursub = 1;
else if (currentpos == amount - 1)
cursub = -1;
else
cursub = 0;
if (currentpos > maxscreen){
offset += currentpos - maxscreen;
minscreen += currentpos - maxscreen;
maxscreen += currentpos - maxscreen;
while (entries[currentpos].property & (ISSKIP | ISHIDE))
currentpos += cursub;
if (currentpos > (minscreen + SCREENMAXOFFSET)){
offset += currentpos - (minscreen + SCREENMAXOFFSET);
minscreen += currentpos - (minscreen + SCREENMAXOFFSET);
refresh = true;
}
if (currentpos < minscreen){
else if (currentpos < minscreen){
offset -= minscreen - currentpos;
maxscreen -= minscreen - currentpos;
minscreen -= minscreen - currentpos;
refresh = true;
}
if (refresh || currentfolder == NULL || !calculatedamount){
for (int i = 0 + offset; i < amount && i < 40 + offset; i++)
if (!(entries[i].isHide))
for (int i = 0 + offset; i < amount && i < SCREENMAXOFFSET + 1 + offset; i++)
_printentry(&entries[i], (i == currentpos), refresh, toptext);
}
else {
if (currentpos - minscreen > 0){
gfx_con_setpos(0, 32 + (currentpos - minscreen) * 16);
temp = (currentpos - minscreen > 0) ? 0 : 16;
gfx_con_setpos(0, 32 + temp + (currentpos - minscreen) * 16);
if (!temp)
_printentry(&entries[currentpos - 1], false, false, toptext);
}
else
gfx_con_setpos(0, 48 + (currentpos - minscreen) * 16);
_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);
}
RESETCOLOR;
sideY = gfx_sideGetY();
if (!(entries[currentpos].isMenu)){
gfx_sideprintf("Current selection:\n");
@@ -158,17 +158,19 @@ int menu_make(menu_entry *entries, int amount, const char *toptext){
gfx_boxGrey(800, sideY, 1279, sideY + 48, 0x1B);
gfx_con_setpos(0, 703);
SWAPCOLOR(COLOR_DEFAULT);
SWAPBGCOLOR(COLOR_WHITE);
SWAPALLCOLOR(COLOR_DEFAULT, COLOR_WHITE);
gfx_printf("Time taken for screen draw: %dms ", get_tmr_ms() - timer);
if (refresh)
gfx_drawScrollBar(minscreen, maxscreen, amount);
gfx_drawScrollBar(minscreen, minscreen + SCREENMAXOFFSET, amount);
refresh = false;
while (hidRead()->buttons & (KEY_B | KEY_A));
input->buttons = 0;
while (!(input->buttons & (KEY_A | KEY_LDOWN | KEY_LUP | KEY_B | KEY_RUP | KEY_RDOWN))){
scrolltimer = get_tmr_ms();
while (1){
if (sd_inited && !!gpio_read(GPIO_PORT_Z, GPIO_PIN_1)){
gfx_errDisplay("menu", ERR_SD_EJECTED, 0);
sd_unmount();
@@ -177,44 +179,53 @@ int menu_make(menu_entry *entries, int amount, const char *toptext){
input = hidRead();
if (!(input->buttons & (KEY_A | KEY_LDOWN | KEY_LUP | KEY_B | KEY_RUP | KEY_RDOWN)))
if (!(input->buttons & (KEY_A | KEY_LDOWN | KEY_LUP | KEY_B | KEY_RUP | KEY_RDOWN))){
delay = 300;
continue;
}
if (input->buttons & (KEY_RDOWN | KEY_RUP)){
delay = 1;
input->Lup = input->Rup;
input->Ldown = input->Rdown;
}
if (delay < 300){
scrolltimer = get_tmr_ms();
while (input->buttons & (KEY_A | KEY_LDOWN | KEY_LUP | KEY_B | KEY_RUP | KEY_RDOWN)){
if (scrolltimer + delay <= get_tmr_ms())
if (scrolltimer + delay < get_tmr_ms()){
break;
}
}
else {
break;
input = hidRead();
}
}
if (delay > 46 && input->buttons & (KEY_A | KEY_LDOWN | KEY_LUP | KEY_B | KEY_RUP | KEY_RDOWN))
delay -= 45;
if (input->buttons & (KEY_RUP | KEY_RDOWN))
delay = 1;
if (input->a){
break;
}
if (input->buttons & (KEY_LUP | KEY_RUP) && currentpos >= 1){
currentpos--;
while(entries[currentpos].property & (ISSKIP | ISHIDE) && currentpos >= 1)
currentpos--;
}
else if (input->buttons & (KEY_LDOWN | KEY_RDOWN) && currentpos < amount - 1){
currentpos++;
while(entries[currentpos].property & (ISSKIP | ISHIDE) && currentpos < amount - 1)
currentpos++;
}
else if (input->b && !disableB){
if (input->b && !disableB){
currentpos = 0;
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();

View File

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

View File

@@ -37,23 +37,11 @@ void MainMenu_SDCard(){
void MainMenu_EMMC(){
if (gfx_defaultWaitMenu("You're about to enter EMMC\nModifying anything here can result in a BRICK!\n\nPlease only continue if you know what you're doing", 4)){
/*
connect_mmc(SYSMMC);
if (!mount_mmc(emmc_fs_entries[res - 2], res - 1))
fileexplorer("emmc:/", 1);
*/
makeMmcMenu(SYSMMC);
}
}
void MainMenu_EMUMMC(){
/*
connect_mmc(EMUMMC);
if (!mount_mmc(emmc_fs_entries[res - 5], res - 4))
fileexplorer("emmc:/", 1);
*/
makeMmcMenu(EMUMMC);
}
@@ -62,8 +50,7 @@ void MainMenu_MountSD(){
}
void MainMenu_Tools(){
//res = makemenu(toolsmenu, 8);
res = menu_make(mainmenu_tools, 5, "-- Tools Menu --");
res = menu_make(mainmenu_tools, 4, "-- Tools Menu --");
switch(res){
case TOOLS_DISPLAY_INFO:
@@ -71,21 +58,17 @@ void MainMenu_Tools(){
break;
case TOOLS_DISPLAY_GPIO:
displaygpio();
//makeMmcMenu(SYSMMC);
break;
case TOOLS_DUMPFIRMWARE:
dumpfirmware(SYSMMC);
break;
case TOOLS_DUMPUSERSAVE:
if ((res = utils_mmcMenu()) > 0)
dumpusersaves(res);
res = menu_make(fwDump_typeMenu, 4, "-- Fw Type --");
if (res >= 2)
dumpfirmware(SYSMMC, (res == 2));
break;
}
}
void MainMenu_SDFormat(){
//res = makemenu(formatmenu, 4);
res = menu_make(mainmenu_format, 3, "-- Format Menu --");
if (res > 0){

View File

@@ -74,14 +74,14 @@ int part_printf(){
if (argv[i][0] == '@'){
int toprintint;
if (parseIntInput(argv[i], &toprintint))
return -1;
return INFUNC_FAIL;
gfx_printf("%d", toprintint);
}
else {
char *toprintstring;
if (parseStringInput(argv[i], &toprintstring))
return -1;
return INFUNC_FAIL;
gfx_printf(toprintstring);
}
@@ -94,7 +94,7 @@ int part_printf(){
int part_print_int(){
int toprint;
if (parseIntInput(argv[0], &toprint))
return -1;
return INFUNC_FAIL;
SWAPCOLOR(currentcolor);
gfx_printf("%s: %d\n", argv[0], toprint);
@@ -107,7 +107,7 @@ int part_Wait(){
SWAPCOLOR(currentcolor);
if (parseIntInput(argv[0], &arg))
return -1;
return INFUNC_FAIL;
begintime = get_tmr_s();
@@ -122,9 +122,9 @@ int part_Wait(){
int part_Check(){
int left, right;
if (parseIntInput(argv[0], &left))
return -1;
return INFUNC_FAIL;
if (parseIntInput(argv[2], &right))
return -1;
return INFUNC_FAIL;
if (!strcmp(argv[1], "=="))
return (left == right);
@@ -139,13 +139,13 @@ int part_Check(){
else if (!strcmp(argv[1], "<"))
return (left < right);
else
return -1;
return INFUNC_FAIL;
}
int part_if(){
int condition;
if (parseIntInput(argv[0], &condition))
return -1;
return INFUNC_FAIL;
getfollowingchar('{');
@@ -167,7 +167,7 @@ int part_if(){
int part_if_args(){
int condition;
if ((condition = part_Check()) < 0)
return -1;
return INFUNC_FAIL;
getfollowingchar('{');
@@ -180,9 +180,9 @@ int part_if_args(){
int part_Math(){
int left, right;
if (parseIntInput(argv[0], &left))
return -1;
return INFUNC_FAIL;
if (parseIntInput(argv[2], &right))
return -1;
return INFUNC_FAIL;
switch (argv[1][0]){
case '+':
@@ -194,7 +194,7 @@ int part_Math(){
case '/':
return left / right;
}
return -1;
return INFUNC_FAIL;
}
int part_SetInt(){
@@ -206,9 +206,9 @@ int part_SetInt(){
int part_SetString(){
char *arg0;
if (parseStringInput(argv[0], &arg0))
return -1;
return INFUNC_FAIL;
if (argv[1][0] != '$')
return -1;
return INFUNC_FAIL;
str_str_add(argv[1], arg0);
return 0;
@@ -218,11 +218,11 @@ int part_SetStringIndex(){
int index;
char *out;
if (parseIntInput(argv[0], &index))
return -1;
return INFUNC_FAIL;
if (argv[1][0] != '$')
return -1;
return INFUNC_FAIL;
if (str_str_index(index, &out))
return -1;
return INFUNC_FAIL;
str_str_add(argv[1], out);
return 0;
@@ -231,7 +231,10 @@ int part_SetStringIndex(){
int part_goto(){
int target = 0;
if (parseIntInput(argv[0], &target))
return -1;
return INFUNC_FAIL;
str_int_add("@RETURN", (int)f_tell(&scriptin));
f_lseek(&scriptin, target);
return 0;
}
@@ -239,14 +242,14 @@ int part_goto(){
int part_invert(){
int arg;
if (parseIntInput(argv[0], &arg))
return -1;
return INFUNC_FAIL;
return (arg) ? 0 : 1;
}
int part_fs_exists(){
char *path;
if (parseStringInput(argv[0], &path))
return -1;
return INFUNC_FAIL;
return fsutil_checkfile(path);
}
@@ -260,7 +263,7 @@ int part_ConnectMMC(){
else if (!strcmp(arg, "EMUMMC"))
connect_mmc(EMUMMC);
else
return -1;
return INFUNC_FAIL;
return 0;
}
@@ -285,6 +288,7 @@ int part_Pause(){
str_int_add("@BTN_DOWN", input->Ldown);
str_int_add("@BTN_LEFT", input->Lleft);
str_int_add("@BTN_RIGHT", input->Lright);
str_int_add("@JOYCONN", hidConnected());
return input->buttons;
}
@@ -292,11 +296,11 @@ int part_Pause(){
int part_addstrings(){
char *combined, *left, *middle;
if (parseStringInput(argv[0], &left))
return -1;
return INFUNC_FAIL;
if (parseStringInput(argv[1], &middle))
return -1;
return INFUNC_FAIL;
if (argv[2][0] != '$')
return -1;
return INFUNC_FAIL;
combined = calloc(strlen(left) + strlen(middle) + 1, sizeof(char));
sprintf(combined, "%s%s", left, middle);
@@ -309,7 +313,7 @@ int part_addstrings(){
int part_setColor(){
char *arg;
if (parseStringInput(argv[0], &arg))
return -1;
return INFUNC_FAIL;
if (!strcmp(arg, "RED"))
currentcolor = COLOR_RED;
@@ -326,7 +330,7 @@ int part_setColor(){
else if (!strcmp(arg, "WHITE"))
currentcolor = COLOR_WHITE;
else
return -1;
return INFUNC_FAIL;
return 0;
}
@@ -340,9 +344,9 @@ int part_fs_Move(){
char *left, *right;
if (parseStringInput(argv[0], &left))
return -1;
return INFUNC_FAIL;
if (parseStringInput(argv[1], &right))
return -1;
return INFUNC_FAIL;
int res;
res = f_rename(left, right);
@@ -356,7 +360,7 @@ int part_fs_Delete(){
char *arg;
if (parseStringInput(argv[0], &arg))
return -1;
return INFUNC_FAIL;
int res;
res = f_unlink(arg);
@@ -370,7 +374,7 @@ int part_fs_DeleteRecursive(){
char *arg;
if (parseStringInput(argv[0], &arg))
return -1;
return INFUNC_FAIL;
return fsact_del_recursive(arg);
}
@@ -379,9 +383,9 @@ int part_fs_Copy(){
char *left, *right;
if (parseStringInput(argv[0], &left))
return -1;
return INFUNC_FAIL;
if (parseStringInput(argv[1], &right))
return -1;
return INFUNC_FAIL;
return fsact_copy(left, right, COPY_MODE_PRINT);
}
@@ -390,9 +394,9 @@ int part_fs_CopyRecursive(){
char *left, *right;
if (parseStringInput(argv[0], &left))
return -1;
return INFUNC_FAIL;
if (parseStringInput(argv[1], &right))
return -1;
return INFUNC_FAIL;
return fsact_copy_recursive(left, right);
}
@@ -401,7 +405,7 @@ int part_fs_MakeDir(){
char *arg;
if (parseStringInput(argv[0], &arg))
return -1;
return INFUNC_FAIL;
int res;
res = f_mkdir(arg);
@@ -418,10 +422,10 @@ int part_fs_OpenDir(){
char *path;
if (parseStringInput(argv[0], &path))
return -1;
return INFUNC_FAIL;
if (f_opendir(&dir, path))
return -1;
return INFUNC_FAIL;
isdirvalid = true;
str_int_add("@ISDIRVALID", isdirvalid);
@@ -440,7 +444,7 @@ int part_fs_CloseDir(){
int part_fs_ReadDir(){
if (!isdirvalid)
return -1;
return INFUNC_FAIL;
if (!f_readdir(&dir, &fno) && fno.fname[0]){
str_str_add("$FILENAME", fno.fname);
@@ -457,16 +461,16 @@ int part_setPrintPos(){
int left, right;
if (parseIntInput(argv[0], &left))
return -1;
return INFUNC_FAIL;
if (parseIntInput(argv[1], &right))
return -1;
return INFUNC_FAIL;
if (left > 78)
return -1;
return INFUNC_FAIL;
if (right > 42)
return -1;
return INFUNC_FAIL;
gfx_con_setpos(left * 16, right * 16);
return 0;
@@ -476,9 +480,9 @@ int part_stringcompare(){
char *left, *right;
if (parseStringInput(argv[0], &left))
return -1;
return INFUNC_FAIL;
if (parseStringInput(argv[1], &right))
return -1;
return INFUNC_FAIL;
return (strcmp(left, right)) ? 0 : 1;
}
@@ -486,11 +490,11 @@ int part_stringcompare(){
int part_fs_combinePath(){
char *combined, *left, *middle;
if (parseStringInput(argv[0], &left))
return -1;
return INFUNC_FAIL;
if (parseStringInput(argv[1], &middle))
return -1;
return INFUNC_FAIL;
if (argv[2][0] != '$')
return -1;
return INFUNC_FAIL;
combined = fsutil_getnextloc(left, middle);
@@ -503,9 +507,9 @@ int part_mmc_dumpPart(){
char *left, *right;
if (parseStringInput(argv[0], &left))
return -1;
return INFUNC_FAIL;
if (parseStringInput(argv[1], &right))
return -1;
return INFUNC_FAIL;
if (!strcmp(left, "BOOT")){
return emmcDumpBoot(right);
@@ -519,21 +523,21 @@ int part_mmc_restorePart(){
char *path;
if (parseStringInput(argv[0], &path))
return -1;
return INFUNC_FAIL;
if (currentlyMounted < 0)
return -1;
return INFUNC_FAIL;
return mmcFlashFile(path, currentlyMounted);
return mmcFlashFile(path, currentlyMounted, false);
}
int part_fs_extractBisFile(){
char *path, *outfolder;
if (parseStringInput(argv[0], &path))
return -1;
return INFUNC_FAIL;
if (parseStringInput(argv[1], &outfolder))
return -1;
return INFUNC_FAIL;
return extract_bis_file(path, outfolder);
}
@@ -547,6 +551,60 @@ int part_getPos(){
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[] = {
{"printf", part_printf, 255},
{"printInt", part_print_int, 1},
@@ -563,6 +621,9 @@ str_fnc_struct functions[] = {
{"setColor", part_setColor, 1},
{"combineStrings", part_addstrings, 3},
{"compareStrings", part_stringcompare, 2},
{"subString", part_subString, 4},
{"inputString", part_inputString, 3},
{"stringLength", part_strLen, 1},
{"invert", part_invert, 1},
{"fs_exists", part_fs_exists, 1},
{"fs_move", part_fs_Move, 2},
@@ -596,8 +657,8 @@ int run_function(char *func_name, int *out){
continue;
*out = functions[i].value();
return (*out < 0) ? -1 : 0;
return (*out == INFUNC_FAIL) ? -1 : 0;
}
}
return -1;
return -2;
}

View File

@@ -16,15 +16,15 @@
#include "variables.h"
#include "../fs/fsreader.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 count = 0;
for (u32 i = 0; i < len; i++) {
if (in[i] == '"'){
i++;
while (in[i] != '"'){
i++;
while (in[++i] != '"'){
if (i >= len)
return -1;
}
@@ -32,55 +32,55 @@ u32 countchars(char* in, char target) {
if (in[i] == target)
count++;
}
return count;
}
char **argv = NULL;
u32 argc;
u32 splitargs(char* in) {
u32 splitargs(const char* in) {
// 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;
}
/*
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));
for (i = 0; i < len && curcount < count; i++) {
if (in[i] == ',') {
curcount++;
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] == '"') {
while (i < len && curcount < count) {
if (in[i] == ' ' || in[i] == ','){
i++;
while (in[i] != '"') {
argv[curcount][current++] = in[i++];
continue;
}
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++;
}
return count;
end = i;
if (in[i - 1] == '"'){
end--;
}
argv[curcount++] = utils_copyStringSize(in + begin, (u32)(end - begin));
}
return curcount;
}
FIL scriptin;
@@ -202,17 +202,6 @@ void mainparser(){
getnextvalidchar();
}
/*
if (currentchar == '?'){
char *jumpname;
jumpname = readtilchar(';', ' ');
getnextchar();
str_jmp_add(jumpname, f_tell(&scriptin));
getfollowingchar('\n');
return;
}
*/
functionparser();
res = run_function(funcbuff, &out);
@@ -220,7 +209,16 @@ void mainparser(){
printerrors = true;
//gfx_printf("%s|%s|%d", funcbuff, argv[0], argc);
//btn_wait();
gfx_errDisplay("mainparser", ERR_PARSE_FAIL, f_tell(&scriptin));
int lineNumber = 1;
u64 end = f_tell(&scriptin);
f_lseek(&scriptin, 0);
while (f_tell(&scriptin) < end && !f_eof(&scriptin)){
if (getnextchar() == '\n')
lineNumber++;
}
gfx_errDisplay((res == -1) ? funcbuff : "run_function", (res == -1) ? ERR_IN_FUNC : ERR_SCRIPT_LOOKUP_FAIL, lineNumber);
forceExit = true;
//gfx_printf("Func: %s\nArg1: %s\n", funcbuff, argv[0]);
}
@@ -288,6 +286,7 @@ void runScript(char *path){
//add builtin vars
str_int_add("@EMUMMC", emu_cfg.enabled);
str_int_add("@RESULT", 0);
str_int_add("@JOYCONN", hidConnected());
str_str_add("$CURRENTPATH", currentpath);
//str_int_printall();

View File

@@ -1,5 +1,7 @@
#pragma once
#define INFUNC_FAIL (int)0xC0000000
void runScript(char *path);
void skipbrackets();
void getfollowingchar(char end);

View File

@@ -17,6 +17,7 @@
#include "../fs/fsutils.h"
#include "../../mem/heap.h"
#include "../utils/utils.h"
#include "../fs/nca.h"
extern bool sd_mount();
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;
FILINFO fno;
bool fail = false;
@@ -107,6 +110,22 @@ int dumpfirmware(int mmc){
connect_mmc(mmc);
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("Creating folders...\n");
@@ -115,7 +134,24 @@ int dumpfirmware(int mmc){
sdbase = calloc(32 + strlen(pkg1.id), sizeof(char));
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);
if ((ret = f_opendir(&dir, sysbase)))
@@ -127,16 +163,39 @@ int dumpfirmware(int mmc){
printerrors = 0;
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);
if (fno.fattrib & AM_DIR){
utils_copystring(fsutil_getnextloc(syspathtemp, "00"), &syspath);
free(syspathtemp);
}
else
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);
gfx_printf("%d %s\r", ++amount, fno.fname);
@@ -145,6 +204,8 @@ int dumpfirmware(int mmc){
fail = true;
free(sdpath);
free(syspathtemp);
if (syspath != syspathtemp)
free(syspath);
}
@@ -159,7 +220,7 @@ int dumpfirmware(int mmc){
return fail;
}
/*
void dumpusersaves(int mmc){
connect_mmc(mmc);
mount_mmc("USER", 2);
@@ -180,6 +241,7 @@ void dumpusersaves(int mmc){
gfx_printf("Press any key to continue");
hidWait();
}
*/
int format(int mode){
gfx_clearscreen();

View File

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

View File

@@ -193,3 +193,13 @@ char *utils_InputText(char *start, int maxLen){
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

@@ -24,3 +24,4 @@ int utils_mmcMenu();
void utils_copystring(const char *in, char **out);
char *utils_InputText(char *start, int maxLen);
void utils_takeScreenshot();
char *utils_copyStringSize(const char *in, int size);