Compare commits

..

1 Commits

Author SHA1 Message Date
Such Meme, Many Skill
b91c36d3fa Fastfs testing 2020-05-19 17:54:21 +02:00
60 changed files with 1649 additions and 2186 deletions

View File

@@ -8,14 +8,27 @@ on:
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: devkitpro/devkita64_devkitarm
steps: steps:
- uses: actions/checkout@v1 - 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 - name: Build TegraExplorer
run: make -j$(nproc) 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 - uses: actions/upload-artifact@master
with: with:

View File

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

View File

@@ -1,28 +1,24 @@
# TegraExplorer # 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! A payload-based file explorer for your switch!
![TegraExplorer builder](https://github.com/suchmememanyskill/TegraExplorer/workflows/TegraExplorer%20builder/badge.svg)
## 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
@@ -60,7 +56,6 @@ Other awesome people:
- Huhen - Huhen
- Bleck9999 - Bleck9999
- Exelix - Exelix
- Emmo
## Screenshots ## Screenshots

View File

@@ -1,8 +1,8 @@
/* /*
* 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,

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: 0x40003000 - 0x40028000 --- */ /* --- IPL: 0x40008000 - 0x40028000 --- */
#define IPL_LOAD_ADDR 0x40003000 #define IPL_LOAD_ADDR 0x40008000
#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

@@ -540,11 +540,6 @@ void gfx_boxGrey(int x0, int y0, int x1, int y1, u8 shade){
memset(gfx_ctxt.fb + y * gfx_ctxt.stride + y0, shade, (y1 - y0 + 1) * 4); memset(gfx_ctxt.fb + y * gfx_ctxt.stride + y0, shade, (y1 - y0 + 1) * 4);
} }
} }
void gfx_setPixel(int x, int y, u32 color) {
*(gfx_ctxt.fb + (YLEFT - x) * gfx_ctxt.stride + y) = color;
}
/* /*
void gfx_boxGrey_old(int x0, int y0, int x1, int y1, u8 shade){ void gfx_boxGrey_old(int x0, int y0, int x1, int y1, u8 shade){
for (int y = y0; y <= y1; y++){ for (int y = y0; y <= y1; y++){

View File

@@ -53,7 +53,6 @@ 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_setPixel(int x, int y, u32 color);
/* /*
#define GFX_SETPOSCORRECTED(x, y) gfx_con_setpos(y - YLEFT, x) #define GFX_SETPOSCORRECTED(x, y) gfx_con_setpos(y - YLEFT, x)

View File

@@ -1,220 +0,0 @@
/*
* 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;
}

View File

@@ -1,34 +0,0 @@
/*
* 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

View File

@@ -1,120 +0,0 @@
/*
* 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,14 +32,6 @@ 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];
@@ -95,12 +87,6 @@ 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,20 +17,15 @@
#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"
@@ -63,81 +58,48 @@ 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;
LIST_INIT(ini_sections); // Copy sept-primary.
if (ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false)) if (f_open(&fp, "sd:/sept/sept-primary.bin", FA_READ))
goto error;
if (f_read(&fp, (u8 *)SEPT_STG1_ADDR, f_size(&fp), NULL))
{ {
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;
if (f_read(&fp, (u8 *)SEPT_STG1_ADDR, f_size(&fp), NULL))
{
f_close(&fp);
goto error;
}
f_close(&fp); f_close(&fp);
goto error;
}
f_close(&fp);
// Copy sept-secondary. // Copy sept-secondary.
if (kb < KB_FIRMWARE_VERSION_810) 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_00.enc", FA_READ))
if (f_open(&fp, "sd:/sept/sept-secondary.enc", FA_READ)) // Try the deprecated version. 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; goto error;
}
if (f_read(&fp, (u8 *)SEPT_STG2_ADDR, f_size(&fp), NULL))
{
f_close(&fp);
goto error;
}
f_close(&fp);
} }
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);
// 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));
@@ -145,8 +107,7 @@ 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,10 +81,8 @@ 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 *temptweak = (u8 *)malloc(0x10); u8 *pdst = (u8 *)dst;
u32 *pdst = (u32 *)dst; u8 *psrc = (u8 *)src;
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--) {
@@ -98,33 +96,34 @@ 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 < 4; j++) for (u32 j = 0; j < 0x10; j++)
pdst[j] = psrc[j] ^ ptweak[j]; pdst[j] = psrc[j] ^ tweak[j];
_gf256_mul_x_le(tweak); _gf256_mul_x_le(tweak);
psrc += 4; psrc += 0x10;
pdst += 4; pdst += 0x10;
} }
se_aes_crypt_ecb(ks2, enc, dst, secsize, dst, secsize); se_aes_crypt_ecb(ks2, enc, dst, secsize, dst, secsize);
pdst = (u32 *)dst; pdst = (u8 *)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 < 4; j++) for (u32 j = 0; j < 0x10; j++)
pdst[j] = pdst[j] ^ ptweak[j]; pdst[j] = pdst[j] ^ tweak[j];
_gf256_mul_x_le(tweak); _gf256_mul_x_le(tweak);
pdst += 4; pdst += 0x10;
} }
res = 1; res = 1;
out:; out:;
free(temptweak);
return res; return res;
} }

View File

@@ -4056,7 +4056,216 @@ FRESULT f_write (
LEAVE_FF(fs, FR_OK); LEAVE_FF(fs, FR_OK);
} }
#ifdef FF_FASTFS
/*-----------------------------------------------------------------------*/
/* Fast Read Aligned Sized File Without a Cache */
/*-----------------------------------------------------------------------*/
#if FF_USE_FASTSEEK
FRESULT f_read_fast (
FIL* fp, /* Pointer to the file object */
const void* buff, /* Pointer to the data to be written */
UINT btr /* Number of bytes to read */
)
{
if (btr % 65536 != 0)
return f_read(fp, buff, btr, NULL);
FRESULT res;
FATFS *fs;
UINT csize_bytes;
DWORD clst;
UINT count = 0;
FSIZE_t work_sector = 0;
FSIZE_t sector_base = 0;
BYTE *wbuff = (BYTE*)buff;
// TODO support sector reading inside a cluster
res = validate(&fp->obj, &fs); /* Check validity of the file object */
if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) {
EFSPRINTF("FOV");
LEAVE_FF(fs, res); /* Check validity */
}
if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */
FSIZE_t remain = fp->obj.objsize - fp->fptr;
if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */
csize_bytes = fs->csize * SS(fs);
if (!fp->fptr) { /* On the top of the file? */
clst = fp->obj.sclust; /* Follow from the origin */
} else {
if (fp->cltbl) clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */
else { EFSPRINTF("CLTBL"); ABORT(fs, FR_CLTBL_NO_INIT); }
}
if (clst < 2) { EFSPRINTF("CCHK"); ABORT(fs, FR_INT_ERR); }
else if (clst == 0xFFFFFFFF) { EFSPRINTF("DSKC"); ABORT(fs, FR_DISK_ERR); }
fp->clust = clst; /* Set working cluster */
sector_base = clst2sect(fs, fp->clust);
count += fs->csize;
btr -= csize_bytes;
fp->fptr += csize_bytes;
while (btr) {
clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */
if (clst < 2) { EFSPRINTF("CCHK2"); ABORT(fs, FR_INT_ERR); }
else if (clst == 0xFFFFFFFF) { EFSPRINTF("DSKC"); ABORT(fs, FR_DISK_ERR); }
fp->clust = clst;
work_sector = clst2sect(fs, fp->clust);
if ((work_sector - sector_base) == count) count += fs->csize;
else {
if (disk_read(fs->pdrv, wbuff, sector_base, count) != RES_OK) ABORT(fs, FR_DISK_ERR);
wbuff += count * SS(fs);
sector_base = work_sector;
count = fs->csize;
}
fp->fptr += MIN(btr, csize_bytes);
btr -= MIN(btr, csize_bytes);
// TODO: what about if data is smaller than cluster?
// Must read-write back that cluster.
if (!btr) { /* Final cluster/sectors read. */
if (disk_read(fs->pdrv, wbuff, sector_base, count) != RES_OK) ABORT(fs, FR_DISK_ERR);
}
}
LEAVE_FF(fs, FR_OK);
}
#endif
#endif
#ifdef FF_FASTFS
/*-----------------------------------------------------------------------*/
/* Fast Write Aligned Sized File Without a Cache */
/*-----------------------------------------------------------------------*/
#if FF_USE_FASTSEEK
FRESULT f_write_fast (
FIL* fp, /* Pointer to the file object */
const void* buff, /* Pointer to the data to be written */
UINT btw /* Number of bytes to write */
)
{
if (btw % 65536 != 0)
return f_write(fp, buff, btw, NULL);
FRESULT res;
FATFS *fs;
UINT csize_bytes;
DWORD clst;
UINT count = 0;
FSIZE_t work_sector = 0;
FSIZE_t sector_base = 0;
const BYTE *wbuff = (const BYTE*)buff;
// TODO support sector writing inside a cluster
res = validate(&fp->obj, &fs); /* Check validity of the file object */
if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) {
EFSPRINTF("FOV");
LEAVE_FF(fs, res); /* Check validity */
}
if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */
/* Check fptr wrap-around (file size cannot reach 4 GiB at FAT volume) */
if ((!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) && (DWORD)(fp->fptr + btw) < (DWORD)fp->fptr) {
btw = (UINT)(0xFFFFFFFF - (DWORD)fp->fptr);
}
csize_bytes = fs->csize * SS(fs);
if (!fp->fptr) { /* On the top of the file? */
clst = fp->obj.sclust; /* Follow from the origin */
} else {
if (fp->cltbl) clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */
else { EFSPRINTF("CLTBL"); ABORT(fs, FR_CLTBL_NO_INIT); }
}
if (clst < 2) { EFSPRINTF("CCHK"); ABORT(fs, FR_INT_ERR); }
else if (clst == 0xFFFFFFFF) { EFSPRINTF("DERR"); ABORT(fs, FR_DISK_ERR); }
fp->clust = clst; /* Set working cluster */
sector_base = clst2sect(fs, fp->clust);
count += fs->csize;
btw -= csize_bytes;
fp->fptr += csize_bytes;
while (btw) {
clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */
if (clst < 2) { EFSPRINTF("CCHK2"); ABORT(fs, FR_INT_ERR); }
else if (clst == 0xFFFFFFFF) { EFSPRINTF("DERR"); ABORT(fs, FR_DISK_ERR); }
fp->clust = clst;
work_sector = clst2sect(fs, fp->clust);
if ((work_sector - sector_base) == count) count += fs->csize;
else {
if (disk_write(fs->pdrv, wbuff, sector_base, count) != RES_OK) ABORT(fs, FR_DISK_ERR);
wbuff += count * SS(fs);
sector_base = work_sector;
count = fs->csize;
}
fp->fptr += MIN(btw, csize_bytes);
btw -= MIN(btw, csize_bytes);
// what about if data is smaller than cluster?
// Probably must read-write back that cluster.
if (!btw) { /* Final cluster/sectors write. */
if (disk_write(fs->pdrv, wbuff, sector_base, count) != RES_OK) ABORT(fs, FR_DISK_ERR);
fp->flag &= (BYTE)~FA_DIRTY;
}
}
fp->flag |= FA_MODIFIED; /* Set file change flag */
LEAVE_FF(fs, FR_OK);
}
#endif
#endif
#ifdef FF_FASTFS
#if FF_USE_FASTSEEK
/*-----------------------------------------------------------------------*/
/* Seek File Read/Write Pointer */
/*-----------------------------------------------------------------------*/
DWORD *f_expand_cltbl (
FIL* fp, /* Pointer to the file object */
UINT tblsz, /* Size of table */
FSIZE_t ofs /* File pointer from top of file */
)
{
if (fp->flag & FA_WRITE) f_lseek(fp, ofs); /* Expand file if write is enabled */
if (!fp->cltbl) { /* Allocate memory for cluster link table */
fp->cltbl = (DWORD *)ff_memalloc(tblsz);
fp->cltbl[0] = tblsz;
}
if (f_lseek(fp, CREATE_LINKMAP)) { /* Create cluster link table */
ff_memfree(fp->cltbl);
fp->cltbl = NULL;
EFSPRINTF("CLTBLSZ");
return NULL;
}
f_lseek(fp, 0);
return fp->cltbl;
}
#endif
#endif
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@@ -4169,6 +4378,13 @@ FRESULT f_close (
#endif #endif
} }
} }
if (fp->cltbl != NULL){
ff_memfree(fp->cltbl);
fp->cltbl = NULL;
}
return res; return res;
} }

View File

@@ -246,7 +246,10 @@ typedef enum {
FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */ FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */ FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */
FR_INVALID_PARAMETER /* (19) Given parameter is invalid */ FR_INVALID_PARAMETER, /* (19) Given parameter is invalid */
#ifdef FF_FASTFS
FR_CLTBL_NO_INIT /* (20) The cluster table for fast seek/read/write was not created */
#endif
} FRESULT; } FRESULT;
@@ -288,6 +291,11 @@ int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */
int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */ int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */
int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */ int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */
TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */ TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */
#ifdef FF_FASTFS
FRESULT f_read_fast (FIL* fp, const void* buff, UINT btr); /* Fast read data from the file */
FRESULT f_write_fast (FIL* fp, const void* buff, UINT btw); /* Fast write data to the file */
DWORD *f_expand_cltbl (FIL* fp, UINT tblsz, FSIZE_t ofs); /* Expand file and populate cluster table */
#endif
#define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize)) #define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize))
#define f_error(fp) ((fp)->err) #define f_error(fp) ((fp)->err)

View File

@@ -42,7 +42,13 @@
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ /* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
#define FF_FASTFS 1
#ifdef FF_FASTFS
#define FF_USE_FASTSEEK 1
#else
#define FF_USE_FASTSEEK 0 #define FF_USE_FASTSEEK 0
#endif
/* This option switches fast seek function. (0:Disable or 1:Enable) */ /* This option switches fast seek function. (0:Disable or 1:Enable) */
@@ -287,3 +293,5 @@
/*--- End of configuration options ---*/ /*--- End of configuration options ---*/

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, ALIGN(num * size, sizeof(hnode_t))); // Clear the aligned size. memset(res, 0, num * size);
return res; return res;
} }

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-2020 shchmue * Copyright (c) 2019 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;
time->hour = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_HOUR_REG) & 0x1F; if (!(val & MAX77620_RTC_24H) && (hour & MAX77620_RTC_HOUR_PM_MASK))
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,7 +19,6 @@
#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"
@@ -95,12 +94,7 @@ 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)
{ {
static se_ll_t *ll_dst = NULL, *ll_src = NULL; se_ll_t *ll_dst = (se_ll_t *)0xECFFFFE0, *ll_src = (se_ll_t *)0xECFFFFF0;
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)
{ {
@@ -240,16 +234,6 @@ 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;
@@ -336,90 +320,12 @@ 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 *temptweak = (u8 *)malloc(0x10); u8 *pdst = (u8 *)dst;
u32 *pdst = (u32 *)dst; u8 *psrc = (u8 *)src;
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--)
@@ -430,35 +336,23 @@ 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 < 4; j++) for (u32 j = 0; j < 0x10; j++)
pdst[j] = psrc[j] ^ ptweak[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];
_gf256_mul_x_le(tweak); _gf256_mul_x_le(tweak);
psrc += 4; psrc += 0x10;
pdst += 4; pdst += 0x10;
}
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;
} }
@@ -496,21 +390,17 @@ 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);
} }
@@ -557,8 +447,7 @@ 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,17 +25,12 @@ 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,7 +18,6 @@
#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"
@@ -81,7 +80,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) |
@@ -103,7 +102,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
@@ -127,7 +126,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(0x4002B000); smmu_init(tsec_ctxt->secmon_base);
// Enable SMMU // Enable SMMU
if (!smmu_is_used()) if (!smmu_is_used())
smmu_enable(); smmu_enable();
@@ -170,7 +169,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 + (0x7000 / 4)); pkg11_magic_off = (u32 *)(iram + ((tsec_ctxt->pkg11_off + 0x20) / 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
@@ -178,7 +177,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.
@@ -255,7 +254,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);
@@ -275,7 +274,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,6 +27,8 @@ 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,6 +26,7 @@
#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"
@@ -101,7 +102,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(0); pinmux_config_uart(UART_A);
// 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);
@@ -294,6 +295,11 @@ 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);
@@ -313,7 +319,6 @@ 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;
@@ -329,7 +334,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)
{ {
@@ -352,7 +357,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, 5, 0); sdmmc_init(&sd_sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_SD_ID, 0);
clock_disable_cl_dvfs(); clock_disable_cl_dvfs();
msleep(200); msleep(200);

View File

@@ -116,5 +116,3 @@ 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

@@ -93,10 +93,3 @@ menu_entry mmcmenu_filemenu[] = {
{"\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

@@ -59,5 +59,3 @@ typedef struct {
#define isFS 0x80 #define isFS 0x80
#define isBOOT 0x2 #define isBOOT 0x2
typedef void (*func_void_ptr)();

View File

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

View File

@@ -28,7 +28,6 @@ extern sdmmc_storage_t storage;
extern emmc_part_t *system_part; extern emmc_part_t *system_part;
extern char *clipboard; extern char *clipboard;
extern u8 clipboardhelper; extern u8 clipboardhelper;
extern bool sd_mounted;
void addEntry(emmc_part_t *part, u8 property_GPT, int spot){ void addEntry(emmc_part_t *part, u8 property_GPT, int spot){
@@ -74,12 +73,6 @@ int fillMmcMenu(short mmcType){
mu_createObjects(count, &mmcMenuEntries); mu_createObjects(count, &mmcMenuEntries);
if (!sd_mounted)
sd_mount();
SETBIT(mmcmenu_filemenu[3].property, ISHIDE, !sd_mounted);
SETBIT(mmcmenu_start[1].property, ISHIDE, !sd_mounted);
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
mu_copySingle(mmcmenu_start[i].name, mmcmenu_start[i].storage, mmcmenu_start[i].property, &mmcMenuEntries[i]); mu_copySingle(mmcmenu_start[i].name, mmcmenu_start[i].storage, mmcmenu_start[i].property, &mmcMenuEntries[i]);

View File

@@ -191,7 +191,6 @@ int filemenu(menu_entry file){
break; break;
} }
fsreader_readfolder(currentpath);
break; break;
case FILE_PAYLOAD: case FILE_PAYLOAD:
launch_payload(fsutil_getnextloc(currentpath, file.name)); launch_payload(fsutil_getnextloc(currentpath, file.name));
@@ -204,8 +203,7 @@ int filemenu(menu_entry file){
while (hidRead()->buttons); while (hidRead()->buttons);
*/ */
startScript(fsutil_getnextloc(currentpath, file.name)); runScript(fsutil_getnextloc(currentpath, file.name));
fsreader_readfolder(currentpath);
break; break;
case FILE_HEXVIEW: case FILE_HEXVIEW:
viewbytes(fsutil_getnextloc(currentpath, file.name)); viewbytes(fsutil_getnextloc(currentpath, file.name));
@@ -213,7 +211,6 @@ int filemenu(menu_entry file){
case FILE_DUMPBIS: case FILE_DUMPBIS:
gfx_clearscreen(); gfx_clearscreen();
extract_bis_file(fsutil_getnextloc(currentpath, file.name), currentpath); extract_bis_file(fsutil_getnextloc(currentpath, file.name), currentpath);
fsreader_readfolder(currentpath);
hidWait(); hidWait();
break; break;
case FILE_SIGN: case FILE_SIGN:
@@ -231,5 +228,6 @@ int filemenu(menu_entry file){
return -1; return -1;
} }
fsreader_readfolder(currentpath);
return 0; return 0;
} }

View File

@@ -16,7 +16,7 @@ int fsact_copy(const char *locin, const char *locout, u8 options){
FILINFO in_info; FILINFO in_info;
u64 sizeRemaining, toCopy; u64 sizeRemaining, toCopy;
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, toSpeed;
int res; int res;
gfx_con_getpos(&x, &y); gfx_con_getpos(&x, &y);
@@ -52,15 +52,18 @@ int fsact_copy(const char *locin, const char *locout, u8 options){
sizeRemaining = f_size(&in); sizeRemaining = f_size(&in);
const u64 totalsize = sizeRemaining; const u64 totalsize = sizeRemaining;
DWORD *clmt_in = f_expand_cltbl(&in, BUFSIZE / 4, 0);
DWORD *clmt_out = f_expand_cltbl(&out, BUFSIZE / 4, totalsize);
while (sizeRemaining > 0){ while (sizeRemaining > 0){
toCopy = MIN(sizeRemaining, BUFSIZE); toCopy = MIN(sizeRemaining, BUFSIZE);
if ((res = f_read(&in, buff, toCopy, NULL))){ if ((res = f_read_fast(&in, buff, toCopy))){
gfx_errDisplay("copy", res, 5); gfx_errDisplay("copy", res, 5);
break; break;
} }
if ((res = f_write(&out, buff, toCopy, NULL))){ if ((res = f_write_fast(&out, buff, toCopy))){
gfx_errDisplay("copy", res, 6); gfx_errDisplay("copy", res, 6);
break; break;
} }

View File

@@ -1,62 +0,0 @@
#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

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

View File

@@ -1,46 +0,0 @@
#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

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

View File

@@ -1,5 +1,4 @@
#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"
@@ -63,15 +62,62 @@ out_free:;
return success; return success;
} }
bool save_sign(const char *keypath, const char *savepath){
u8 *key = GetKey(keypath, "save_mac_key");
if (key == NULL){ char *getKey(const char *search, link_t *inilist){
return false; 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]));
} }
if (!save_commit(savepath, key)) return out;
return false; }
return true; bool save_sign(const char *keypath, const char *savepath){
LIST_INIT(inilist);
char *key;
u8 *hex;
bool success = false;
if (!ini_parse(&inilist, keypath, false)){
gfx_errDisplay("save_sign", ERR_INI_PARSE_FAIL, 1);
goto out_free;
}
if ((key = getKey("save_mac_key", &inilist)) == NULL){
gfx_errDisplay("save_sign", ERR_INI_PARSE_FAIL, 2);
goto out_free;
}
hex = getHex(key);
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.4 | Battery: %3d%%\n", battery >> 8); gfx_printf("Tegraexplorer v2.0.2 | Battery: %3d%%\n", battery >> 8);
RESETCOLOR; RESETCOLOR;
} }

View File

@@ -18,9 +18,6 @@ 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);
@@ -65,7 +62,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, calculatedamount = 0, cursub = 0, temp; int currentpos = 0, offset = 0, delay = 300, minscreen = 0, maxscreen = 39, calculatedamount = 0;
u32 scrolltimer, timer, sideY; u32 scrolltimer, timer, sideY;
bool refresh = true; bool refresh = true;
Inputs *input = hidRead(); Inputs *input = hidRead();
@@ -98,53 +95,56 @@ int menu_make(menu_entry *entries, int amount, const char *toptext){
gfx_sideprintf("\n\n\n"); gfx_sideprintf("\n\n\n");
} }
for (;;){ gfx_drawScrollBar(minscreen, maxscreen, amount);
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){
cursub = 1; while (currentpos < amount && entries[currentpos].property & (ISSKIP | ISHIDE))
else if (currentpos == amount - 1) currentpos++;
cursub = -1; }
else if (currentpos == amount - 1){
cursub = 0; while (currentpos >= 1 && entries[currentpos].property & (ISSKIP | ISHIDE))
currentpos--;
}
while (entries[currentpos].property & (ISSKIP | ISHIDE)) if (currentpos > maxscreen){
currentpos += cursub; offset += currentpos - maxscreen;
minscreen += currentpos - maxscreen;
maxscreen += currentpos - maxscreen;
if (currentpos > (minscreen + SCREENMAXOFFSET)){
offset += currentpos - (minscreen + SCREENMAXOFFSET);
minscreen += currentpos - (minscreen + SCREENMAXOFFSET);
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 < SCREENMAXOFFSET + 1 + offset; i++) for (int i = 0 + offset; i < amount && i < 40 + offset; i++)
_printentry(&entries[i], (i == currentpos), refresh, toptext); if (!(entries[i].isHide))
_printentry(&entries[i], (i == currentpos), refresh, toptext);
} }
else { else {
temp = (currentpos - minscreen > 0) ? 0 : 16; if (currentpos - minscreen > 0){
gfx_con_setpos(0, 32 + temp + (currentpos - minscreen) * 16); gfx_con_setpos(0, 32 + (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 < MIN(amount - 1, minscreen + SCREENMAXOFFSET)) if (currentpos < amount - 1 && currentpos < maxscreen)
_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,14 +158,12 @@ 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);
SWAPALLCOLOR(COLOR_DEFAULT, COLOR_WHITE); SWAPCOLOR(COLOR_DEFAULT);
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, minscreen + SCREENMAXOFFSET, amount); gfx_drawScrollBar(minscreen, maxscreen, amount);
refresh = false;
while (hidRead()->buttons & (KEY_B | KEY_A)); while (hidRead()->buttons & (KEY_B | KEY_A));
@@ -184,12 +182,14 @@ int menu_make(menu_entry *entries, int amount, const char *toptext){
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()){
break; break;
@@ -200,32 +200,27 @@ int menu_make(menu_entry *entries, int amount, const char *toptext){
} }
} }
if (delay > 46)
delay -= 45;
if (input->a){ if (input->Lup && currentpos >= 1){
break; currentpos--;
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,6 +1,4 @@
#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,10 +60,7 @@ void MainMenu_Tools(){
displaygpio(); displaygpio();
break; break;
case TOOLS_DUMPFIRMWARE: case TOOLS_DUMPFIRMWARE:
res = menu_make(fwDump_typeMenu, 4, "-- Fw Type --"); dumpfirmware(SYSMMC);
if (res >= 2)
dumpfirmware(SYSMMC, (res == 2));
break; break;
} }
} }

