diff --git a/Makefile b/Makefile
index 4cd6f54..dc3c88c 100644
--- a/Makefile
+++ b/Makefile
@@ -29,7 +29,7 @@ OBJS = $(patsubst $(SOURCEDIR)/%.S, $(BUILDDIR)/$(TARGET)/%.o, \
CUSTOMDEFINES := -DIPL_LOAD_ADDR=$(IPL_LOAD_ADDR)
CUSTOMDEFINES += -DLP_VER_MJ=$(LPVERSION_MAJOR) -DLP_VER_MN=$(LPVERSION_MINOR) -DLP_VER_BF=$(LPVERSION_BUGFX)
-ARCH := -march=armv4t -mtune=arm7tdmi -mthumb-interwork
+ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork
CFLAGS = $(ARCH) -O2 -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -std=gnu11 -Wall $(CUSTOMDEFINES)
LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defsym=IPL_LOAD_ADDR=$(IPL_LOAD_ADDR)
diff --git a/source/hos/pkg2.c b/source/hos/pkg2.c
index e745cbc..301fd4e 100644
--- a/source/hos/pkg2.c
+++ b/source/hos/pkg2.c
@@ -139,7 +139,6 @@ int pkg2_decompress_kip(pkg2_kip1_info_t* ki, u32 sectsToDecomp)
memcpy(newKip, &hdr, sizeof(hdr));
newKipSize = dstDataPtr-(unsigned char*)(newKip);
- free(ki->kip1);
ki->kip1 = newKip;
ki->size = newKipSize;
diff --git a/source/incognito/incognito.c b/source/incognito/incognito.c
index ad17d3e..922f712 100644
--- a/source/incognito/incognito.c
+++ b/source/incognito/incognito.c
@@ -109,7 +109,11 @@ bool dump_keys()
tsec_ctxt_t tsec_ctxt;
- emummc_storage_init_mmc(&storage, &sdmmc);
+ if (!emummc_storage_init_mmc(&storage, &sdmmc))
+ {
+ EPRINTF("Unable to init MMC.");
+ return false;
+ }
// Read package1.
u8 *pkg1 = (u8 *)malloc(0x40000);
@@ -119,6 +123,7 @@ bool dump_keys()
if (!pkg1_id)
{
EPRINTF("Unknown pkg1 version.");
+ free(pkg1);
return false;
}
@@ -135,6 +140,7 @@ bool dump_keys()
if (!found_tsec_fw)
{
EPRINTF("Failed to locate TSEC firmware.");
+ free(pkg1);
return false;
}
diff --git a/source/libs/fatfs/diskio.c b/source/libs/fatfs/diskio.c
index e820c6a..75a1c1e 100644
--- a/source/libs/fatfs/diskio.c
+++ b/source/libs/fatfs/diskio.c
@@ -107,7 +107,7 @@ static inline int _emmc_xts(u32 ks1, u32 ks2, u32 enc, u8 *tweak, bool regen_twe
pdst += 0x10;
}
- se_aes_crypt_ecb(ks2, 0, dst, secsize, src, secsize);
+ se_aes_crypt_ecb(ks2, enc, dst, secsize, src, secsize);
pdst = (u8 *)dst;
@@ -150,12 +150,11 @@ DRESULT disk_read (
__attribute__ ((aligned (16))) static u8 tweak[0x10];
__attribute__ ((aligned (16))) static u64 prev_cluster = -1;
__attribute__ ((aligned (16))) static u32 prev_sector = 0;
- u32 tweak_exp = 0;
- bool regen_tweak = true, cache_sector = false;
+ bool needs_cache_sector = false;
if (secindex == 0 || clear_sector_cache) {
- free(sector_cache);
- sector_cache = (sector_cache_t *)malloc(sizeof(sector_cache_t) * MAX_SEC_CACHE_ENTRIES);
+ if (!sector_cache)
+ sector_cache = (sector_cache_t *)malloc(sizeof(sector_cache_t) * MAX_SEC_CACHE_ENTRIES);
clear_sector_cache = false;
secindex = 0;
}
@@ -176,12 +175,14 @@ DRESULT disk_read (
if (s == secindex && s < MAX_SEC_CACHE_ENTRIES) {
sector_cache[s].sector = sector;
sector_cache[s].visit_count++;
- cache_sector = true;
+ needs_cache_sector = true;
secindex++;
}
}
if (nx_emmc_part_read(&storage, system_part, sector, count, buff)) {
+ u32 tweak_exp = 0;
+ bool regen_tweak = true;
if (prev_cluster != sector / 0x20) { // sector in different cluster than last read
prev_cluster = sector / 0x20;
tweak_exp = sector % 0x20;
@@ -194,7 +195,7 @@ DRESULT disk_read (
// fatfs will never pull more than a cluster
_emmc_xts(9, 8, 0, tweak, regen_tweak, tweak_exp, prev_cluster, buff, buff, count * 0x200);
- if (cache_sector) {
+ if (needs_cache_sector) {
memcpy(sector_cache[s].cached_sector, buff, 0x200);
memcpy(sector_cache[s].tweak, tweak, 0x10);
}
diff --git a/source/libs/fatfs/ffconf.h b/source/libs/fatfs/ffconf.h
index 221c909..dc9577e 100644
--- a/source/libs/fatfs/ffconf.h
+++ b/source/libs/fatfs/ffconf.h
@@ -97,7 +97,7 @@
*/
-#define FF_USE_LFN 1
+#define FF_USE_LFN 3
#define FF_MAX_LFN 255
/* The FF_USE_LFN switches the support for LFN (long file name).
/
diff --git a/source/power/max17050.c b/source/power/max17050.c
index aca452e..227f76b 100644
--- a/source/power/max17050.c
+++ b/source/power/max17050.c
@@ -43,9 +43,6 @@
#define MAX17050_VMAX_TOLERANCE 50 /* 50 mV */
-#pragma GCC push_options
-#pragma GCC optimize ("Os")
-
int max17050_get_property(enum MAX17050_reg reg, int *value)
{
u16 data;
@@ -267,5 +264,3 @@ int max17050_fix_configuration()
return 0;
}
-
-#pragma GCC pop_options
\ No newline at end of file
diff --git a/source/soc/clock.c b/source/soc/clock.c
index 73e5fb3..0726748 100644
--- a/source/soc/clock.c
+++ b/source/soc/clock.c
@@ -15,6 +15,7 @@
*/
#include "../soc/clock.h"
+#include "../soc/kfuse.h"
#include "../soc/t210.h"
#include "../utils/util.h"
#include "../storage/sdmmc.h"
@@ -188,6 +189,7 @@ void clock_enable_kfuse()
usleep(10);
CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) &= 0xFFFFFEFF;
usleep(20);
+ kfuse_wait_ready();
}
void clock_disable_kfuse()
diff --git a/source/soc/fuse.h b/source/soc/fuse.h
index 191f18a..0748936 100644
--- a/source/soc/fuse.h
+++ b/source/soc/fuse.h
@@ -37,12 +37,31 @@
#define FUSE_WRITE_ACCESS_SW 0x30
#define FUSE_PWR_GOOD_SW 0x34
#define FUSE_SKU_INFO 0x110
+#define FUSE_CPU_SPEEDO_0_CALIB 0x114
+#define FUSE_CPU_IDDQ_CALIB 0x118
+#define FUSE_OPT_FT_REV 0x128
+#define FUSE_CPU_SPEEDO_1_CALIB 0x12C
+#define FUSE_CPU_SPEEDO_2_CALIB 0x130
+#define FUSE_SOC_SPEEDO_0_CALIB 0x134
+#define FUSE_SOC_SPEEDO_1_CALIB 0x138
+#define FUSE_SOC_SPEEDO_2_CALIB 0x13C
+#define FUSE_SOC_IDDQ_CALIB 0x140
+#define FUSE_OPT_CP_REV 0x190
#define FUSE_FIRST_BOOTROM_PATCH_SIZE 0x19c
#define FUSE_PRIVATE_KEY0 0x1A4
#define FUSE_PRIVATE_KEY1 0x1A8
#define FUSE_PRIVATE_KEY2 0x1AC
#define FUSE_PRIVATE_KEY3 0x1B0
+#define FUSE_PRIVATE_KEY4 0x1B4
#define FUSE_RESERVED_SW 0x1C0
+#define FUSE_OPT_VENDOR_CODE 0x200
+#define FUSE_OPT_FAB_CODE 0x204
+#define FUSE_OPT_LOT_CODE_0 0x208
+#define FUSE_OPT_LOT_CODE_1 0x20C
+#define FUSE_OPT_WAFER_ID 0x210
+#define FUSE_OPT_X_COORDINATE 0x214
+#define FUSE_OPT_Y_COORDINATE 0x218
+#define FUSE_GPU_IDDQ_CALIB 0x228
/*! Fuse commands. */
#define FUSE_READ 0x1
diff --git a/source/soc/kfuse.c b/source/soc/kfuse.c
new file mode 100644
index 0000000..52f188f
--- /dev/null
+++ b/source/soc/kfuse.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2018 naehrwert
+ *
+ * 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 "../soc/kfuse.h"
+#include "../soc/clock.h"
+#include "../soc/t210.h"
+#include "../utils/util.h"
+
+int kfuse_read(u32 *buf)
+{
+ int res = 0;
+
+ clock_enable_kfuse();
+
+ while (!(KFUSE(KFUSE_STATE) & KFUSE_STATE_DONE))
+ ;
+
+ if (!(KFUSE(KFUSE_STATE) & KFUSE_STATE_CRCPASS))
+ goto out;
+
+ KFUSE(KFUSE_KEYADDR) = KFUSE_KEYADDR_AUTOINC;
+ for (int i = 0; i < KFUSE_NUM_WORDS; i++)
+ buf[i] = KFUSE(KFUSE_KEYS);
+
+ res = 1;
+
+out:;
+ clock_disable_kfuse();
+ return res;
+}
+
+int kfuse_wait_ready()
+{
+ // Wait for KFUSE to finish init and verification of data.
+ while (!(KFUSE(KFUSE_STATE) & KFUSE_STATE_DONE))
+ {
+ usleep(500);
+ }
+
+ if (!(KFUSE(KFUSE_STATE) & KFUSE_STATE_CRCPASS))
+ return 0;
+
+ return 1;
+}
diff --git a/source/soc/kfuse.h b/source/soc/kfuse.h
new file mode 100644
index 0000000..3824eb8
--- /dev/null
+++ b/source/soc/kfuse.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2018 naehrwert
+ *
+ * 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 _KFUSE_H_
+#define _KFUSE_H_
+
+#include "../utils/types.h"
+
+#define KFUSE_STATE_SOFTRESET (1 << 31)
+#define KFUSE_STATE_STOP (1 << 25)
+#define KFUSE_STATE_RESTART (1 << 24)
+#define KFUSE_STATE_CRCPASS (1 << 17)
+#define KFUSE_STATE_DONE (1 << 16)
+#define KFUSE_STATE_ERRBLOCK_MASK 0x3F00
+#define KFUSE_STATE_ERRBLOCK_SHIFT 8
+#define KFUSE_STATE_CURBLOCK_MASK 0x3F
+
+#define KFUSE_KEYADDR_AUTOINC (1<<16)
+
+#define KFUSE_STATE 0x80
+#define KFUSE_KEYADDR 0x88
+#define KFUSE_KEYS 0x8C
+
+#define KFUSE_NUM_WORDS 144
+
+int kfuse_read(u32 *buf);
+int kfuse_wait_ready();
+
+#endif
diff --git a/source/storage/sdmmc_driver.c b/source/storage/sdmmc_driver.c
index 9330eac..0c0c2ff 100644
--- a/source/storage/sdmmc_driver.c
+++ b/source/storage/sdmmc_driver.c
@@ -77,7 +77,7 @@ static int _sdmmc_set_voltage(sdmmc_t *sdmmc, u32 power)
{
pwr |= TEGRA_MMC_PWRCTL_SD_BUS_POWER;
sdmmc->regs->pwrcon = pwr;
- }
+ }
return 1;
}
@@ -385,7 +385,7 @@ int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type)
static void _sdmmc_reset(sdmmc_t *sdmmc)
{
- sdmmc->regs->swrst |=
+ sdmmc->regs->swrst |=
TEGRA_MMC_SWRST_SW_RESET_FOR_CMD_LINE | TEGRA_MMC_SWRST_SW_RESET_FOR_DAT_LINE;
_sdmmc_get_clkcon(sdmmc);
u32 timeout = get_tmr_ms() + 2000;
@@ -456,7 +456,7 @@ static int _sdmmc_setup_read_small_block(sdmmc_t *sdmmc)
static int _sdmmc_parse_cmdbuf(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, bool is_data_present)
{
u16 cmdflags = 0;
-
+
switch (cmd->rsp_type)
{
case SDMMC_RSP_TYPE_0:
@@ -722,7 +722,7 @@ static int _sdmmc_check_mask_interrupt(sdmmc_t *sdmmc, u16 *pout, u16 mask)
sdmmc->regs->norintsts = norintsts & mask;
return SDMMC_MASKINT_MASKED;
}
-
+
return SDMMC_MASKINT_NOERROR;
}
@@ -767,7 +767,7 @@ static int _sdmmc_stop_transmission_inner(sdmmc_t *sdmmc, u32 *rsp)
if (!res)
return 0;
-
+
_sdmmc_cache_rsp(sdmmc, rsp, 4, SDMMC_RSP_TYPE_1);
return _sdmmc_wait_prnsts_type1(sdmmc);
@@ -901,7 +901,7 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_
_sdmmc_parse_cmdbuf(sdmmc, cmd, is_data_present);
int res = _sdmmc_wait_request(sdmmc);
- DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", res,
+ DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", res,
sdmmc->regs->rspreg0, sdmmc->regs->rspreg1, sdmmc->regs->rspreg2, sdmmc->regs->rspreg3);
if (res)
{
@@ -943,7 +943,7 @@ static int _sdmmc_config_sdmmc1()
gpio_output_enable(GPIO_PORT_Z, GPIO_PIN_1, GPIO_OUTPUT_DISABLE);
usleep(100);
- // Check if SD card is inserted.
+ // Check if SD card is inserted.
if(!!gpio_read(GPIO_PORT_Z, GPIO_PIN_1))
return 0;
@@ -1055,7 +1055,7 @@ void sdmmc_end(sdmmc_t *sdmmc)
if (!sdmmc->clock_stopped)
{
_sdmmc_sd_clock_disable(sdmmc);
- // Disable SDMMC power.
+ // Disable SDMMC power.
_sdmmc_set_voltage(sdmmc, SDMMC_POWER_OFF);
// Disable SD card power.
@@ -1134,7 +1134,7 @@ int sdmmc_enable_low_voltage(sdmmc_t *sdmmc)
_sdmmc_set_voltage(sdmmc, SDMMC_POWER_1_8);
_sdmmc_get_clkcon(sdmmc);
msleep(5);
-
+
if (sdmmc->regs->hostctl2 & SDHCI_CTRL_VDD_180)
{
sdmmc->regs->clkcon |= TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE;