diff --git a/Makefile b/Makefile
index bd2925c..7f4fdc5 100644
--- a/Makefile
+++ b/Makefile
@@ -8,7 +8,7 @@ include $(DEVKITARM)/base_rules
################################################################################
-IPL_LOAD_ADDR := 0x40008000
+IPL_LOAD_ADDR := 0x40003000
LPVERSION_MAJOR := 3
LPVERSION_MINOR := 0
LPVERSION_BUGFX := 2
diff --git a/common/common_gfx.h b/common/common_gfx.h
index 6bae186..d2e579f 100644
--- a/common/common_gfx.h
+++ b/common/common_gfx.h
@@ -1,9 +1,9 @@
/*
* Common Gfx Header
* Copyright (c) 2018 naehrwert
- * Copyright (c) 2018 CTCaer
- * Copyright (c) 2018 M4xw
- *
+ * Copyright (C) 2018 CTCaer
+ * Copyright (C) 2018 M4xw
+ *
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
diff --git a/common/common_module.h b/common/common_module.h
index 93a1541..1d3fb89 100644
--- a/common/common_module.h
+++ b/common/common_module.h
@@ -1,6 +1,6 @@
/*
* Common Module Header
- * Copyright (c) 2018 M4xw
+ * Copyright (C) 2018 M4xw
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
diff --git a/common/memory_map.h b/common/memory_map.h
index 16272c9..a1a41cb 100644
--- a/common/memory_map.h
+++ b/common/memory_map.h
@@ -19,8 +19,8 @@
//#define IPL_STACK_TOP 0x4003FF00
/* --- BIT/BCT: 0x40000000 - 0x40003000 --- */
-/* --- IPL: 0x40008000 - 0x40028000 --- */
-#define IPL_LOAD_ADDR 0x40008000
+/* --- IPL: 0x40003000 - 0x40028000 --- */
+#define IPL_LOAD_ADDR 0x40003000
#define IPL_SZ_MAX 0x20000 // 128KB.
//#define IRAM_LIB_ADDR 0x4002B000
#define SDRAM_PARAMS_ADDR 0x40030000 // SDRAM extraction buffer during sdram init.
diff --git a/source/hos/fss.c b/source/hos/fss.c
new file mode 100644
index 0000000..a68deeb
--- /dev/null
+++ b/source/hos/fss.c
@@ -0,0 +1,220 @@
+/*
+ * Atmosphère Fusée Secondary Storage parser.
+ *
+ * Copyright (c) 2019-2020 CTCaer
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+
+#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;
+}
diff --git a/source/hos/fss.h b/source/hos/fss.h
new file mode 100644
index 0000000..3f56d7c
--- /dev/null
+++ b/source/hos/fss.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2019 CTCaer
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#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
diff --git a/source/hos/hos.h b/source/hos/hos.h
new file mode 100644
index 0000000..d2c8712
--- /dev/null
+++ b/source/hos/hos.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2018 naehrwert
+ * Copyright (c) 2018-2020 CTCaer
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#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
+
+#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
diff --git a/source/hos/pkg2.c b/source/hos/pkg2.c
index 74c59c5..09ebb67 100644
--- a/source/hos/pkg2.c
+++ b/source/hos/pkg2.c
@@ -26,15 +26,15 @@
#include "../gfx/gfx.h"
+u32 pkg2_newkern_ini1_val;
+u32 pkg2_newkern_ini1_start;
+u32 pkg2_newkern_ini1_end;
+
/*#include "util.h"
#define DPRINTF(...) gfx_printf(__VA_ARGS__)
#define DEBUG_PRINTING*/
#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)
{
u32 size = sizeof(pkg2_kip1_t);
diff --git a/source/hos/pkg2.h b/source/hos/pkg2.h
index 5e7c3de..96e8fe5 100644
--- a/source/hos/pkg2.h
+++ b/source/hos/pkg2.h
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
- * Copyright (C) 2018-2020 CTCaer
+ * Copyright (c) 2018-2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -32,6 +32,14 @@ extern u32 pkg2_newkern_ini1_val;
extern u32 pkg2_newkern_ini1_start;
extern u32 pkg2_newkern_ini1_end;
+typedef struct _kernel_patch_t
+{
+ u32 id;
+ u32 off;
+ u32 val;
+ u32 *ptr;
+} kernel_patch_t;
+
typedef struct _pkg2_hdr_t
{
u8 ctr[0x10];
@@ -87,6 +95,12 @@ typedef struct _pkg2_kip1_info_t
link_t link;
} pkg2_kip1_info_t;
+typedef struct _pkg2_kernel_id_t
+{
+ u8 hash[8];
+ kernel_patch_t *kernel_patchset;
+} pkg2_kernel_id_t;
+
bool pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2, bool *new_pkg2);
int pkg2_decompress_kip(pkg2_kip1_info_t* ki, u32 sectsToDecomp);
pkg2_hdr_t *pkg2_decrypt(void *data);
diff --git a/source/hos/sept.c b/source/hos/sept.c
index 1858533..84d0181 100644
--- a/source/hos/sept.c
+++ b/source/hos/sept.c
@@ -17,15 +17,20 @@
#include
#include "sept.h"
+#include "../config/ini.h"
#include "../gfx/di.h"
+#include "../hos/fss.h"
+#include "../hos/hos.h"
#include "../libs/fatfs/ff.h"
#include "../mem/heap.h"
#include "../soc/hw_init.h"
#include "../soc/pmc.h"
#include "../soc/t210.h"
#include "../storage/nx_emmc.h"
+#include "../storage/nx_sd.h"
#include "../storage/sdmmc.h"
#include "../utils/btn.h"
+#include "../utils/list.h"
#include "../utils/types.h"
#include "../gfx/gfx.h"
@@ -58,48 +63,81 @@ u8 warmboot_reboot[] = {
extern u32 color_idx;
extern boot_cfg_t b_cfg;
-extern void sd_unmount();
extern void reloc_patcher(u32 payload_dst, u32 payload_src, u32 payload_size);
int reboot_to_sept(const u8 *tsec_fw, const u32 tsec_size, const u32 kb)
{
FIL fp;
+ bool fss0_sept_used = false;
// Copy warmboot reboot code and TSEC fw.
memcpy((u8 *)(SEPT_PK1T_ADDR - WB_RST_SIZE), (u8 *)warmboot_reboot, sizeof(warmboot_reboot));
memcpy((void *)SEPT_PK1T_ADDR, tsec_fw, tsec_size);
*(vu32 *)SEPT_TCSZ_ADDR = tsec_size;
- // Copy sept-primary.
- if (f_open(&fp, "sd:/sept/sept-primary.bin", FA_READ))
- goto error;
+ LIST_INIT(ini_sections);
+ if (ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false))
+ {
+ bool found = false;
+ LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
+ {
+ // Only parse non config sections.
+ if (ini_sec->type == INI_CHOICE && strcmp(ini_sec->name, "config"))
+ {
+ LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
+ {
+ if (!strcmp("fss0", kv->key))
+ {
+ fss0_sept_t sept_ctxt;
+ sept_ctxt.kb = kb;
+ sept_ctxt.sept_primary = (void *)SEPT_STG1_ADDR;
+ sept_ctxt.sept_secondary = (void *)SEPT_STG2_ADDR;
+ fss0_sept_used = parse_fss(NULL, kv->val, &sept_ctxt);
- if (f_read(&fp, (u8 *)SEPT_STG1_ADDR, f_size(&fp), NULL))
- {
- f_close(&fp);
- goto error;
+ found = true;
+ break;
+ }
+ }
+ }
+ if (found)
+ break;
+ }
}
- f_close(&fp);
- // Copy sept-secondary.
- if (kb < KB_FIRMWARE_VERSION_810)
+
+ if (!fss0_sept_used)
{
- if (f_open(&fp, "sd:/sept/sept-secondary_00.enc", FA_READ))
- 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))
+ // Copy sept-primary.
+ if (f_open(&fp, "sd:/sept/sept-primary.bin", FA_READ))
goto error;
- }
- if (f_read(&fp, (u8 *)SEPT_STG2_ADDR, f_size(&fp), NULL))
- {
+ if (f_read(&fp, (u8 *)SEPT_STG1_ADDR, f_size(&fp), NULL))
+ {
+ f_close(&fp);
+ goto error;
+ }
+ f_close(&fp);
+
+ // Copy sept-secondary.
+ if (kb < KB_FIRMWARE_VERSION_810)
+ {
+ if (f_open(&fp, "sd:/sept/sept-secondary_00.enc", FA_READ))
+ if (f_open(&fp, "sd:/sept/sept-secondary.enc", FA_READ)) // Try the deprecated version.
+ goto error;
+ }
+ else
+ {
+ if (f_open(&fp, "sd:/sept/sept-secondary_01.enc", FA_READ))
+ goto error;
+ }
+
+ if (f_read(&fp, (u8 *)SEPT_STG2_ADDR, f_size(&fp), NULL))
+ {
+ f_close(&fp);
+ goto error;
+ }
f_close(&fp);
- goto error;
}
- f_close(&fp);
// Save auto boot config to sept payload, if any.
boot_cfg_t *tmp_cfg = malloc(sizeof(boot_cfg_t));
@@ -107,7 +145,8 @@ int reboot_to_sept(const u8 *tsec_fw, const u32 tsec_size, const u32 kb)
tmp_cfg->boot_cfg |= BOOT_CFG_SEPT_RUN;
- if (f_open(&fp, "sd:/sept/payload.bin", FA_READ | FA_WRITE)) {
+ if (f_open(&fp, "sd:/sept/payload.bin", FA_READ | FA_WRITE))
+ {
free(tmp_cfg);
goto error;
}
diff --git a/source/libs/fatfs/diskio.c b/source/libs/fatfs/diskio.c
index 62d8373..9edd52a 100644
--- a/source/libs/fatfs/diskio.c
+++ b/source/libs/fatfs/diskio.c
@@ -81,8 +81,10 @@ static inline void _gf256_mul_x_le(void *block) {
static inline int _emmc_xts(u32 ks1, u32 ks2, u32 enc, u8 *tweak, bool regen_tweak, u32 tweak_exp, u64 sec, void *dst, void *src, u32 secsize) {
int res = 0;
- u8 *pdst = (u8 *)dst;
- u8 *psrc = (u8 *)src;
+ u8 *temptweak = (u8 *)malloc(0x10);
+ u32 *pdst = (u32 *)dst;
+ u32 *psrc = (u32 *)src;
+ u32 *ptweak = (u32 *)tweak;
if (regen_tweak) {
for (int i = 0xF; i >= 0; i--) {
@@ -96,34 +98,33 @@ static inline int _emmc_xts(u32 ks1, u32 ks2, u32 enc, u8 *tweak, bool regen_twe
for (u32 i = 0; i < tweak_exp * 0x20; i++)
_gf256_mul_x_le(tweak);
- u8 temptweak[0x10];
memcpy(temptweak, tweak, 0x10);
//We are assuming a 0x10-aligned sector size in this implementation.
for (u32 i = 0; i < secsize / 0x10; i++) {
- for (u32 j = 0; j < 0x10; j++)
- pdst[j] = psrc[j] ^ tweak[j];
+ for (u32 j = 0; j < 4; j++)
+ pdst[j] = psrc[j] ^ ptweak[j];
_gf256_mul_x_le(tweak);
- psrc += 0x10;
- pdst += 0x10;
+ psrc += 4;
+ pdst += 4;
}
se_aes_crypt_ecb(ks2, enc, dst, secsize, dst, secsize);
- pdst = (u8 *)dst;
+ pdst = (u32 *)dst;
memcpy(tweak, temptweak, 0x10);
for (u32 i = 0; i < secsize / 0x10; i++) {
- for (u32 j = 0; j < 0x10; j++)
- pdst[j] = pdst[j] ^ tweak[j];
+ for (u32 j = 0; j < 4; j++)
+ pdst[j] = pdst[j] ^ ptweak[j];
_gf256_mul_x_le(tweak);
- pdst += 0x10;
+ pdst += 4;
}
-
res = 1;
out:;
+ free(temptweak);
return res;
}
diff --git a/source/libs/fatfs/ff.c b/source/libs/fatfs/ff.c
index 2464273..736568f 100644
--- a/source/libs/fatfs/ff.c
+++ b/source/libs/fatfs/ff.c
@@ -42,8 +42,8 @@
#include "../../storage/sdmmc.h"
extern sdmmc_storage_t sd_storage;
-#define EFSPRINTF(text, ...) print_error(); gfx_printf("%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF);
-//#define EFSPRINTF(...)
+//#define EFSPRINTF(text, ...) print_error(); gfx_printf("%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF);
+#define EFSPRINTF(...)
/*--------------------------------------------------------------------------
diff --git a/source/mem/heap.c b/source/mem/heap.c
index 4ed7230..7c0e202 100644
--- a/source/mem/heap.c
+++ b/source/mem/heap.c
@@ -136,7 +136,7 @@ void *malloc(u32 size)
void *calloc(u32 num, u32 size)
{
void *res = (void *)_heap_alloc(&_heap, num * size);
- memset(res, 0, num * size);
+ memset(res, 0, ALIGN(num * size, sizeof(hnode_t))); // Clear the aligned size.
return res;
}
@@ -164,7 +164,7 @@ void heap_monitor(heap_monitor_t *mon, bool print_node_stats)
count, node->used, (u32)node + sizeof(hnode_t), node->size);
count++;
-
+
if (node->next)
node = node->next;
else
diff --git a/source/rtc/max77620-rtc.c b/source/rtc/max77620-rtc.c
index 385c936..d2a780a 100644
--- a/source/rtc/max77620-rtc.c
+++ b/source/rtc/max77620-rtc.c
@@ -2,7 +2,7 @@
* PMIC Real Time Clock driver for Nintendo Switch's MAX77620-RTC
*
* Copyright (c) 2018-2019 CTCaer
- * Copyright (c) 2019 shchmue
+ * Copyright (c) 2019-2020 shchmue
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -35,10 +35,10 @@ void max77620_rtc_get_time(rtc_time_t *time)
// Get time.
time->sec = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_SEC_REG) & 0x7F;
time->min = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_MIN_REG) & 0x7F;
- u8 hour = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_HOUR_REG);
- time->hour = hour & 0x1F;
- if (!(val & MAX77620_RTC_24H) && (hour & MAX77620_RTC_HOUR_PM_MASK))
+ time->hour = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_HOUR_REG) & 0x1F;
+
+ if (!(val & MAX77620_RTC_24H) && time->hour & MAX77620_RTC_HOUR_PM_MASK)
time->hour = (time->hour & 0xF) + 12;
// Get day of week. 1: Monday to 7: Sunday.
diff --git a/source/sec/se.c b/source/sec/se.c
index 6eb4700..484f3c8 100644
--- a/source/sec/se.c
+++ b/source/sec/se.c
@@ -19,6 +19,7 @@
#include
+#include "../../common/memory_map.h"
#include "../sec/se.h"
#include "../mem/heap.h"
#include "../soc/bpmp.h"
@@ -94,7 +95,12 @@ static int _se_wait()
static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size)
{
- se_ll_t *ll_dst = (se_ll_t *)0xECFFFFE0, *ll_src = (se_ll_t *)0xECFFFFF0;
+ static se_ll_t *ll_dst = NULL, *ll_src = NULL;
+ if (!ll_dst)
+ {
+ ll_dst = (se_ll_t *)malloc(sizeof(se_ll_t));
+ ll_src = (se_ll_t *)malloc(sizeof(se_ll_t));
+ }
if (dst)
{
@@ -234,6 +240,16 @@ void se_aes_key_set(u32 ks, const void *key, u32 size)
}
}
+void se_aes_iv_set(u32 ks, const void *iv, u32 size)
+{
+ u32 *data = (u32 *)iv;
+ for (u32 i = 0; i < size / 4; i++)
+ {
+ SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | 8 | i;
+ SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data[i];
+ }
+}
+
void se_aes_key_read(u32 ks, void *key, u32 size)
{
u32 *data = (u32 *)key;
@@ -320,12 +336,90 @@ int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_s
return 1;
}
+// random calls were derived from Atmosphère's
+int se_initialize_rng(u32 ks)
+{
+ u8 *output_buf = (u8 *)malloc(0x10);
+
+ SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
+ SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) |
+ SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
+ SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_MODE(RNG_MODE_FORCE_INSTANTION) | SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY);
+ SE(SE_RNG_RESEED_INTERVAL_REG_OFFSET) = 70001;
+ SE(SE_RNG_SRC_CONFIG_REG_OFFSET) = SE_RNG_SRC_CONFIG_ENT_SRC_LOCK(RNG_SRC_RO_ENT_LOCK_ENABLE);
+ SE(SE_BLOCK_COUNT_REG_OFFSET) = 0;
+
+ int res =_se_execute(OP_START, output_buf, 0x10, NULL, 0);
+
+ free(output_buf);
+ return res;
+}
+
+int se_generate_random(u32 ks, void *dst, u32 size)
+{
+ SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
+ SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) |
+ SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
+ SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_MODE(RNG_MODE_NORMAL) | SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY);
+
+ u32 num_blocks = size >> 4;
+ u32 aligned_size = num_blocks << 4;
+ if (num_blocks)
+ {
+ SE(SE_BLOCK_COUNT_REG_OFFSET) = num_blocks - 1;
+ if (!_se_execute(OP_START, dst, aligned_size, NULL, 0))
+ return 0;
+ }
+ if (size > aligned_size)
+ return _se_execute_one_block(OP_START, dst + aligned_size, size - aligned_size, NULL, 0);
+ return 1;
+}
+
+int se_generate_random_key(u32 ks_dst, u32 ks_src)
+{
+ SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
+ SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) |
+ SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
+ SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_MODE(RNG_MODE_NORMAL) | SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY);
+
+ SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst);
+ if (!_se_execute(OP_START, NULL, 0, NULL, 0))
+ return 0;
+ SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst) | 1;
+ if (!_se_execute(OP_START, NULL, 0, NULL, 0))
+ return 0;
+
+ return 1;
+}
+
+int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size)
+{
+ if (enc)
+ {
+ SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
+ SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) |
+ SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_XOR_POS(XOR_TOP) | SE_CRYPTO_INPUT_SEL(INPUT_AHB) |
+ SE_CRYPTO_IV_SEL(IV_ORIGINAL);
+ }
+ else
+ {
+ SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
+ SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVAHB) |
+ SE_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM) | SE_CRYPTO_INPUT_SEL(INPUT_AHB) |
+ SE_CRYPTO_IV_SEL(IV_ORIGINAL);
+ }
+ SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1;
+ return _se_execute(OP_START, dst, dst_size, src, src_size);
+}
+
int se_aes_xts_crypt_sec(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, const void *src, u32 secsize)
{
int res = 0;
u8 *tweak = (u8 *)malloc(0x10);
- u8 *pdst = (u8 *)dst;
- u8 *psrc = (u8 *)src;
+ u8 *temptweak = (u8 *)malloc(0x10);
+ u32 *pdst = (u32 *)dst;
+ u32 *psrc = (u32 *)src;
+ u32 *ptweak = (u32 *)tweak;
//Generate tweak.
for (int i = 0xF; i >= 0; i--)
@@ -336,23 +430,35 @@ int se_aes_xts_crypt_sec(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, const vo
if (!se_aes_crypt_block_ecb(ks1, 1, tweak, tweak))
goto out;
+ memcpy(temptweak, tweak, 0x10);
+
//We are assuming a 0x10-aligned sector size in this implementation.
for (u32 i = 0; i < secsize / 0x10; i++)
{
- for (u32 j = 0; j < 0x10; j++)
- pdst[j] = psrc[j] ^ tweak[j];
- if (!se_aes_crypt_block_ecb(ks2, enc, pdst, pdst))
- goto out;
- for (u32 j = 0; j < 0x10; j++)
- pdst[j] = pdst[j] ^ tweak[j];
+ for (u32 j = 0; j < 4; j++)
+ pdst[j] = psrc[j] ^ ptweak[j];
_gf256_mul_x_le(tweak);
- psrc += 0x10;
- pdst += 0x10;
+ psrc += 4;
+ pdst += 4;
+ }
+
+ se_aes_crypt_ecb(ks2, enc, dst, secsize, dst, secsize);
+
+ pdst = (u32 *)dst;
+
+ memcpy(tweak, temptweak, 0x10);
+ for (u32 i = 0; i < secsize / 0x10; i++)
+ {
+ for (u32 j = 0; j < 4; j++)
+ pdst[j] = pdst[j] ^ ptweak[j];
+ _gf256_mul_x_le(tweak);
+ pdst += 4;
}
res = 1;
out:;
+ free(temptweak);
free(tweak);
return res;
}
@@ -390,17 +496,21 @@ int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size)
se_aes_key_iv_clear(ks);
u32 num_blocks = (src_size + 0xf) >> 4;
- if (num_blocks > 1) {
+ if (num_blocks > 1)
+ {
SE(SE_BLOCK_COUNT_REG_OFFSET) = num_blocks - 2;
if (!_se_execute(OP_START, NULL, 0, src, src_size))
goto out;
SE(SE_CRYPTO_REG_OFFSET) |= SE_CRYPTO_IV_SEL(IV_UPDATED);
}
- if (src_size & 0xf) {
+ if (src_size & 0xf)
+ {
memcpy(last_block, src + (src_size & ~0xf), src_size & 0xf);
last_block[src_size & 0xf] = 0x80;
- } else if (src_size >= 0x10) {
+ }
+ else if (src_size >= 0x10)
+ {
memcpy(last_block, src + src_size - 0x10, 0x10);
}
@@ -447,7 +557,8 @@ int se_calc_sha256(void *dst, const void *src, u32 src_size)
return res;
}
-int se_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *key, u32 key_size) {
+int se_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *key, u32 key_size)
+{
int res = 0;
u8 *secret = (u8 *)malloc(0x40);
u8 *ipad = (u8 *)malloc(0x40 + src_size);
diff --git a/source/sec/se.h b/source/sec/se.h
index 0d517c7..211c279 100644
--- a/source/sec/se.h
+++ b/source/sec/se.h
@@ -25,12 +25,17 @@ void se_rsa_key_clear(u32 ks);
int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size);
void se_key_acc_ctrl(u32 ks, u32 flags);
void se_aes_key_set(u32 ks, const void *key, u32 size);
+void se_aes_iv_set(u32 ks, const void *iv, u32 size);
void se_aes_key_read(u32 ks, void *key, u32 size);
void se_aes_key_clear(u32 ks);
+int se_initialize_rng(u32 ks);
+int se_generate_random(u32 ks, void *dst, u32 size);
+int se_generate_random_key(u32 ks_dst, u32 ks_src);
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input);
int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size);
int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src);
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr);
+int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size);
int se_aes_xts_crypt_sec(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, const void *src, u32 secsize);
int se_aes_xts_crypt(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, const void *src, u32 secsize, u32 num_secs);
int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size);
diff --git a/source/sec/tsec.c b/source/sec/tsec.c
index 5a1f85e..0a8169e 100644
--- a/source/sec/tsec.c
+++ b/source/sec/tsec.c
@@ -18,6 +18,7 @@
#include
+#include "../hos/hos.h"
#include "../sec/tsec.h"
#include "../sec/tsec_t210.h"
#include "../sec/se_t210.h"
@@ -80,7 +81,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
kfuse_wait_ready();
- // Configure Falcon.
+ //Configure Falcon.
TSEC(TSEC_DMACTL) = 0;
TSEC(TSEC_IRQMSET) =
TSEC_IRQMSET_EXT(0xFF) |
@@ -102,7 +103,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
goto out;
}
- // Load firmware or emulate memio environment for newer TSEC fw.
+ //Load firmware or emulate memio environment for newer TSEC fw.
if (kb == KB_FIRMWARE_VERSION_620)
TSEC(TSEC_DMATRFBASE) = (u32)tsec_ctxt->fw >> 8;
else
@@ -126,7 +127,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
{
// Init SMMU translation for TSEC.
pdir = smmu_init_for_tsec();
- smmu_init(tsec_ctxt->secmon_base);
+ smmu_init(0x4002B000);
// Enable SMMU
if (!smmu_is_used())
smmu_enable();
@@ -169,7 +170,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
iram = page_alloc(0x30);
memcpy(iram, tsec_ctxt->pkg1, 0x30000);
// PKG1.1 magic offset.
- pkg11_magic_off = (u32 *)(iram + ((tsec_ctxt->pkg11_off + 0x20) / 4));
+ pkg11_magic_off = (u32 *)(iram + (0x7000 / 4));
smmu_map(pdir, 0x40010000, (u32)iram, 0x30, _READABLE | _WRITABLE | _NONSECURE);
// Exception vectors
@@ -177,7 +178,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
smmu_map(pdir, EXCP_VEC_BASE, (u32)evec, 1, _READABLE | _WRITABLE | _NONSECURE);
}
- // Execute firmware.
+ //Execute firmware.
HOST1X(HOST1X_CH0_SYNC_SYNCPT_160) = 0x34C2E1DA;
TSEC(TSEC_STATUS) = 0;
TSEC(TSEC_BOOTKEYVER) = 1; // HOS uses key version 1.
@@ -254,7 +255,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
goto out_free;
}
- // Fetch result.
+ //Fetch result.
HOST1X(HOST1X_CH0_SYNC_SYNCPT_160) = 0;
u32 buf[4];
buf[0] = SOR1(SOR_NV_PDISP_SOR_DP_HDCP_BKSV_LSB);
@@ -274,7 +275,7 @@ out_free:;
out:;
- // Disable clocks.
+ //Disable clocks.
clock_disable_kfuse();
clock_disable_sor1();
clock_disable_sor0();
diff --git a/source/sec/tsec.h b/source/sec/tsec.h
index 83b1d1f..5d15fb5 100644
--- a/source/sec/tsec.h
+++ b/source/sec/tsec.h
@@ -27,8 +27,6 @@ typedef struct _tsec_ctxt_t
void *fw;
u32 size;
void *pkg1;
- u32 pkg11_off;
- u32 secmon_base;
} tsec_ctxt_t;
typedef struct _tsec_key_data_t
diff --git a/source/soc/hw_init.c b/source/soc/hw_init.c
index f5df093..8867ff2 100644
--- a/source/soc/hw_init.c
+++ b/source/soc/hw_init.c
@@ -26,7 +26,6 @@
#include "pinmux.h"
#include "pmc.h"
#include "t210.h"
-#include "uart.h"
#include "../gfx/di.h"
#include "../mem/mc.h"
#include "../mem/minerva.h"
@@ -102,7 +101,7 @@ void _config_gpios()
pinmux_config_i2c(I2C_1);
pinmux_config_i2c(I2C_5);
- pinmux_config_uart(UART_A);
+ pinmux_config_uart(0);
// Configure volume up/down as inputs.
gpio_config(GPIO_PORT_X, GPIO_PIN_6, GPIO_MODE_GPIO);
@@ -295,11 +294,6 @@ void config_hw()
APB_MISC(APB_MISC_PP_PINMUX_GLOBAL) = 0;
_config_gpios();
-#ifdef DEBUG_UART_PORT
- clock_enable_uart(DEBUG_UART_PORT);
- uart_init(DEBUG_UART_PORT, 115200);
-#endif
-
clock_enable_cl_dvfs();
clock_enable_i2c(I2C_1);
@@ -319,6 +313,7 @@ void config_hw()
sdram_init();
bpmp_mmu_enable();
+ mc_enable_ahb_redirect();
// Clear flags from PMC_SCRATCH0
PMC(APBDEV_PMC_SCRATCH0) &= ~PMC_SCRATCH0_MODE_PAYLOAD;
@@ -334,7 +329,7 @@ void reconfig_hw_workaround(bool extra_reconfig, u32 magic)
// Re-enable clocks to Audio Processing Engine as a workaround to hanging.
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)
{
@@ -357,7 +352,7 @@ void reconfig_hw_workaround(bool extra_reconfig, u32 magic)
if (magic == 0xBAADF00D)
{
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) |= (1 << 22);
- sdmmc_init(&sd_sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_SD_ID, 0);
+ sdmmc_init(&sd_sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, 5, 0);
clock_disable_cl_dvfs();
msleep(200);
diff --git a/source/tegraexplorer/fs/fsactions.c b/source/tegraexplorer/fs/fsactions.c
index 1edc6c2..d12e13a 100644
--- a/source/tegraexplorer/fs/fsactions.c
+++ b/source/tegraexplorer/fs/fsactions.c
@@ -15,7 +15,6 @@ int fsact_copy(const char *locin, const char *locout, u8 options){
FIL in, out;
FILINFO in_info;
u64 sizeRemaining, toCopy;
- UINT temp1, temp2;
u8 *buff, toPrint = options & COPY_MODE_PRINT, toCancel = options & COPY_MODE_CANCEL;
u32 x, y, i = 11;
int res;
@@ -56,19 +55,14 @@ int fsact_copy(const char *locin, const char *locout, u8 options){
while (sizeRemaining > 0){
toCopy = MIN(sizeRemaining, BUFSIZE);
- if ((res = f_read(&in, buff, toCopy, &temp1))){
+ if ((res = f_read(&in, buff, toCopy, NULL))){
gfx_errDisplay("copy", res, 5);
- return 1;
+ break;
}
- if ((res = f_write(&out, buff, toCopy, &temp2))){
+ if ((res = f_write(&out, buff, toCopy, NULL))){
gfx_errDisplay("copy", res, 6);
- return 1;
- }
-
- if (temp1 != temp2){
- gfx_errDisplay("copy", ERR_DISK_WRITE_FAILED, 7);
- return 1;
+ break;
}
sizeRemaining -= toCopy;
@@ -100,13 +94,10 @@ int fsact_copy(const char *locin, const char *locout, u8 options){
f_close(&out);
free(buff);
- if ((res = f_chmod(locout, in_info.fattrib, 0x3A))){
- gfx_errDisplay("copy", res, 8);
- return 1;
- }
+ f_chmod(locout, in_info.fattrib, 0x3A);
f_stat(locin, &in_info); //somehow stops fatfs from being weird
- return 0;
+ return res;
}
int fsact_del_recursive(char *path){