View File

@@ -1,281 +0,0 @@
#include "args.h"
#include "parser.h"
#include "scriptCtx.h"
#include "lexer.h"
#include "functions.h"
#include "list.h"
#include <string.h>
#include "../../mem/heap.h"
#include "../utils/utils.h"
// do not include first openToken!
int distanceBetweenTokens(lexarToken_t* tokens, u32 len, int openToken, int closeToken) {
int i = 0;
int layer = 0;
for (; i < len; i++) {
if (tokens[i].token == openToken)
layer++;
else if (tokens[i].token == closeToken) {
if (layer == 0)
return i;
layer--;
}
}
return -1;
}
dictValue_t getVarFromToken(scriptCtx_t* ctx, lexarToken_t* tokens, int* index, u32 maxLen) {
dictValue_t val = { 0 };
val.free = 0;
int i = *index;
u8 not = 0;
if (tokens[i].token == Not) {
not = 1;
i++;
}
if (tokens[i].token == Not)
return ErrDictValue(ERRDOUBLENOT);
if (tokens[i].token == Variable) {
char* funcName = tokens[i].text;
if (tokens[i + 1].token == LBracket) {
i += 2;
int argCount = distanceBetweenTokens(&tokens[i], maxLen - 2, LBracket, RBracket);
if (argCount < 0)
return ErrDictValue(ERRSYNTAX);
ctx->args_loc.tokens = &tokens[i];
ctx->args_loc.stored = argCount;
val = executeFunction(ctx, funcName);
i += argCount;
}
else if (tokens[i + 1].token == LSBracket) {
dictValue_t* var = varVectorFind(&ctx->vars, tokens[i].text);
i += 2;
if (var == NULL)
return ErrDictValue(ERRNOVAR);
int argCount = distanceBetweenTokens(&tokens[i], maxLen - 2, LSBracket, RSBracket);
if (argCount < 0)
return ErrDictValue(ERRSYNTAX);
dictValue_t index = solveEquation(ctx, &tokens[i], argCount);
i += argCount;
if (index.varType != IntType)
return ErrDictValue(ERRINVALIDTYPE);
if (var->arrayLen <= index.integer || index.integer < 0)
return ErrDictValue(ERRSYNTAX);
switch (var->varType) {
case StringArrayType:
val = StrDictValue(var->stringArray[index.integer]);
break;
case IntArrayType:
val = IntDictValue(var->integerArray[index.integer]);
break;
case ByteArrayType:
val = IntDictValue(var->byteArray[index.integer]);
break;
default:
return ErrDictValue(ERRINVALIDTYPE);
}
}
else {
dictValue_t* var = varVectorFind(&ctx->vars, tokens[i].text);
if (var != NULL) {
if (var->type == IntType) {
val = IntDictValue(var->integer);
}
else if (var->type == StringType){
val = StrDictValue(util_cpyStr(var->string));
val.free = 1;
}
else {
val = *var;
val.free = 0;
}
}
else
return ErrDictValue(ERRNOVAR);
}
}
else if (tokens[i].token == LSBracket) {
i++;
int argCount = distanceBetweenTokens(&tokens[i], maxLen - 1, LSBracket, RSBracket);
if (argCount <= 0)
return ErrDictValue(-5);
varVector_t arrayVars = extractVars(ctx, &tokens[i], argCount);
int type = arrayVars.vars[0].value.varType;
if (!(type == StringType || type == IntType))
return ErrDictValue(ERRINVALIDTYPE);
val.type = (type + 2) | FREEINDICT;
val.arrayLen = arrayVars.stored;
val.integerArray = calloc(val.arrayLen, (type == IntType) ? sizeof(int) : sizeof(char*));
val.free = (type == StringType) ? 1 : 0;
for (int i = 0; i < arrayVars.stored; i++) {
if (arrayVars.vars[i].value.varType != type)
return ErrDictValue(ERRINVALIDTYPE); // Free-ing issue!!
if (type == StringType) {
val.stringArray[i] = util_cpyStr(arrayVars.vars[i].value.string);
}
else {
val.integerArray[i] = arrayVars.vars[i].value.integer;
}
}
i += argCount;
varVectorFree(&arrayVars);
}
else if (tokens[i].token == LBracket) {
i += 1;
int argCount = distanceBetweenTokens(&tokens[i], maxLen - 1, LBracket, RBracket);
if (argCount < 0)
return ErrDictValue(ERRSYNTAX);
val = solveEquation(ctx, &tokens[i], argCount);
i += argCount;
}
else if (tokens[i].token == IntLit) {
val = IntDictValue(tokens[i].val);
}
else if (tokens[i].token == StrLit) {
val = StrDictValue(tokens[i].text); // Do we need to copy the string here? if we set var.free = 0, it shouldn't matter
val.free = 0;
}
else {
// ERR
return ErrDictValue(ERRNOVAR);
}
if (not) {
if (val.type == IntType)
val.integer = !val.integer;
else
return ErrDictValue(ERRINVALIDTYPE);
}
*index = i;
return val;
}
int matchTypes(dictValue_t d1, dictValue_t d2, int type) {
return (d1.varType == d2.varType && d1.varType == type);
}
#define ELIFT(token) else if (localOpToken == token)
dictValue_t solveEquation(scriptCtx_t *ctx, lexarToken_t* tokens, u32 len) {
dictValue_t res = { 0 };
u16 lastToken = 0;
for (int i = 0; i < len; i++) {
if (tokens[i].token == Variable || tokens[i].token == StrLit || tokens[i].token == IntLit || tokens[i].token == Not || tokens[i].token == LBracket || tokens[i].token == LSBracket){
dictValue_t val = getVarFromToken(ctx, tokens, &i, len - i);
if (val.type == ErrType)
return val;
if (lastToken) {
u16 localOpToken = lastToken; // do we need local op token?
lastToken = 0;
if (matchTypes(res, val, IntType)) {
if (localOpToken == Plus)
res.integer += val.integer;
ELIFT(Minus)
res.integer -= val.integer;
ELIFT(Multiply)
res.integer *= val.integer;
ELIFT(Division)
res.integer /= val.integer;
ELIFT(Mod)
res.integer %= val.integer;
ELIFT(Smaller)
res.integer = res.integer < val.integer;
ELIFT(SmallerEqual)
res.integer = res.integer <= val.integer;
ELIFT(Bigger)
res.integer = res.integer > val.integer;
ELIFT(BiggerEqual)
res.integer = res.integer >= val.integer;
ELIFT(EqualEqual)
res.integer = res.integer == val.integer;
ELIFT(NotEqual)
res.integer = res.integer != val.integer;
ELIFT(LogicAND) {
res.integer = res.integer && val.integer;
if (!res.integer)
break;
}
ELIFT(LogicOR) {
res.integer = res.integer || val.integer;
if (res.integer)
break;
}
ELIFT(AND)
res.integer = res.integer & val.integer;
ELIFT(OR)
res.integer = res.integer | val.integer;
else
return ErrDictValue(ERRBADOPERATOR);
}
else if (matchTypes(res, val, StringType)) {
if (localOpToken == Plus) {
char* buff = calloc(strlen(res.string) + strlen(val.string) + 1, 1);
strcpy(buff, res.string);
strcat(buff, val.string);
if (res.free)
free(res.string);
if (val.free)
free(val.string);
res.string = buff;
}
ELIFT(EqualEqual) {
res.type = IntType;
int compRes = !strcmp(res.string, val.string);
if (res.free)
free(res.string);
if (val.free)
free(val.string);
res.integer = compRes;
res.free = 0;
}
ELIFT(Minus) {
if (!strcmp(res.string + strlen(res.string) - strlen(val.string), val.string)) {
*(res.string + strlen(res.string) - strlen(val.string)) = 0;
}
free(val.string);
}
else
return ErrDictValue(ERRBADOPERATOR);
}
else
return ErrDictValue(ERRBADOPERATOR);
}
else {
res = val;
}
}
else if (tokens[i].token >= Plus && tokens[i].token <= OR) {
lastToken = tokens[i].token;
}
}
return res;
}

View File

@@ -1,6 +0,0 @@
#pragma once
#include "types.h"
char* createStrOutTextHolder(textHolder_t t);
dictValue_t solveEquation(scriptCtx_t* ctx, lexarToken_t* tokens, u32 len);
int distanceBetweenTokens(lexarToken_t* tokens, u32 len, int openToken, int closeToken);

View File

@@ -1,177 +1,608 @@
#include "functions.h"
#include "list.h"
#include "args.h"
#include "parser.h"
#include "lexer.h"
#include "types.h"
#include "scriptCtx.h"
#include "../../gfx/gfx.h"
#include "../../mem/heap.h"
#include <string.h> #include <string.h>
#include <stdlib.h>
#include "../../mem/heap.h"
#include "../gfx/gfxutils.h"
#include "../emmc/emmc.h"
#include "../../utils/types.h"
#include "../../libs/fatfs/ff.h"
#include "../../utils/sprintf.h"
#include "../../hid/hid.h" #include "../../hid/hid.h"
#include "../../gfx/gfx.h"
#include "../../utils/util.h"
#include "../../storage/emummc.h"
#include "parser.h"
#include "../common/common.h"
#include "../fs/fsactions.h"
#include "variables.h"
#include "../utils/utils.h"
#include "functions.h"
#include "../fs/fsutils.h"
#include "../../utils/sprintf.h"
#include "../fs/fsactions.h"
#include "../emmc/emmcoperations.h"
#include "../emmc/emmcmenu.h"
dictValue_t funcPrint(scriptCtx_t* ctx, varVector_t* args) { extern FIL scriptin;
for (int i = 0; i < args->stored; i++) { extern char **argv;
switch (args->vars[i].value.varType) { extern u32 argc;
case IntType: extern int forceExit;
gfx_printf("%d", args->vars[i].value.integer); extern short currentlyMounted;
break;
case StringType:
gfx_printf("%s", args->vars[i].value.string);
break;
}
}
return NullDictValue(); int parseIntInput(char *in, int *out){
if (in[0] == '@'){
if (str_int_find(in, out))
return -1;
}
else
*out = atoi(in);
return 0;
}
/*
int parseJmpInput(char *in, u64 *out){
if (in[0] == '?'){
if (str_jmp_find(in, out))
return -1;
else
return 0;
}
else
return -1;
}
*/
int parseStringInput(char *in, char **out){
if (in[0] == '$'){
if (str_str_find(in, out))
return -1;
else
return 0;
}
else{
*out = in;
return 0;
}
} }
dictValue_t funcPrintln(scriptCtx_t* ctx, varVector_t* args) { #pragma GCC push_options
funcPrint(ctx, args); #pragma GCC optimize ("Os")
gfx_printf("\n");
return NullDictValue(); u32 currentcolor = COLOR_WHITE;
int part_printf(){
SWAPCOLOR(currentcolor);
for (int i = 0; i < argc; i++){
if (argv[i][0] == '@'){
int toprintint;
if (parseIntInput(argv[i], &toprintint))
return INFUNC_FAIL;
gfx_printf("%d", toprintint);
}
else {
char *toprintstring;
if (parseStringInput(argv[i], &toprintstring))
return INFUNC_FAIL;
gfx_printf(toprintstring);
}
}
gfx_printf("\n");
return 0;
} }
dictValue_t funcIf(scriptCtx_t* ctx, varVector_t* args) { int part_print_int(){
if (args->vars[0].value.varType == IntType) { int toprint;
setCurIndentInstruction(ctx, (args->vars[0].value.integer == 0), -1); if (parseIntInput(argv[0], &toprint))
return NullDictValue(); return INFUNC_FAIL;
}
return ErrDictValue(ERRINVALIDTYPE); SWAPCOLOR(currentcolor);
gfx_printf("%s: %d\n", argv[0], toprint);
return 0;
} }
dictValue_t scriptElse(scriptCtx_t* ctx, varVector_t* args) { int part_Wait(){
indentInstructor_t curInstruction = getCurIndentInstruction(ctx); int arg;
setCurIndentInstruction(ctx, !curInstruction.skip, -1); u32 begintime;
return NullDictValue(); SWAPCOLOR(currentcolor);
if (parseIntInput(argv[0], &arg))
return INFUNC_FAIL;
begintime = get_tmr_s();
while (begintime + arg > get_tmr_s()){
gfx_printf("\r<Wait %d seconds> ", (begintime + arg) - get_tmr_s());
}
gfx_printf("\r \r");
return 0;
} }
dictValue_t scriptWhile(scriptCtx_t* ctx, varVector_t* args) { int part_Check(){
if (args->vars[0].value.varType == IntType) { int left, right;
setCurIndentInstruction(ctx, (args->vars[0].value.integer == 0), ctx->lastTokenPos); if (parseIntInput(argv[0], &left))
return NullDictValue(); return INFUNC_FAIL;
} if (parseIntInput(argv[2], &right))
return INFUNC_FAIL;
return ErrDictValue(ERRINVALIDTYPE); if (!strcmp(argv[1], "=="))
return (left == right);
else if (!strcmp(argv[1], "!="))
return (left != right);
else if (!strcmp(argv[1], ">="))
return (left >= right);
else if (!strcmp(argv[1], "<="))
return (left <= right);
else if (!strcmp(argv[1], ">"))
return (left > right);
else if (!strcmp(argv[1], "<"))
return (left < right);
else
return INFUNC_FAIL;
} }
dictValue_t scriptLen(scriptCtx_t* ctx, varVector_t* args) { int part_if(){
if (args->vars[0].value.varType >= IntArrayType && args->vars[0].value.varType <= ByteArrayType) int condition;
return IntDictValue(args->vars[0].value.arrayLen); if (parseIntInput(argv[0], &condition))
else if (args->vars[0].value.varType == StringType) { return INFUNC_FAIL;
if (args->vars[0].value.string != NULL)
return IntDictValue(strlen(args->vars[0].value.string));
}
return ErrDictValue(ERRINVALIDTYPE); getfollowingchar('{');
if (!condition)
skipbrackets();
return 0;
/*
if (condition)
return 0;
else {
skipbrackets();
return 0;
}
*/
} }
dictValue_t scriptMakeByteArray(scriptCtx_t* ctx, varVector_t* args) { int part_if_args(){
if (args->vars[0].value.varType == IntArrayType) { int condition;
u8* buff = calloc(args->vars[0].value.arrayLen, 1); if ((condition = part_Check()) < 0)
for (int i = 0; i < args->vars[0].value.arrayLen; i++) { return INFUNC_FAIL;
buff[i] = (u8)(args->vars[0].value.integerArray[i] & 0xFF);
}
return DictValueCreate(ByteArrayType | FREEINDICT, args->vars[0].value.arrayLen, buff); getfollowingchar('{');
}
return ErrDictValue(ERRINVALIDTYPE); if (!condition)
skipbrackets();
return 0;
} }
dictValue_t scriptWait(scriptCtx_t*ctx, varVector_t* args){ int part_Math(){
Inputs* input = hidWait(); int left, right;
if (parseIntInput(argv[0], &left))
return INFUNC_FAIL;
if (parseIntInput(argv[2], &right))
return INFUNC_FAIL;
return IntDictValue(input->buttons); switch (argv[1][0]){
case '+':
return left + right;
case '-':
return left - right;
case '*':
return left * right;
case '/':
return left / right;
}
return INFUNC_FAIL;
} }
dictValue_t scriptSetPixel(scriptCtx_t *ctx, varVector_t* args){ int part_SetInt(){
int pixelArgs[5] = {0}; int out;
parseIntInput(argv[0], &out);
for (int i = 0; i < args->stored; i++){ return out;
if (args->vars[i].value.varType != IntType)
return ErrDictValue(ERRINVALIDTYPE);
pixelArgs[i] = args->vars[i].value.integer;
}
u32 color = 0xFF000000 | ((pixelArgs[2] & 0xFF) << 16) | ((pixelArgs[3] & 0xFF) << 8) | ((pixelArgs[4] & 0xFF));
gfx_setPixel(pixelArgs[0], pixelArgs[1], color);
return NullDictValue();
} }
const static str_fnc_struct functions[] = { int part_SetString(){
{"print", funcPrint, {0x40}}, char *arg0;
{"println", funcPrintln, {0x40}}, if (parseStringInput(argv[0], &arg0))
{"if", funcIf, {1}}, return INFUNC_FAIL;
{"while", scriptWhile, {1}}, if (argv[1][0] != '$')
{"else", scriptElse, {0}}, return INFUNC_FAIL;
{"len", scriptLen, {1}},
{"byte", scriptMakeByteArray, {1}}, str_str_add(argv[1], arg0);
{"wait", scriptWait, {0}}, return 0;
{"setPixel", scriptSetPixel, {5}}, }
{NULL, NULL, {0}},
int part_SetStringIndex(){
int index;
char *out;
if (parseIntInput(argv[0], &index))
return INFUNC_FAIL;
if (argv[1][0] != '$')
return INFUNC_FAIL;
if (str_str_index(index, &out))
return INFUNC_FAIL;
str_str_add(argv[1], out);
return 0;
}
int part_goto(){
int target = 0;
if (parseIntInput(argv[0], &target))
return INFUNC_FAIL;
str_int_add("@RETURN", (int)f_tell(&scriptin));
f_lseek(&scriptin, target);
return 0;
}
int part_invert(){
int arg;
if (parseIntInput(argv[0], &arg))
return INFUNC_FAIL;
return (arg) ? 0 : 1;
}
int part_fs_exists(){
char *path;
if (parseStringInput(argv[0], &path))
return INFUNC_FAIL;
return fsutil_checkfile(path);
}
int part_ConnectMMC(){
char *arg;
parseStringInput(argv[0], &arg);
if (!strcmp(arg, "SYSMMC"))
connect_mmc(SYSMMC);
else if (!strcmp(arg, "EMUMMC"))
connect_mmc(EMUMMC);
else
return INFUNC_FAIL;
return 0;
}
int part_MountMMC(){
char *arg;
parseStringInput(argv[0], &arg);
return mount_mmc(arg, 2);
}
int part_Pause(){
Inputs *input = hidWaitMask(KEY_A | KEY_B | KEY_X | KEY_Y | KEY_POW | KEY_VOLP | KEY_VOLM | KEY_LUP | KEY_LDOWN | KEY_LLEFT | KEY_LRIGHT);
str_int_add("@BTN_POWER", input->pow);
str_int_add("@BTN_VOL+", input->volp);
str_int_add("@BTN_VOL-", input->volm);
str_int_add("@BTN_A", input->a);
str_int_add("@BTN_B", input->b);
str_int_add("@BTN_X", input->x);
str_int_add("@BTN_Y", input->y);
str_int_add("@BTN_UP", input->Lup);
str_int_add("@BTN_DOWN", input->Ldown);
str_int_add("@BTN_LEFT", input->Lleft);
str_int_add("@BTN_RIGHT", input->Lright);
return input->buttons;
}
int part_addstrings(){
char *combined, *left, *middle;
if (parseStringInput(argv[0], &left))
return INFUNC_FAIL;
if (parseStringInput(argv[1], &middle))
return INFUNC_FAIL;
if (argv[2][0] != '$')
return INFUNC_FAIL;
combined = calloc(strlen(left) + strlen(middle) + 1, sizeof(char));
sprintf(combined, "%s%s", left, middle);
str_str_add(argv[2], combined);
free(combined);
return 0;
}
int part_setColor(){
char *arg;
if (parseStringInput(argv[0], &arg))
return INFUNC_FAIL;
if (!strcmp(arg, "RED"))
currentcolor = COLOR_RED;
else if (!strcmp(arg, "ORANGE"))
currentcolor = COLOR_ORANGE;
else if (!strcmp(arg, "YELLOW"))
currentcolor = COLOR_YELLOW;
else if (!strcmp(arg, "GREEN"))
currentcolor = COLOR_GREEN;
else if (!strcmp(arg, "BLUE"))
currentcolor = COLOR_BLUE;
else if (!strcmp(arg, "VIOLET"))
currentcolor = COLOR_VIOLET;
else if (!strcmp(arg, "WHITE"))
currentcolor = COLOR_WHITE;
else
return INFUNC_FAIL;
return 0;
}
int part_Exit(){
forceExit = true;
return 0;
}
int part_fs_Move(){
char *left, *right;
if (parseStringInput(argv[0], &left))
return INFUNC_FAIL;
if (parseStringInput(argv[1], &right))
return INFUNC_FAIL;
int res;
res = f_rename(left, right);
if (res)
res = f_rename(left, right);
return res;
}
int part_fs_Delete(){
char *arg;
if (parseStringInput(argv[0], &arg))
return INFUNC_FAIL;
int res;
res = f_unlink(arg);
if (res)
res = f_unlink(arg);
return res;
}
int part_fs_DeleteRecursive(){
char *arg;
if (parseStringInput(argv[0], &arg))
return INFUNC_FAIL;
return fsact_del_recursive(arg);
}
int part_fs_Copy(){
char *left, *right;
if (parseStringInput(argv[0], &left))
return INFUNC_FAIL;
if (parseStringInput(argv[1], &right))
return INFUNC_FAIL;
return fsact_copy(left, right, COPY_MODE_PRINT);
}
int part_fs_CopyRecursive(){
char *left, *right;
if (parseStringInput(argv[0], &left))
return INFUNC_FAIL;
if (parseStringInput(argv[1], &right))
return INFUNC_FAIL;
return fsact_copy_recursive(left, right);
}
int part_fs_MakeDir(){
char *arg;
if (parseStringInput(argv[0], &arg))
return INFUNC_FAIL;
int res;
res = f_mkdir(arg);
if (res)
res = f_mkdir(arg);
return res;
}
DIR dir;
FILINFO fno;
int isdirvalid = false;
int part_fs_OpenDir(){
char *path;
if (parseStringInput(argv[0], &path))
return INFUNC_FAIL;
if (f_opendir(&dir, path))
return INFUNC_FAIL;
isdirvalid = true;
str_int_add("@ISDIRVALID", isdirvalid);
return 0;
}
int part_fs_CloseDir(){
if (!isdirvalid)
return 0;
f_closedir(&dir);
isdirvalid = false;
str_int_add("@ISDIRVALID", isdirvalid);
return 0;
}
int part_fs_ReadDir(){
if (!isdirvalid)
return INFUNC_FAIL;
if (!f_readdir(&dir, &fno) && fno.fname[0]){
str_str_add("$FILENAME", fno.fname);
str_int_add("@ISDIR", (fno.fattrib & AM_DIR) ? 1 : 0);
}
else {
part_fs_CloseDir();
}
return 0;
}
int part_setPrintPos(){
int left, right;
if (parseIntInput(argv[0], &left))
return INFUNC_FAIL;
if (parseIntInput(argv[1], &right))
return INFUNC_FAIL;
if (left > 78)
return INFUNC_FAIL;
if (right > 42)
return INFUNC_FAIL;
gfx_con_setpos(left * 16, right * 16);
return 0;
}
int part_stringcompare(){
char *left, *right;
if (parseStringInput(argv[0], &left))
return INFUNC_FAIL;
if (parseStringInput(argv[1], &right))
return INFUNC_FAIL;
return (strcmp(left, right)) ? 0 : 1;
}
int part_fs_combinePath(){
char *combined, *left, *middle;
if (parseStringInput(argv[0], &left))
return INFUNC_FAIL;
if (parseStringInput(argv[1], &middle))
return INFUNC_FAIL;
if (argv[2][0] != '$')
return INFUNC_FAIL;
combined = fsutil_getnextloc(left, middle);
str_str_add(argv[2], combined);
free(combined);
return 0;
}
int part_mmc_dumpPart(){
char *left, *right;
if (parseStringInput(argv[0], &left))
return INFUNC_FAIL;
if (parseStringInput(argv[1], &right))
return INFUNC_FAIL;
if (!strcmp(left, "BOOT")){
return emmcDumpBoot(right);
}
else {
return emmcDumpSpecific(left, right);
}
}
int part_mmc_restorePart(){
char *path;
if (parseStringInput(argv[0], &path))
return INFUNC_FAIL;
if (currentlyMounted < 0)
return INFUNC_FAIL;
return mmcFlashFile(path, currentlyMounted, false);
}
int part_fs_extractBisFile(){
char *path, *outfolder;
if (parseStringInput(argv[0], &path))
return INFUNC_FAIL;
if (parseStringInput(argv[1], &outfolder))
return INFUNC_FAIL;
return extract_bis_file(path, outfolder);
}
int part_clearscreen(){
gfx_clearscreen();
return 0;
}
int part_getPos(){
return (int)f_tell(&scriptin);
}
str_fnc_struct functions[] = {
{"printf", part_printf, 255},
{"printInt", part_print_int, 1},
{"setPrintPos", part_setPrintPos, 2},
{"clearscreen", part_clearscreen, 0},
{"if", part_if, 1},
{"if", part_if_args, 3}, // function overloading
{"math", part_Math, 3},
{"check", part_Check, 3},
{"setInt", part_SetInt, 1},
{"goto", part_goto, 1},
{"setString", part_SetString, 2},
{"setStringIndex", part_SetStringIndex, 2},
{"setColor", part_setColor, 1},
{"combineStrings", part_addstrings, 3},
{"compareStrings", part_stringcompare, 2},
{"invert", part_invert, 1},
{"fs_exists", part_fs_exists, 1},
{"fs_move", part_fs_Move, 2},
{"fs_mkdir", part_fs_MakeDir, 1},
{"fs_del", part_fs_Delete, 1},
{"fs_delRecursive", part_fs_DeleteRecursive, 1},
{"fs_copy", part_fs_Copy, 2},
{"fs_copyRecursive", part_fs_CopyRecursive, 2},
{"fs_openDir", part_fs_OpenDir, 1},
{"fs_closeDir", part_fs_CloseDir, 0},
{"fs_readDir", part_fs_ReadDir, 0},
{"fs_combinePath", part_fs_combinePath, 3},
{"fs_extractBisFile", part_fs_extractBisFile, 2},
{"mmc_connect", part_ConnectMMC, 1},
{"mmc_mount", part_MountMMC, 1},
{"mmc_dumpPart", part_mmc_dumpPart, 2},
{"mmc_restorePart", part_mmc_restorePart, 1},
{"getPosition", part_getPos, 0},
{"pause", part_Pause, 0},
{"wait", part_Wait, 1},
{"exit", part_Exit, 0},
{NULL, NULL, 0}
}; };
varVector_t extractVars(scriptCtx_t* ctx, lexarToken_t* tokens, u32 len) { #pragma GCC pop_options
varVector_t args = varVectorInit(4);
int lastLoc = 0;
for (int i = 0; i < len; i++) {
if (tokens[i].token == LSBracket) {
int distance = distanceBetweenTokens(&tokens[i + 1], len - i - 1, LSBracket, RSBracket);
i += distance + 1;
}
if (tokens[i].token == Seperator) {
dictValue_t res = solveEquation(ctx, &tokens[lastLoc], i - lastLoc);
lastLoc = i + 1;
varVectorAdd(&args, DictCreate(NULL, res));
}
if (i + 1 >= len) { int run_function(char *func_name, int *out){
dictValue_t res = solveEquation(ctx, &tokens[lastLoc], i + 1 - lastLoc); for (u32 i = 0; functions[i].key != NULL; i++){
varVectorAdd(&args, DictCreate(NULL, res)); if (!strcmp(functions[i].key, func_name)){
} if (argc != functions[i].arg_count && functions[i].arg_count != 255)
} continue;
return args; *out = functions[i].value();
} return (*out == INFUNC_FAIL) ? -1 : 0;
}
dictValue_t executeFunction(scriptCtx_t* ctx, char* func_name) { }
int argCount = 0; return -2;
varVector_t args = { 0 };
if (ctx->args_loc.stored > 0) {
args = extractVars(ctx, ctx->args_loc.tokens, ctx->args_loc.stored);
for (int i = 0; i < args.stored; i++) {
if (args.vars[i].value.varType == ErrType)
return args.vars[i].value;
}
argCount = args.stored;
}
for (u32 i = 0; functions[i].key != NULL; i++) {
if (!strcmp(functions[i].key, func_name)) {
if (argCount != functions[i].argCount && !functions[i].varArgs)
continue;
dictValue_t val = functions[i].value(ctx, &args);
// free args
varVectorFree(&args);
return val;
}
}
dictValue_t* var = varVectorFind(&ctx->vars, func_name);
if (var != NULL) {
if (var->type == JumpType) {
setCurIndentInstruction(ctx, 0, ctx->curPos);
ctx->curPos = var->integer - 1;
ctx->lastToken.token = Invalid;
return NullDictValue();
}
}
return ErrDictValue(ERRNOFUNC);
} }

View File

@@ -1,10 +1,13 @@
#pragma once #pragma once
#include "types.h" #include "../../utils/types.h"
#define BIT(n) (1U << n) typedef void (*func_void_ptr)();
typedef int (*func_int_ptr)();
#define VARARGS(x) {x, 1, 0} typedef struct {
#define OPERATORARGS(x) {x, 0, 1} char *key;
func_int_ptr value;
u8 arg_count;
} str_fnc_struct;
dictValue_t executeFunction(scriptCtx_t* ctx, char* func_name); int run_function(char *func_name, int *out);
varVector_t extractVars(scriptCtx_t* ctx, lexarToken_t* tokens, u32 len);

View File

@@ -1,195 +0,0 @@
#include "lexer.h"
#include "parser.h"
#include "args.h"
#include "../utils/utils.h"
#include "../../mem/heap.h"
#include <string.h>
static inline int isValidWord(char c) {
char r = c | 0x20;
return (r >= 'a' && r <= 'z');
}
static inline int isValidVar(char c) {
char r = c | 0x20;
return ((r >= 'a' && r <= 'z') || (r >= '0' && r <= '9'));
}
static inline int isValidNum(char c) {
return (c >= '0' && c <= '9');
}
static inline int isValidHexNum(char c) {
char r = c | 0x20;
return (isValidNum(r) || (r >= 'a' && r <= 'f'));
}
#define makeLexarToken(token, var) (lexarToken_t) {token, {var}}
#define makeLexarIntToken(intVar) (lexarToken_t) {IntLit, .val = intVar}
typedef struct {
u8 tokenC;
u16 tokenN;
} lexarTranslation_t;
lexarTranslation_t lexarTranslations[] = {
{'(', LBracket},
{')', RBracket},
{'{', LCBracket},
{'}', RCBracket},
{',', Seperator},
{'+', Plus},
{'-', Minus},
{'*', Multiply},
{'/', Division},
{'%', Mod},
{'<', Smaller},
{'>', Bigger},
{'=', Equal},
{'!', Not},
{'[', LSBracket},
{']', RSBracket},
{'\0', 0},
};
char lexarDebugGetTokenC(u16 tokenN) {
for (int i = 0; lexarTranslations[i].tokenC; i++) {
if (lexarTranslations[i].tokenN == tokenN) {
return lexarTranslations[i].tokenC;
}
}
return '?';
}
lexarVector_t lexarVectorInit(int startSize) {
lexarVector_t l = { 0 };
l.tokens = calloc(startSize, sizeof(lexarVector_t));
l.len = startSize;
l.stored = 0;
return l;
}
void lexarVectorAdd(lexarVector_t* vec, lexarToken_t token) {
if (vec->stored >= vec->len) {
vec->len *= 2;
//vec->tokens = realloc(vec->tokens, vec->len * sizeof(lexarToken_t));
void *temp = calloc(vec->len, sizeof(lexarToken_t));
memcpy(temp, vec->tokens, vec->len / 2 * sizeof(lexarToken_t));
free(vec->tokens);
vec->tokens = temp;
}
vec->tokens[vec->stored++] = token;
}
void lexarVectorClear(lexarVector_t* vec) {
for (int i = 0; i < vec->stored; i++) {
if (vec->tokens[i].token == Variable || vec->tokens[i].token == StrLit)
if (vec->tokens[i].text != NULL)
free(vec->tokens[i].text);
}
free(vec->tokens);
}
#define ELIFC(c) else if (*in == c)
lexarVector_t lexarGo(const char* in) {
lexarVector_t vec = lexarVectorInit(16);
while (*in) {
if (isValidWord(*in)) {
char* startWord = in;
in++;
while (isValidVar(*in))
in++;
lexarVectorAdd(&vec, makeLexarToken(Variable, utils_copyStringSize(startWord, in - startWord)));
continue;
}
else if (isValidNum(*in) || (*in == '-' && isValidNum(in[1]))) {
int parse = 0;
u8 negative = (*in == '-');
if (negative)
in++;
if (*in == '0' && (in[1] | 0x20) == 'x') {
in += 2;
while (isValidHexNum(*in)) {
parse = parse * 16 + (*in & 0x0F) + (*in >= 'A' ? 9 : 0);
in++;
}
}
else while (isValidNum(*in)) {
parse = parse * 10 + *in++ - '0';
}
if (negative)
parse *= -1;
lexarVectorAdd(&vec, makeLexarIntToken(parse));
continue;
}
ELIFC('"') {
char* startStr = ++in;
while (*in != '"')
in++;
lexarVectorAdd(&vec, makeLexarToken(StrLit, utils_copyStringSize(startStr, in - startStr)));
in++;
continue;
}
ELIFC('#') {
while (*in != '\n')
in++;
in++;
continue;
}
ELIFC('&') {
if (in[1] == '&') {
lexarVectorAdd(&vec, makeLexarToken(LogicAND, 0));
in++;
}
else {
lexarVectorAdd(&vec, makeLexarToken(AND, 0));
}
in++;
continue;
}
ELIFC('|') {
if (in[1] == '|') {
lexarVectorAdd(&vec, makeLexarToken(LogicOR, 0));
in++;
}
else {
lexarVectorAdd(&vec, makeLexarToken(OR, 0));
}
in++;
continue;
}
int val = 0;
for (int i = 0; lexarTranslations[i].tokenC; i++) {
if (lexarTranslations[i].tokenC == *in) {
val = lexarTranslations[i].tokenN;
break;
}
}
in++;
if (*in == '=' && val >= Smaller && val <= Not) {
val++;
in++;
}
if (val != Invalid)
lexarVectorAdd(&vec, makeLexarToken(val, 0));
}
return vec;
}

View File

@@ -1,6 +0,0 @@
#pragma once
#include "types.h"
lexarVector_t lexarGo(const char* in);
char lexarDebugGetTokenC(u16 tokenN);
void lexarVectorClear(lexarVector_t* vec);

View File

@@ -1,88 +0,0 @@
#include "list.h"
#include <string.h>
#include "types.h"
#include "../../mem/heap.h"
void freeDictValue(dictValue_t dv) {
if (dv.string == NULL)
return;
switch (dv.varType) {
case StringType:
case IntArrayType:
case ByteArrayType: // As it's a union with the biggest object being a pointer, this should be the same
free(dv.string);
break;
case StringArrayType:
for (unsigned int i = 0; i < dv.arrayLen; i++)
free(dv.stringArray[i]);
free(dv.stringArray);
}
}
void freeDict(dict_t* dict) {
freeDictValue(dict->value);
free(dict->key);
free(dict);
}
varVector_t varVectorInit(int startSize) {
varVector_t vec = { 0 };
vec.vars = calloc(startSize, sizeof(dict_t));
vec.len = startSize;
vec.stored = 0;
return vec;
}
dictValue_t* varVectorFind(varVector_t* vec, const char* key) {
for (int i = 0; i < vec->stored; i++) {
if (!strcmp(vec->vars[i].key, key))
return &vec->vars[i].value;
}
return NULL;
}
void varVectorAdd(varVector_t* vec, dict_t add) {
dictValue_t* var = NULL;
if (add.key != NULL)
var = varVectorFind(vec, add.key);
if (var != NULL) {
freeDictValue(*var);
*var = add.value;
free(add.key);
return;
}
if (vec->stored >= vec->len) {
vec->len *= 2;
dict_t* old = vec->vars;
//vec->vars = realloc(old, vec->len * sizeof(dict_t));
void *temp = calloc(vec->len, sizeof(dict_t));
memcpy(temp, vec->vars, vec->len / 2 * sizeof(dict_t));
free(vec->vars);
vec->vars = temp;
if (vec->vars == NULL) {
free(old);
}
}
vec->vars[vec->stored] = add;
vec->stored++;
}
void varVectorFree(varVector_t* vec) {
for (int i = 0; i < vec->stored; i++) {
dict_t *var = &vec->vars[i];
if (var->key != NULL) {
free(var->key);
var->key = NULL;
}
if (var->value.free)
freeDictValue(var->value);
}
free(vec->vars);
}

View File

@@ -1,25 +0,0 @@
#pragma once
#include "types.h"
#define dictValSetInt(dictVal, i) dictVal.integer = i; dictVal.type = IntType;
#define dictValSetStr(dictVal, str) dictVal.string = strdup(str); dictVal.type = StringType;
#define dictValSetJump(dictVal, i) dictVal.integer = i; dictVal.type = JumpType;
#define dictValInt(i) (dictValue_t) {IntType, 0, i}
#define DictCreate(key, value) (dict_t) {key, value}
#define DictValueCreate(type, arrayLen, val) (dictValue_t) {type, arrayLen, val}
void freeDictValue(dictValue_t dv);
void freeDict(dict_t* dict);
varVector_t varVectorInit(int startSize);
void varVectorAdd(varVector_t* vec, dict_t add);
dictValue_t* varVectorFind(varVector_t* vec, const char* key);
static inline void freeDictValueOnVar(dictValue_t dv) {
if (dv.free)
freeDictValue(dv);
}
void varVectorFree(varVector_t* vec);

View File

@@ -1,263 +1,319 @@
#include "args.h"
#include "parser.h"
#include "types.h"
#include "list.h"
#include "functions.h"
#include "scriptCtx.h"
#include "lexer.h"
#include <string.h> #include <string.h>
#include "../../mem/heap.h" #include "../../mem/heap.h"
#include "../utils/utils.h"
#include "../../storage/nx_sd.h"
#include "../../gfx/gfx.h"
#include "../../hid/hid.h"
#include "../gfx/gfxutils.h" #include "../gfx/gfxutils.h"
#include "../emmc/emmc.h"
#include "../../utils/types.h"
#include "../../libs/fatfs/ff.h"
#include "../../utils/sprintf.h"
#include "../../utils/btn.h"
#include "../../gfx/gfx.h"
#include "../../utils/util.h"
#include "../../storage/emummc.h"
#include "parser.h"
#include "../common/common.h"
#include "../fs/fsactions.h"
#include "functions.h"
#include "variables.h"
#include "../fs/fsreader.h"
#include "../utils/utils.h"
//#define DPRINTF(str, ...) printf(str, __VA_ARGS__) u32 countchars(char* in, char target) {
#define DPRINTF u32 len = strlen(in);
u32 count = 0;
#define findNextCharsCtx(ctx, targets) findNextChars(&(ctx->curPos), targets) for (u32 i = 0; i < len; i++) {
if (in[i] == '"'){
int checkIfVar(u16 token) { i++;
return (token == StrLit || token == IntLit || token == Variable || token == RSBracket); while (in[i] != '"'){
i++;
if (i >= len)
return -1;
}
}
if (in[i] == target)
count++;
}
return count;
} }
void printToken(lexarToken_t* token) { char **argv = NULL;
switch (token->token) { u32 argc;
case 1: u32 splitargs(char* in) {
gfx_printf("%s ", token->text); // arg like '5, "6", @arg7'
break; u32 i, current = 0, count = 1, len = strlen(in), curcount = 0;
case 6:
//printf("%d: '%s'\n", vec.tokens[i].token, vec.tokens[i].text); if ((count += countchars(in, ',')) < 0){
gfx_printf("\"%s\" ", token->text); return 0;
break; }
case 7:
//printf("%d: %d\n", vec.tokens[i].token, vec.tokens[i].val); /*
gfx_printf("%d ", token->val); if (argv != NULL) {
break; for (i = 0; argv[i] != NULL; i++)
default: free(argv[i]);
//printf("%d: %c\n", vec.tokens[i].token, lexarDebugGetTokenC(vec.tokens[i].token)); free(argv);
gfx_printf("%c ", lexarDebugGetTokenC(token->token)); }
break; */
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] == '"') {
i++;
while (in[i] != '"') {
argv[curcount][current++] = in[i++];
}
}
}
return count;
}
FIL scriptin;
UINT endByte = 0;
int forceExit = false;
char currentchar = 0;
char getnextchar(){
f_read(&scriptin, &currentchar, sizeof(char), &endByte);
if (sizeof(char) != endByte)
forceExit = true;
//gfx_printf("|%c|", currentchar);
return currentchar;
}
void getfollowingchar(char end){
while (currentchar != end && !f_eof(&scriptin)){
if (currentchar == '"'){
while (getnextchar() != '"' && !f_eof(&scriptin));
}
getnextchar();
} }
} }
scriptResult_t runFunction(scriptCtx_t* ctx) { void getnextvalidchar(){
dictValue_t res = solveEquation(ctx, &ctx->script->tokens[ctx->startEq], ctx->curPos - ctx->startEq); while ((!((currentchar >= '?' && currentchar <= 'Z') || (currentchar >= 'a' && currentchar <= 'z') || currentchar == '#') && !f_eof(&scriptin)) /*|| currentchar == ';' */)
getnextchar();
}
if (res.varType == ErrType) char *makestr(u32 size, char ignore){
return scriptResultCreate(res.integer, &ctx->script->tokens[ctx->startEq]); char *str;
u32 count = 0;
ctx->startEq = ctx->curPos; str = calloc(size + 1, sizeof(char));
if (ctx->varToken.token != Invalid) { // we should not assign null's for (u32 i = 0; i < size; i++){
ctx->varToken.token = Invalid; getnextchar();
if (ctx->varIndexSet) { if (ignore != 0 && ignore == currentchar)
ctx->varIndexSet = 0; continue;
dictValue_t* arrayVal = varVectorFind(&ctx->vars, ctx->varToken.text);
if (!(arrayVal == NULL || arrayVal->arrayLen <= ctx->varIndex)) { str[count++] = currentchar;
if (arrayVal->varType == IntArrayType && res.varType == IntType) { }
arrayVal->integerArray[ctx->varIndex] = res.integer;
} return str;
else if (arrayVal->varType == StringArrayType && res.varType == StringType) { }
free(arrayVal->stringArray[ctx->varIndex]);
arrayVal->stringArray[ctx->varIndex] = res.string; char *readtilchar(char end, char ignore){
} FSIZE_t offset, size;
else if (arrayVal->varType == ByteArrayType && res.varType == IntType) {
arrayVal->byteArray[ctx->varIndex] = (u8)(res.integer & 0xFF); offset = f_tell(&scriptin);
} getfollowingchar(end);
else { size = f_tell(&scriptin) - offset;
return scriptResultCreate(ERRINVALIDTYPE, &ctx->script->tokens[ctx->startEq]);
} if (size <= 0)
} return NULL;
else {
return scriptResultCreate(ERRNOVAR, &ctx->script->tokens[ctx->startEq]); f_lseek(&scriptin, offset - 1);
}
} return makestr((u32)size, ignore);
else { }
varVectorAdd(&ctx->vars, DictCreate(util_cpyStr(ctx->varToken.text), res));
}
char *funcbuff = NULL;
void functionparser(){
char *unsplitargs;
/*
if (funcbuff != NULL)
free(funcbuff);
*/
funcbuff = readtilchar('(', ' ');
getfollowingchar('(');
getnextchar();
unsplitargs = readtilchar(')', 0);
if (unsplitargs != NULL){
argc = splitargs(unsplitargs);
getnextchar();
} }
else { else {
freeDictValueOnVar(res); argc = 0;
} }
getnextchar();
return scriptResultCreate(0, 0); free(unsplitargs);
} }
// TODO char *gettargetvar(){
// Make sure mem gets free'd properly char *variable = NULL;
// Fix bug that custom functions cannot be run from end of script
// add arrays
#define RUNFUNCWITHPANIC(ctx) scriptResult_t res = runFunction(ctx); if (res.resCode != 0) return res variable = readtilchar('=', ' ');
scriptResult_t mainLoop(scriptCtx_t* ctx) { getfollowingchar('=');
for (ctx->curPos = 0; ctx->curPos < ctx->script->stored; ctx->curPos++) { getnextchar();
u32 i = ctx->curPos;
lexarToken_t curToken = ctx->script->tokens[i];
//printToken(&curToken);
if (checkIfVar(ctx->lastToken.token) && curToken.token == Variable) { return variable;
RUNFUNCWITHPANIC(ctx);
}
else if (curToken.token == Equal) {
// Set last var to lastToken, if lastToken is var
if (ctx->lastToken.token == RSBracket) {
int layer = 0;
i = ctx->lastTokenPos - 1;
for (; i > 0; i--) {
if (ctx->script->tokens[i].token == RSBracket)
layer++;
else if (ctx->script->tokens[i].token == LSBracket) {
if (layer == 0)
break;
layer--;
}
}
i--;
if (ctx->script->tokens[i].token == Variable) {
dictValue_t index = solveEquation(ctx, &ctx->script->tokens[i + 2], ctx->lastTokenPos - i - 2);
ctx->lastTokenPos = i;
ctx->lastToken = ctx->script->tokens[i];
if (index.varType == IntType) {
ctx->varIndex = index.integer;
ctx->varIndexSet = 1;
if (ctx->varIndexSet) {
dictValue_t* arrayVal = varVectorFind(&ctx->vars, ctx->varToken.text);
if (arrayVal == NULL) {
return scriptResultCreate(ERRSYNTAX, &ctx->script->tokens[ctx->curPos]);
}
if (ctx->varIndex < 0 || ctx->varIndex >= arrayVal->arrayLen || arrayVal->varType < IntArrayType)
return scriptResultCreate(ERRSYNTAX, &ctx->script->tokens[ctx->curPos]);
}
}
else
return scriptResultCreate(ERRINVALIDTYPE, &ctx->script->tokens[ctx->curPos]);
}
else
return scriptResultCreate(ERRSYNTAX, &ctx->script->tokens[ctx->curPos]);
}
if (ctx->lastToken.token == Variable) {
ctx->startEq = ctx->curPos + 1;
ctx->varToken = ctx->lastToken;
}
else
return scriptResultCreate(ERRSYNTAX, &ctx->script->tokens[ctx->curPos]);
//printf("Setting token %s to next assignment", ctx->lastToken.text);
// !! check prev for ] for arrays
}
else if (curToken.token == LBracket) {
i++;
int distance = distanceBetweenTokens(&ctx->script->tokens[i], ctx->script->stored - i, LBracket, RBracket);
if (distance < 0)
return scriptResultCreate(ERRSYNTAX, &ctx->script->tokens[ctx->curPos]);
i += distance;
ctx->curPos = i;
if (ctx->curPos + 1 >= ctx->script->stored && checkIfVar(ctx->lastToken.token)) {
solveEquation(ctx, &ctx->script->tokens[ctx->startEq], i + 1 - ctx->startEq);
}
continue;
}
else if (curToken.token == LCBracket) {
if (ctx->lastToken.token == Equal && ctx->varToken.token == Variable) {
varVectorAdd(&ctx->vars, DictCreate(util_cpyStr(ctx->varToken.text), DictValueCreate(JumpType, 0, ctx->curPos)));
ctx->varToken.token = Invalid;
setCurIndentInstruction(ctx, 1, -1);
}
if (checkIfVar(ctx->lastToken.token)) {
RUNFUNCWITHPANIC(ctx);
}
ctx->startEq = ctx->curPos + 1;
indentInstructor_t ins = getCurIndentInstruction(ctx);
if (ins.active) {
if (ins.skip) {
int distance = distanceBetweenTokens(&ctx->script->tokens[i + 1], ctx->script->stored - i - 1, LCBracket, RCBracket);
if (distance < 0)
return scriptResultCreate(ERRSYNTAX, &ctx->script->tokens[ctx->curPos]);
ctx->curPos += distance + 1;
ctx->startEq = ctx->curPos + 1;
}
else {
ctx->indentLevel++;
}
}
else
return scriptResultCreate(ERRINACTIVEINDENT, &ctx->script->tokens[ctx->curPos]);
}
else if (curToken.token == RCBracket) {
if (checkIfVar(ctx->lastToken.token)) {
RUNFUNCWITHPANIC(ctx);
if (i != ctx->curPos)
continue;
}
ctx->indentLevel--;
indentInstructor_t ins = getCurIndentInstruction(ctx);
if (ins.active && ins.jump) {
ctx->curPos = ins.jumpLoc - 1;
}
ctx->startEq = ctx->curPos + 1;
}
else if (ctx->curPos + 1 >= ctx->script->stored && checkIfVar(ctx->lastToken.token)) {
solveEquation(ctx, &ctx->script->tokens[ctx->startEq], i + 1 - ctx->startEq);
}
ctx->lastToken = ctx->script->tokens[ctx->curPos];
ctx->lastTokenPos = ctx->curPos;
}
return scriptResultCreate(0, 0);
} }
const char* functionFails[] = { void mainparser(){
"An invalid operation was performed", char *variable = NULL;
"Double Nots are not allowed", int res, out = 0;
"A syntax error was found",
"The recieved type was incorrect",
"The variable could not be found",
"The specified function could not be found",
"An inactive indent was found"
};
void startScript(char* path) { getnextvalidchar();
char* file = sd_file_read(path, NULL);
if (file == NULL) if (f_eof(&scriptin))
return; return;
gfx_clearscreen(); if (currentchar == '#'){
getfollowingchar('\n');
scriptCtx_t ctx = createScriptCtx(); return;
lexarVector_t vec = lexarGo(file);
free(file);
ctx.script = &vec;
scriptResult_t res = mainLoop(&ctx);
gfx_printf("end of script\n");
if (res.resCode) {
gfx_printf("[ERROR] %d\n%s\nNear:", res.resCode, functionFails[res.resCode - 1]);
printToken(res.nearToken);
} }
gfx_printf("\n\n"); if (currentchar == '@'){
//mainLoop2(&ctx, &vec); variable = gettargetvar();
lexarVectorClear(&vec); getnextvalidchar();
destroyScriptCtx(&ctx); }
hidWait();
/*
if (currentchar == '?'){
char *jumpname;
jumpname = readtilchar(';', ' ');
getnextchar();
str_jmp_add(jumpname, f_tell(&scriptin));
getfollowingchar('\n');
return;
}
*/
functionparser();
res = run_function(funcbuff, &out);
if (res < 0){
printerrors = true;
//gfx_printf("%s|%s|%d", funcbuff, argv[0], argc);
//btn_wait();
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]);
}
else {
str_int_add("@RESULT", out);
if (variable != NULL)
str_int_add(variable, out);
}
//gfx_printf("\nGoing to next func %c\n", currentchar);
if (funcbuff != NULL){
free(funcbuff);
funcbuff = NULL;
}
if (argv != NULL) {
for (int i = 0; argv[i] != NULL; i++)
free(argv[i]);
free(argv);
argv = NULL;
}
if (variable != NULL){
free(variable);
}
}
void skipbrackets(){
u32 bracketcounter = 0;
getfollowingchar('{');
getnextchar();
while ((currentchar != '}' || bracketcounter != 0) && !f_eof(&scriptin)){
if (currentchar == '{')
bracketcounter++;
else if (currentchar == '}')
bracketcounter--;
getnextchar();
}
}
extern u32 currentcolor;
extern char *currentpath;
void runScript(char *path){
int res;
char *path_local = NULL;
forceExit = false;
currentchar = 0;
currentcolor = COLOR_WHITE;
gfx_clearscreen();
utils_copystring(path, &path_local);
res = f_open(&scriptin, path, FA_READ | FA_OPEN_EXISTING);
DWORD *clmt_in = f_expand_cltbl(&scriptin, BUFSIZE / 4, 0);
if (res != FR_OK){
gfx_errDisplay("ParseScript", res, 1);
return;
}
printerrors = false;
//add builtin vars
str_int_add("@EMUMMC", emu_cfg.enabled);
str_int_add("@RESULT", 0);
str_str_add("$CURRENTPATH", currentpath);
//str_int_printall();
while (!f_eof(&scriptin) && !forceExit){
mainparser();
}
printerrors = true;
//str_int_printall();
f_close(&scriptin);
str_int_clear();
//str_jmp_clear();
str_str_clear();
free(path_local);
//btn_wait();
} }

View File

@@ -1,9 +1,7 @@
#pragma once #pragma once
#include "types.h" #define INFUNC_FAIL (int)0xC0000000
//#define DictValue(type, val, len) (dictValue_t) {type, len, val}
#define scriptResultCreate(resCode, funcName) (scriptResult_t) {resCode, funcName} void runScript(char *path);
void skipbrackets();
void startScript(char* path); void getfollowingchar(char end);
char* readFile(char* path);

View File

@@ -1,37 +0,0 @@
#include "scriptCtx.h"
#include "list.h"
#include "malloc.h"
#include "types.h"
scriptCtx_t createScriptCtx() {
scriptCtx_t ctx;
ctx.indentInstructors = calloc(sizeof(indentInstructor_t), 64);
ctx.indentLevel = 0;
ctx.vars = varVectorInit(16);
ctx.script = NULL;
ctx.lastToken.token = 0;
ctx.varToken.token = 0;
ctx.startEq = 0;
ctx.varIndexStruct = 0;
return ctx;
}
void destroyScriptCtx(scriptCtx_t* ctx) {
// TODO
varVectorFree(&ctx->vars);
free(ctx->indentInstructors);
}
u8 setIndentInstruction(scriptCtx_t* ctx, u8 level, u8 skip, int jumpLoc) {
if (level >= 64)
return 1;
ctx->indentInstructors[level].skip = skip;
ctx->indentInstructors[level].active = 1;
ctx->indentInstructors[level].jump = (jumpLoc >= 0) ? 1 : 0;
ctx->indentInstructors[level].jumpLoc = jumpLoc;
return 0;
}

View File

@@ -1,19 +0,0 @@
#pragma once
#include "types.h"
#define TEXTHOLDEREMPTY() (textHolder_t) {0}
#define TEXTHOLDER(start, len) (textHolder_t) {start, len, 1}
u8 setIndentInstruction(scriptCtx_t* ctx, u8 level, u8 skip, int jumpLoc);
void destroyScriptCtx(scriptCtx_t* ctx);
scriptCtx_t createScriptCtx();
static inline indentInstructor_t getCurIndentInstruction(scriptCtx_t* ctx);
static inline u8 setCurIndentInstruction(scriptCtx_t* ctx, u8 skip, int jumpLoc);
static inline u8 setCurIndentInstruction(scriptCtx_t* ctx, u8 skip, int jumpLoc) {
return setIndentInstruction(ctx, ctx->indentLevel, skip, jumpLoc);
}
static inline indentInstructor_t getCurIndentInstruction(scriptCtx_t* ctx) {
return ctx->indentInstructors[ctx->indentLevel];
}

View File

@@ -1,174 +0,0 @@
#pragma once
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef struct {
u16 token;
union {
char* text;
int val;
};
} lexarToken_t;
typedef struct {
lexarToken_t* tokens;
u32 len;
u32 stored;
} lexarVector_t;
enum Tokens {
Invalid = 0,
Variable = 1,
LBracket,
RBracket,
RCBracket,
LCBracket,
StrLit,
IntLit,
Seperator,
Plus,
Minus,
Multiply,
Division,
Mod,
Smaller,
SmallerEqual,
Bigger,
BiggerEqual,
Equal,
EqualEqual,
Not,
NotEqual,
LogicAND,
LogicOR,
LSBracket,
RSBracket,
AND,
OR
};
enum Errors {
ERRBADOPERATOR = 1,
ERRDOUBLENOT,
ERRSYNTAX,
ERRINVALIDTYPE,
ERRNOVAR,
ERRNOFUNC,
ERRINACTIVEINDENT
};
typedef struct { // this is to keep track of how many {} we passed. Keep an internal var with the "indentation level", +1 for {, -1 for }. have an array with the following def on what to do (on func: enter, set indentation & jump back, on while, jump to while, use while as if, on if simply set true or false)
union {
struct {
u8 active : 1;
u8 skip : 1;
u8 jump : 1;
};
u8 container;
};
int jumpLoc;
} indentInstructor_t;
typedef struct {
char* start;
u32 len;
union {
struct {
u8 set : 1;
};
u8 options;
};
} textHolder_t;
typedef struct {
int resCode;
lexarToken_t* nearToken;
} scriptResult_t;
#define JumpDictValue(jump) (dictValue_t) {{JumpType}, 0, .integer = jump}
#define StrDictValue(str) (dictValue_t) {{StringType}, 0, .string = str}
#define ErrDictValue(err) (dictValue_t) {{ErrType}, 0, .integer = err}
#define NullDictValue() (dictValue_t) {{NullType}, 0, .integer = 0}
#define IntArrDictValue(arr, len) (dictValue_t) {{IntArrayType}, len, .integerArray = arr}
#define StringArrDictValue(arr, len) (dictValue_t) {{StringArrayType}, len, .stringArray = arr}
#define IntDictValue(i) (dictValue_t) {{IntType}, 0, .integer = i}
enum {
IntType = 0,
StringType,
IntArrayType,
StringArrayType,
ByteArrayType,
JumpType,
DictType,
NullType,
ErrType,
};
typedef struct {
union {
u8 type;
struct {
u8 varType : 7;
u8 free : 1;
};
};
unsigned int arrayLen;
union {
int integer;
char* string;
unsigned char* byteArray;
int* integerArray;
char** stringArray;
};
} dictValue_t;
typedef struct {
char* key;
dictValue_t value;
} dict_t;
typedef struct {
dict_t* vars;
u32 len;
u32 stored;
} varVector_t;
typedef struct {
indentInstructor_t* indentInstructors;
u8 indentLevel; // -> max 63
varVector_t vars;
lexarVector_t* script;
lexarToken_t lastToken;
lexarToken_t varToken;
u32 startEq;
u32 curPos;
u32 lastTokenPos;
lexarVector_t args_loc;
union {
u32 varIndexStruct;
struct {
u32 varIndex : 31;
u32 varIndexSet : 1;
};
};
} scriptCtx_t;
typedef dictValue_t(*func_int_ptr)(scriptCtx_t* ctx, varVector_t* args);
typedef struct {
char* key;
func_int_ptr value;
union {
u8 args;
struct {
u8 argCount : 6;
u8 varArgs : 1;
u8 operatorParse : 1;
};
};
} str_fnc_struct;
#define FREEINDICT 0x80

View File

@@ -0,0 +1,250 @@
#include <string.h>
#include "../../mem/heap.h"
#include "../gfx/gfxutils.h"
#include "../emmc/emmc.h"
#include "../../utils/types.h"
#include "../../libs/fatfs/ff.h"
#include "../../utils/sprintf.h"
#include "../../utils/btn.h"
#include "../../gfx/gfx.h"
#include "../../utils/util.h"
#include "../../storage/emummc.h"
#include "parser.h"
#include "../common/common.h"
#include "../fs/fsactions.h"
#include "variables.h"
#include "../utils/utils.h"
static dict_str_int *str_int_table = NULL;
static dict_str_str *str_str_table = NULL;
//static dict_str_loc *str_jmp_table = NULL;
int str_int_add(char *key, int value){
char *key_local;
dict_str_int *keyvaluepair;
utils_copystring(key, &key_local);
keyvaluepair = calloc(1, sizeof(dict_str_int));
keyvaluepair->key = key_local;
keyvaluepair->value = value;
keyvaluepair->next = NULL;
if (str_int_table == NULL){
str_int_table = keyvaluepair;
}
else {
dict_str_int *temp;
temp = str_int_table;
while (temp != NULL){
if (!strcmp(temp->key, key_local)){
free(keyvaluepair);
free(key_local);
temp->value = value;
return 0;
}
if (temp->next == NULL){
temp->next = keyvaluepair;
return 0;
}
temp = temp->next;
}
}
return 0;
}
int str_int_find(char *key, int *out){
dict_str_int *temp;
temp = str_int_table;
while (temp != NULL){
if (!strcmp(temp->key, key)){
*out = temp->value;
return 0;
}
temp = temp->next;
}
return -1;
}
void str_int_clear(){
dict_str_int *cur, *next;
cur = str_int_table;
while (cur != NULL){
next = cur->next;
free(cur->key);
free(cur);
cur = next;
}
str_int_table = NULL;
}
void str_int_printall(){
dict_str_int *temp;
temp = str_int_table;
while (temp != NULL){
gfx_printf("%s -> %d\n", temp->key, temp->value);
temp = temp->next;
}
}
/*
int str_jmp_add(char *key, u64 value){
char *key_local;
dict_str_loc *keyvaluepair;
//gfx_printf("Adding |%s|\n", key_local);
utils_copystring(key, &key_local);
keyvaluepair = calloc(1, sizeof(dict_str_loc));
keyvaluepair->key = key_local;
keyvaluepair->value = value;
keyvaluepair->next = NULL;
if (str_jmp_table == NULL){
str_jmp_table = keyvaluepair;
}
else {
dict_str_loc *temp;
temp = str_jmp_table;
while (temp != NULL){
if (!strcmp(temp->key, key_local)){
free(keyvaluepair);
free(key_local);
temp->value = value;
return 0;
}
if (temp->next == NULL){
temp->next = keyvaluepair;
return 0;
}
temp = temp->next;
}
}
return 0;
}
int str_jmp_find(char *key, u64 *out){
dict_str_loc *temp;
temp = str_jmp_table;
//gfx_printf("Searching |%s|\n", key);
while (temp != NULL){
if (!strcmp(temp->key, key)){
//gfx_printf("Key found!\n", temp->value);
*out = temp->value;
return 0;
}
temp = temp->next;
}
//gfx_printf("no key!\n");
return -1;
}
void str_jmp_clear(){
dict_str_loc *cur, *next;
cur = str_jmp_table;
while (cur != NULL){
next = cur->next;
free(cur->key);
free(cur);
cur = next;
}
str_jmp_table = NULL;
}
*/
int str_str_add(char *key, char *value){
char *key_local, *value_local;
dict_str_str *keyvaluepair;
//gfx_printf("Adding |%s|\n", key_local);
utils_copystring(value, &value_local);
utils_copystring(key, &key_local);
keyvaluepair = calloc(1, sizeof(dict_str_str));
keyvaluepair->key = key_local;
keyvaluepair->value = value_local;
keyvaluepair->next = NULL;
if (str_str_table == NULL){
str_str_table = keyvaluepair;
}
else {
dict_str_str *temp;
temp = str_str_table;
while (temp != NULL){
if (!strcmp(temp->key, key_local)){
free(keyvaluepair);
free(key_local);
free(temp->value);
temp->value = value_local;
return 0;
}
if (temp->next == NULL){
temp->next = keyvaluepair;
return 0;
}
temp = temp->next;
}
}
return 0;
}
int str_str_find(char *key, char **out){
dict_str_str *temp;
temp = str_str_table;
while (temp != NULL){
if (!strcmp(temp->key, key)){
*out = temp->value;
return 0;
}
temp = temp->next;
}
return -1;
}
int str_str_index(int index, char **out){
dict_str_str *temp;
temp = str_str_table;
for (int i = 0; i < index; i++){
if (temp == NULL)
return -1;
temp = temp->next;
}
if (temp == NULL)
return -1;
*out = temp->value;
return 0;
}
void str_str_clear(){
dict_str_str *cur, *next;
cur = str_str_table;
while (cur != NULL){
next = cur->next;
free(cur->key);
free(cur->value);
free(cur);
cur = next;
}
str_str_table = NULL;
}

View File

@@ -0,0 +1,34 @@
#pragma once
#include "../../utils/types.h"
typedef struct _dict_str_int {
char *key;
int value;
struct _dict_str_int *next;
} dict_str_int;
typedef struct _dict_str_str {
char *key;
char *value;
struct _dict_str_str *next;
} dict_str_str;
typedef struct _dict_str_loc {
char *key;
u64 value;
struct _dict_str_loc *next;
} dict_str_loc;
int str_int_add(char *key, int value);
int str_int_find(char *key, int *out);
void str_int_clear();
void str_int_printall();
/*
int str_jmp_add(char *key, u64 value);
int str_jmp_find(char *key, u64 *out);
void str_jmp_clear();
*/
int str_str_add(char *key, char *value);
int str_str_find(char *key, char **out);
int str_str_index(int index, char **out);
void str_str_clear();

View File

@@ -17,7 +17,6 @@
#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();
@@ -94,9 +93,7 @@ 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;
@@ -110,22 +107,6 @@ int dumpfirmware(int mmc, bool daybreak){
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");
@@ -134,24 +115,7 @@ int dumpfirmware(int mmc, bool daybreak){
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)))
@@ -163,39 +127,16 @@ int dumpfirmware(int mmc, bool daybreak){
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);
@@ -204,9 +145,7 @@ int dumpfirmware(int mmc, bool daybreak){
fail = true; fail = true;
free(sdpath); free(sdpath);
free(syspathtemp); free(syspath);
if (syspath != syspathtemp)
free(syspath);
} }
printerrors = 1; printerrors = 1;

View File

@@ -1,7 +1,6 @@
#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, bool daybreak); int dumpfirmware(int mmc);

View File

@@ -193,19 +193,3 @@ 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;
}
char* util_cpyStr(const char* in){
char *out = malloc(strlen(in) + 1);
strcpy(out, in);
return out;
}

View File

@@ -24,5 +24,3 @@ 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);
char* util_cpyStr(const char* in);