Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4f2bbbf101 | ||
|
|
b677d6cad3 | ||
|
|
b3f8961e45 | ||
|
|
2f37811aba | ||
|
|
5cd596e53c | ||
|
|
4ae42c3a9d | ||
|
|
e105634b0d | ||
|
|
4781dc2ab4 | ||
|
|
e779e53406 | ||
|
|
9f5b97620a | ||
|
|
98d715243a | ||
|
|
e809745120 | ||
|
|
0d9aebda7b | ||
|
|
5ed875ce90 | ||
|
|
30d3c76655 | ||
|
|
949a034500 | ||
|
|
b2893d7fb6 | ||
|
|
9a3fdd944e | ||
|
|
8b8f3c564c | ||
|
|
cd1bb96241 | ||
|
|
8b59ddf3a8 | ||
|
|
09bfed9146 | ||
|
|
cbe75d7769 | ||
|
|
dad380344f | ||
|
|
71b0975730 |
10
Makefile
10
Makefile
@@ -6,7 +6,7 @@ include $(DEVKITARM)/base_rules
|
||||
|
||||
TARGET := hekate
|
||||
BLVERSION_MAJOR := 4
|
||||
BLVERSION_MINOR := 5
|
||||
BLVERSION_MINOR := 6
|
||||
BUILD := build
|
||||
OUTPUT := output
|
||||
SOURCEDIR = bootloader
|
||||
@@ -53,6 +53,7 @@ OBJS = $(addprefix $(BUILD)/$(TARGET)/, \
|
||||
ini.o \
|
||||
ianos.o \
|
||||
smmu.o \
|
||||
max77620-rtc.o \
|
||||
)
|
||||
|
||||
OBJS += $(addprefix $(BUILD)/$(TARGET)/, \
|
||||
@@ -61,9 +62,12 @@ OBJS += $(addprefix $(BUILD)/$(TARGET)/, \
|
||||
elfload.o elfreloc_arm.o \
|
||||
)
|
||||
|
||||
CUSTOMDEFINES := -DBLVERSIONMJ=$(BLVERSION_MAJOR) -DBLVERSIONMN=$(BLVERSION_MINOR) -DMENU_LOGO_ENABLE
|
||||
#CUSTOMDEFINES += -DDEBUG
|
||||
# 0: UART_A, 1: UART_B.
|
||||
#CUSTOMDEFINES += -DDEBUG_UART_PORT=0
|
||||
|
||||
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork
|
||||
CUSTOMDEFINES := -DBLVERSIONMJ=$(BLVERSION_MAJOR) -DBLVERSIONMN=$(BLVERSION_MINOR)
|
||||
CUSTOMDEFINES += -DMENU_LOGO_ENABLE #-DDEBUG
|
||||
CFLAGS = $(ARCH) -O2 -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -std=gnu11 -Wall $(CUSTOMDEFINES)
|
||||
LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ void set_default_configuration()
|
||||
h_cfg.se_keygen_done = 0;
|
||||
h_cfg.sbar_time_keeping = 0;
|
||||
h_cfg.backlight = 100;
|
||||
h_cfg.autohosoff = 1;
|
||||
h_cfg.autohosoff = 0;
|
||||
h_cfg.errors = 0;
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ int create_config_entry()
|
||||
return 0;
|
||||
}
|
||||
|
||||
void _config_autoboot_list()
|
||||
static void _config_autoboot_list(void *ent)
|
||||
{
|
||||
gfx_clear_grey(&gfx_ctxt, 0x1B);
|
||||
gfx_con_setpos(&gfx_con, 0, 0);
|
||||
@@ -231,6 +231,9 @@ void _config_autoboot_list()
|
||||
else
|
||||
EPRINTF("\nConfiguration saving failed!");
|
||||
gfx_puts(&gfx_con, "\nPress any key...");
|
||||
|
||||
ment_t *tmp = (ment_t *)ent;
|
||||
tmp->data = NULL;
|
||||
}
|
||||
else
|
||||
goto out2;
|
||||
@@ -251,9 +254,6 @@ out2:;
|
||||
ini_free(&ini_sections);
|
||||
|
||||
sd_unmount();
|
||||
|
||||
if (temp_autoboot == NULL)
|
||||
return;
|
||||
}
|
||||
|
||||
void config_autoboot()
|
||||
@@ -291,13 +291,13 @@ void config_autoboot()
|
||||
ments[2].caption = " Disable";
|
||||
ments[2].data = &boot_values[0];
|
||||
|
||||
ments[3].type = MENT_HANDLER;
|
||||
ments[3].type = MENT_HDLR_RE;
|
||||
if (h_cfg.autoboot_list)
|
||||
ments[3].caption = "*More configs...";
|
||||
else
|
||||
ments[3].caption = " More configs...";
|
||||
ments[3].handler = _config_autoboot_list;
|
||||
ments[3].data = NULL;
|
||||
ments[3].data = (void *)0xCAFE;
|
||||
|
||||
ments[4].type = MENT_CHGLINE;
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir)
|
||||
lblen = strlen(lbuf);
|
||||
|
||||
// Remove trailing newline.
|
||||
if (lbuf[lblen - 1] == '\n')
|
||||
if (lbuf[lblen - 1] == '\n' || lbuf[lblen - 1] == '\r')
|
||||
lbuf[lblen - 1] = 0;
|
||||
|
||||
if (lblen > 2 && lbuf[0] == '[') // Create new section.
|
||||
@@ -96,7 +96,7 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir)
|
||||
}
|
||||
|
||||
u32 i;
|
||||
for (i = 0; i < lblen && lbuf[i] != '\n' && lbuf[i] != ']'; i++)
|
||||
for (i = 0; i < lblen && lbuf[i] != ']' && lbuf[i] != '\n' && lbuf[i] != '\r'; i++)
|
||||
;
|
||||
lbuf[i] = 0;
|
||||
|
||||
@@ -114,7 +114,7 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir)
|
||||
}
|
||||
|
||||
u32 i;
|
||||
for (i = 0; i < lblen && lbuf[i] != '\n' && lbuf[i] != '}'; i++)
|
||||
for (i = 0; i < lblen && lbuf[i] != '}' && lbuf[i] != '\n' && lbuf[i] != '\r'; i++)
|
||||
;
|
||||
lbuf[i] = 0;
|
||||
|
||||
@@ -132,7 +132,7 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir)
|
||||
}
|
||||
|
||||
u32 i;
|
||||
for (i = 0; i < lblen && lbuf[i] != '\n'; i++)
|
||||
for (i = 0; i < lblen && lbuf[i] != '\n' && lbuf[i] != '\r'; i++)
|
||||
;
|
||||
lbuf[i] = 0;
|
||||
|
||||
@@ -155,7 +155,7 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir)
|
||||
else if (csec && csec->type == INI_CHOICE) //Extract key/value.
|
||||
{
|
||||
u32 i;
|
||||
for (i = 0; i < lblen && lbuf[i] != '\n' && lbuf[i] != '='; i++)
|
||||
for (i = 0; i < lblen && lbuf[i] != '=' && lbuf[i] != '\n' && lbuf[i] != '\r'; i++)
|
||||
;
|
||||
lbuf[i] = 0;
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ extern void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_st
|
||||
#define WPRINTF(text) gfx_printf(&gfx_con, "%k"text"%k\n", 0xFFFFDD00, 0xFFCCCCCC)
|
||||
#define WPRINTFARGS(text, args...) gfx_printf(&gfx_con, "%k"text"%k\n", 0xFFFFDD00, args, 0xFFCCCCCC)
|
||||
|
||||
int _dump_emmc_verify(sdmmc_storage_t *storage, u32 lba_curr, char *outFilename, emmc_part_t *part)
|
||||
static int _dump_emmc_verify(sdmmc_storage_t *storage, u32 lba_curr, char *outFilename, emmc_part_t *part)
|
||||
{
|
||||
FIL fp;
|
||||
u32 btn = 0;
|
||||
@@ -165,7 +165,7 @@ int _dump_emmc_verify(sdmmc_storage_t *storage, u32 lba_curr, char *outFilename,
|
||||
}
|
||||
}
|
||||
|
||||
int _dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
|
||||
static int _dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
|
||||
{
|
||||
static const u32 FAT32_FILESIZE_LIMIT = 0xFFFFFFFF;
|
||||
static const u32 SECTORS_TO_MIB_COEFF = 11;
|
||||
@@ -635,7 +635,7 @@ void dump_emmc_user() { _dump_emmc_selected(PART_USER); }
|
||||
void dump_emmc_boot() { _dump_emmc_selected(PART_BOOT); }
|
||||
void dump_emmc_rawnand() { _dump_emmc_selected(PART_RAW); }
|
||||
|
||||
int _restore_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
|
||||
static int _restore_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
|
||||
{
|
||||
static const u32 SECTORS_TO_MIB_COEFF = 11;
|
||||
|
||||
@@ -652,7 +652,10 @@ int _restore_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *par
|
||||
res = f_open(&fp, outFilename, FA_READ);
|
||||
if (res)
|
||||
{
|
||||
WPRINTFARGS("Error (%d) while opening backup. Continuing...\n", res);
|
||||
if (res != FR_NO_FILE)
|
||||
EPRINTFARGS("Error (%d) while opening backup. Continuing...\n", res);
|
||||
else
|
||||
WPRINTFARGS("Error (%d) file not found. Continuing...\n", res);
|
||||
gfx_con.fntsz = 16;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -54,6 +54,9 @@ extern void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_st
|
||||
#define WPRINTF(text) gfx_printf(&gfx_con, "%k"text"%k\n", 0xFFFFDD00, 0xFFCCCCCC)
|
||||
#define WPRINTFARGS(text, args...) gfx_printf(&gfx_con, "%k"text"%k\n", 0xFFFFDD00, args, 0xFFCCCCCC)
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("Os")
|
||||
|
||||
void print_fuseinfo()
|
||||
{
|
||||
gfx_clear_partial_grey(&gfx_ctxt, 0x1B, 0, 1256);
|
||||
@@ -77,7 +80,7 @@ void print_fuseinfo()
|
||||
break;
|
||||
}
|
||||
gfx_printf(&gfx_con, "Sdram ID: %d\n", (fuse_read_odm(4) >> 3) & 0x1F);
|
||||
gfx_printf(&gfx_con, "Burnt fuses: %d\n", burntFuses);
|
||||
gfx_printf(&gfx_con, "Burnt fuses: %d / 64\n", burntFuses);
|
||||
gfx_printf(&gfx_con, "Secure key: %08X%08X%08X%08X\n\n\n",
|
||||
byte_swap_32(FUSE(FUSE_PRIVATE_KEY0)), byte_swap_32(FUSE(FUSE_PRIVATE_KEY1)),
|
||||
byte_swap_32(FUSE(FUSE_PRIVATE_KEY2)), byte_swap_32(FUSE(FUSE_PRIVATE_KEY3)));
|
||||
@@ -637,11 +640,11 @@ void _ipatch_process(u32 offset, u32 value)
|
||||
u8 lo = value & 0xff;
|
||||
switch (value >> 8)
|
||||
{
|
||||
case 0xdf:
|
||||
gfx_printf(&gfx_con, " svc #0x%02x", lo);
|
||||
break;
|
||||
case 0x20:
|
||||
gfx_printf(&gfx_con, " movs r0, #0x%02x", lo);
|
||||
gfx_printf(&gfx_con, " MOVS R0, #0x%02X", lo);
|
||||
break;
|
||||
case 0xDF:
|
||||
gfx_printf(&gfx_con, " SVC #0x%02X", lo);
|
||||
break;
|
||||
}
|
||||
gfx_puts(&gfx_con, "\n");
|
||||
@@ -657,7 +660,7 @@ void bootrom_ipatches_info()
|
||||
u32 res = fuse_read_ipatch(_ipatch_process);
|
||||
if (res != 0)
|
||||
EPRINTFARGS("Failed to read ipatches. Error: %d", res);
|
||||
|
||||
|
||||
gfx_puts(&gfx_con, "\nPress POWER to dump them to SD Card.\nPress VOL to go to the menu.\n");
|
||||
|
||||
u32 btn = btn_wait();
|
||||
@@ -688,15 +691,15 @@ void bootrom_ipatches_info()
|
||||
if (!sd_save_to_file((u8 *)BOOTROM_BASE, BOOTROM_SIZE, path))
|
||||
gfx_puts(&gfx_con, "\nbootrom_patched.bin saved!\n");
|
||||
|
||||
u8 ipatch_backup[13];
|
||||
memcpy(ipatch_backup, (void *) IPATCH_BASE, 13);
|
||||
memset((void*)IPATCH_BASE, 0, 13);
|
||||
u32 ipatch_backup[14];
|
||||
memcpy(ipatch_backup, (void *)IPATCH_BASE, sizeof(ipatch_backup));
|
||||
memset((void*)IPATCH_BASE, 0, sizeof(ipatch_backup));
|
||||
|
||||
emmcsn_path_impl(path, "/dumps", "bootrom_unpatched.bin", NULL);
|
||||
if (!sd_save_to_file((u8 *)BOOTROM_BASE, BOOTROM_SIZE, path))
|
||||
gfx_puts(&gfx_con, "\nbootrom_unpatched.bin saved!\n");
|
||||
|
||||
memcpy((void*)IPATCH_BASE, ipatch_backup, 13);
|
||||
memcpy((void*)IPATCH_BASE, ipatch_backup, sizeof(ipatch_backup));
|
||||
|
||||
sd_unmount();
|
||||
}
|
||||
@@ -704,3 +707,6 @@ void bootrom_ipatches_info()
|
||||
btn_wait();
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GCC pop_options
|
||||
|
||||
|
||||
@@ -322,6 +322,7 @@ void menu_autorcm()
|
||||
ments[4].handler = _disable_autorcm;
|
||||
}
|
||||
ments[4].type = MENT_HDLR_RE;
|
||||
ments[4].data = NULL;
|
||||
|
||||
memset(&ments[5], 0, sizeof(ment_t));
|
||||
menu_t menu = {ments, "This corrupts your BOOT0!", 0, 0};
|
||||
@@ -329,7 +330,7 @@ void menu_autorcm()
|
||||
tui_do_menu(&gfx_con, &menu);
|
||||
}
|
||||
|
||||
int _fix_attributes(char *path, u32 *total, u32 is_root, u32 check_first_run)
|
||||
int _fix_attributes(char *path, u32 *total, u32 hos_folder, u32 check_first_run)
|
||||
{
|
||||
FRESULT res;
|
||||
DIR dir;
|
||||
@@ -369,8 +370,8 @@ int _fix_attributes(char *path, u32 *total, u32 is_root, u32 check_first_run)
|
||||
if (res != FR_OK || fno.fname[0] == 0)
|
||||
break;
|
||||
|
||||
// Skip official Nintendo dir.
|
||||
if (is_root && !strcmp(fno.fname, "Nintendo"))
|
||||
// Skip official Nintendo dir if started from root.
|
||||
if (!hos_folder && !strcmp(fno.fname, "Nintendo"))
|
||||
continue;
|
||||
|
||||
// Set new directory or file.
|
||||
@@ -380,15 +381,21 @@ int _fix_attributes(char *path, u32 *total, u32 is_root, u32 check_first_run)
|
||||
// Check if archive bit is set.
|
||||
if (fno.fattrib & AM_ARC)
|
||||
{
|
||||
*(u32 *)total = *(u32 *)total + 1;
|
||||
*total = *total + 1;
|
||||
f_chmod(path, 0, AM_ARC);
|
||||
}
|
||||
|
||||
// Is it a directory?
|
||||
if (fno.fattrib & AM_DIR)
|
||||
{
|
||||
// Set archive bit to NCA folders.
|
||||
if (hos_folder && !strcmp(fno.fname + strlen(fno.fname) - 4, ".nca"))
|
||||
{
|
||||
*total = *total + 1;
|
||||
f_chmod(path, AM_ARC, AM_ARC);
|
||||
}
|
||||
// Enter the directory.
|
||||
res = _fix_attributes(path, total, 0, 0);
|
||||
res = _fix_attributes(path, total, hos_folder, 0);
|
||||
if (res != FR_OK)
|
||||
break;
|
||||
}
|
||||
@@ -405,7 +412,7 @@ void _fix_sd_attr(u32 type)
|
||||
gfx_con_setpos(&gfx_con, 0, 0);
|
||||
|
||||
char path[256];
|
||||
char label[14];
|
||||
char label[16];
|
||||
|
||||
u32 total = 0;
|
||||
if (sd_mount())
|
||||
@@ -418,21 +425,21 @@ void _fix_sd_attr(u32 type)
|
||||
break;
|
||||
case 1:
|
||||
default:
|
||||
memcpy(path, "/switch", 8);
|
||||
memcpy(label, "switch folder", 14);
|
||||
memcpy(path, "/Nintendo", 10);
|
||||
memcpy(label, "Nintendo folder", 16);
|
||||
break;
|
||||
}
|
||||
|
||||
gfx_printf(&gfx_con, "Traversing all %s files!\nThis may take some time, please wait...\n\n", label);
|
||||
_fix_attributes(path, &total, !type, type);
|
||||
_fix_attributes(path, &total, type, type);
|
||||
gfx_printf(&gfx_con, "%kTotal archive bits cleared: %d!%k\n\nDone! Press any key...", 0xFF96FF00, total, 0xFFCCCCCC);
|
||||
sd_unmount();
|
||||
}
|
||||
btn_wait();
|
||||
}
|
||||
|
||||
void fix_sd_all_attr() { _fix_sd_attr(0); }
|
||||
void fix_sd_switch_attr() { _fix_sd_attr(1); }
|
||||
void fix_sd_all_attr() { _fix_sd_attr(0); }
|
||||
void fix_sd_nin_attr() { _fix_sd_attr(1); }
|
||||
|
||||
void fix_battery_desync()
|
||||
{
|
||||
@@ -546,8 +553,10 @@ void fix_battery_desync()
|
||||
}*/
|
||||
|
||||
/*
|
||||
//#include "../modules/hekate_libsys_minerva/mtc.h"
|
||||
//mtc_config_t mtc_cfg;
|
||||
#include "../modules/hekate_libsys_minerva/mtc.h"
|
||||
#include "../ianos/ianos.h"
|
||||
#include "../soc/fuse.h"
|
||||
mtc_config_t mtc_cfg;
|
||||
|
||||
void minerva()
|
||||
{
|
||||
@@ -575,6 +584,9 @@ void minerva()
|
||||
break;
|
||||
}
|
||||
|
||||
// Change DRAM voltage.
|
||||
//i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_SD1, 42); //40 = (1000 * 1100 - 600000) / 12500 -> 1.1V
|
||||
|
||||
mtc_cfg.rate_from = mtc_cfg.mtc_table[curr_ram_idx].rate_khz;
|
||||
mtc_cfg.rate_to = 800000;
|
||||
mtc_cfg.train_mode = OP_TRAIN_SWITCH;
|
||||
@@ -583,7 +595,7 @@ void minerva()
|
||||
|
||||
// Thefollowing frequency needs periodic training every 100ms.
|
||||
//msleep(200);
|
||||
|
||||
|
||||
//mtc_cfg.rate_to = 1600000;
|
||||
//gfx_printf(&gfx_con, "Training and switching %7d -> %7d\n\n", mtc_cfg.current_emc_table->rate_khz, 1600000);
|
||||
//ianos_loader(false, "bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)&mtc_cfg);
|
||||
|
||||
@@ -20,8 +20,9 @@
|
||||
|
||||
void dump_packages12();
|
||||
void fix_sd_all_attr();
|
||||
void fix_sd_switch_attr();
|
||||
void fix_sd_nin_attr();
|
||||
void fix_battery_desync();
|
||||
void menu_autorcm();
|
||||
//void minerva();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -238,6 +238,10 @@
|
||||
#define DC_WINBUF_ADDR_H_OFFSET 0x806
|
||||
#define DC_WINBUF_ADDR_V_OFFSET 0x808
|
||||
#define DC_WINBUF_SURFACE_KIND 0x80B
|
||||
#define PITCH (0 << 0)
|
||||
#define TILED (1 << 0)
|
||||
#define BLOCK (2 << 0)
|
||||
#define BLOCK_HEIGHT(x) (((x) & 0x7) << 4)
|
||||
|
||||
/*! Display serial interface registers. */
|
||||
#define _DSIREG(reg) ((reg) * 4)
|
||||
|
||||
@@ -15,13 +15,12 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "di.h"
|
||||
#include "tui.h"
|
||||
#include "../utils/btn.h"
|
||||
#include "../config/config.h"
|
||||
#include "../power/max17050.h"
|
||||
#include "../utils/util.h"
|
||||
#include "../config/config.h"
|
||||
#include "di.h"
|
||||
|
||||
#ifdef MENU_LOGO_ENABLE
|
||||
extern u8 *Kc_MENU_LOGO;
|
||||
@@ -206,8 +205,10 @@ void *tui_do_menu(gfx_con_t *con, menu_t *menu)
|
||||
return NULL;
|
||||
break;
|
||||
case MENT_HDLR_RE:
|
||||
ent->handler(ent->data);
|
||||
return NULL;
|
||||
ent->handler(ent);
|
||||
if (!ent->data)
|
||||
return NULL;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ static void _se_lock(bool lock_se)
|
||||
SE(SE_SECURITY_0) &= 0xFFFFFFFB; // Make access lock regs secure only.
|
||||
}
|
||||
|
||||
memset((void *)IPATCH_BASE, 0, 13);
|
||||
memset((void *)IPATCH_BASE, 0, 14 * sizeof(u32));
|
||||
SB(SB_CSR) = 0x10; // Protected IROM enable.
|
||||
|
||||
// This is useful for documenting the bits in the SE config registers, so we can keep it around.
|
||||
@@ -184,8 +184,12 @@ int keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
memset(tmp, 0x00, 0x20);
|
||||
retries++;
|
||||
|
||||
if (retries > 3)
|
||||
// We rely on racing conditions, make sure we cover even the unluckiest cases.
|
||||
if (retries > 15)
|
||||
{
|
||||
gfx_printf(&gfx_con, "%k\nFailed to get TSEC keys. Please try again.%k\n\n", 0xFFFF0000, 0xFFCCCCCC);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (kb >= KB_FIRMWARE_VERSION_620)
|
||||
@@ -281,10 +285,10 @@ static int _read_emmc_pkg1(launch_ctxt_t *ctxt)
|
||||
ctxt->pkg1_id = pkg1_identify(ctxt->pkg1);
|
||||
if (!ctxt->pkg1_id)
|
||||
{
|
||||
gfx_printf(&gfx_con, "%kUnknown package1,\nVersion (= '%s').%k\n", 0xFFFF0000, (char *)ctxt->pkg1 + 0x10, 0xFFCCCCCC);
|
||||
gfx_printf(&gfx_con, "%kUnknown pkg1,\nVersion (= '%s').%k\n", 0xFFFF0000, (char *)ctxt->pkg1 + 0x10, 0xFFCCCCCC);
|
||||
goto out;
|
||||
}
|
||||
gfx_printf(&gfx_con, "Identified package1 ('%s'),\nKeyblob version %d\n\n", (char *)(ctxt->pkg1 + 0x10), ctxt->pkg1_id->kb);
|
||||
gfx_printf(&gfx_con, "Identified pkg1 ('%s'),\nKeyblob version %d\n\n", (char *)(ctxt->pkg1 + 0x10), ctxt->pkg1_id->kb);
|
||||
|
||||
// Read the correct keyblob.
|
||||
ctxt->keyblob = (u8 *)calloc(NX_EMMC_BLOCKSIZE, 1);
|
||||
@@ -376,7 +380,7 @@ int hos_launch(ini_sec_t *cfg)
|
||||
if (!_read_emmc_pkg1(&ctxt))
|
||||
return 0;
|
||||
|
||||
gfx_printf(&gfx_con, "Loaded package1 and keyblob\n");
|
||||
gfx_printf(&gfx_con, "Loaded pkg1 and keyblob\n");
|
||||
|
||||
// Generate keys.
|
||||
if (!h_cfg.se_keygen_done || ctxt.pkg1_id->kb >= KB_FIRMWARE_VERSION_620)
|
||||
@@ -402,12 +406,20 @@ int hos_launch(ini_sec_t *cfg)
|
||||
|
||||
pkg1_unpack((void *)ctxt.pkg1_id->warmboot_base, (void *)ctxt.pkg1_id->secmon_base, NULL, ctxt.pkg1_id, ctxt.pkg1);
|
||||
|
||||
gfx_printf(&gfx_con, "Decrypted and unpacked package1\n");
|
||||
gfx_printf(&gfx_con, "Decrypted and unpacked pkg1\n");
|
||||
}
|
||||
|
||||
// Replace 'warmboot.bin' if requested.
|
||||
if (ctxt.warmboot)
|
||||
memcpy((void *)ctxt.pkg1_id->warmboot_base, ctxt.warmboot, ctxt.warmboot_size);
|
||||
else
|
||||
{
|
||||
// Else we patch it to allow downgrading.
|
||||
patch_t *warmboot_patchset = ctxt.pkg1_id->warmboot_patchset;
|
||||
gfx_printf(&gfx_con, "%kPatching Warmboot%k\n", 0xFFFFBA00, 0xFFCCCCCC);
|
||||
for (u32 i = 0; warmboot_patchset[i].off != 0xFFFFFFFF; i++)
|
||||
*(vu32 *)(ctxt.pkg1_id->warmboot_base + warmboot_patchset[i].off) = warmboot_patchset[i].val;
|
||||
}
|
||||
// Set warmboot address in PMC if required.
|
||||
if (ctxt.pkg1_id->set_warmboot)
|
||||
PMC(APBDEV_PMC_SCRATCH1) = ctxt.pkg1_id->warmboot_base;
|
||||
@@ -431,10 +443,15 @@ int hos_launch(ini_sec_t *cfg)
|
||||
if (!bootConfigBuf)
|
||||
return 0;
|
||||
|
||||
gfx_printf(&gfx_con, "Read package2\n");
|
||||
gfx_printf(&gfx_con, "Read pkg2\n");
|
||||
|
||||
// Decrypt package2 and parse KIP1 blobs in INI1 section.
|
||||
pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(ctxt.pkg2);
|
||||
if (!pkg2_hdr)
|
||||
{
|
||||
gfx_printf(&gfx_con, "Pkg2 decryption failed!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
LIST_INIT(kip1_info);
|
||||
pkg2_parse_kips(&kip1_info, pkg2_hdr);
|
||||
@@ -470,6 +487,8 @@ int hos_launch(ini_sec_t *cfg)
|
||||
for (u32 j = 0; j < kernel_patchset[i].val; j++)
|
||||
*(vu32 *)(ctxt.kernel + kernel_patchset[i].off + (j << 2)) = temp[j];
|
||||
}
|
||||
else if (kernel_patchset[i].id < SVC_VERIFY_DS)
|
||||
*(vu32 *)(ctxt.kernel + kernel_patchset[i].off) = kernel_patchset[i].val;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -486,13 +505,15 @@ int hos_launch(ini_sec_t *cfg)
|
||||
{
|
||||
gfx_printf(&gfx_con, "%kREQUESTED PATCH '%s' NOT APPLIED!%k\n", 0xFFFF0000, unappliedPatch, 0xFFCCCCCC);
|
||||
sd_unmount(); // Just exiting is not enough until pkg2_patch_kips stops modifying the string passed into it.
|
||||
while(1) {} // MUST stop here, because if user requests 'nogc' but it's not applied, their GC controller gets updated!
|
||||
|
||||
_free_launch_components(&ctxt);
|
||||
return 0; // MUST stop here, because if user requests 'nogc' but it's not applied, their GC controller gets updated!
|
||||
}
|
||||
|
||||
// Rebuild and encrypt package2.
|
||||
pkg2_build_encrypt((void *)0xA9800000, ctxt.kernel, ctxt.kernel_size, &kip1_info);
|
||||
|
||||
gfx_printf(&gfx_con, "Rebuilt and loaded package2\n");
|
||||
gfx_printf(&gfx_con, "Rebuilt and loaded pkg2\n");
|
||||
|
||||
// Unmount SD card.
|
||||
sd_unmount();
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
#define KB_FIRMWARE_VERSION_620 6
|
||||
#define KB_FIRMWARE_VERSION_MAX KB_FIRMWARE_VERSION_620
|
||||
|
||||
#define HOS_PKG11_MAGIC 0x31314B50
|
||||
|
||||
typedef struct _launch_ctxt_t
|
||||
{
|
||||
void *keyblob;
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
#include "../utils/aarch64_util.h"
|
||||
#include "../sec/se.h"
|
||||
|
||||
#define _NOPv7() 0xE320F000
|
||||
|
||||
#define SM_100_ADR 0x4002B020
|
||||
PATCHSET_DEF(_secmon_1_patchset,
|
||||
// Patch the relocator to be able to run from SM_100_ADR.
|
||||
@@ -66,10 +68,18 @@ PATCHSET_DEF(_secmon_5_patchset,
|
||||
|
||||
PATCHSET_DEF(_secmon_6_patchset,
|
||||
// Patch package2 decryption and signature/hash checks.
|
||||
{ 0xDC8 + 0x820, _NOP() }, //package2 structure.
|
||||
{ 0xDC8 + 0x82C, _NOP() }, //Version.
|
||||
{ 0xDC8 + 0xE90, _NOP() }, //Header signature.
|
||||
{ 0xDC8 + 0x112C, _NOP() } //Sections SHA2.
|
||||
{ 0xDC8 + 0x820, _NOP() }, //package2 structure.
|
||||
{ 0xDC8 + 0x82C, _NOP() }, //Version.
|
||||
{ 0xDC8 + 0xE90, _NOP() }, //Header signature.
|
||||
{ 0xDC8 + 0x112C, _NOP() }, //Sections SHA2.
|
||||
// Fix sleep mode for debug.
|
||||
{ 0x1A68 + 0x3854, 0x94000E45 }, //gpio_config_for_uart.
|
||||
{ 0x1A68 + 0x3858, 0x97FFFC0F }, //clkrst_reboot_uarta.
|
||||
{ 0x1A68 + 0x385C, 0x52A00021 }, //MOV W1, #0x10000 ; baudrate.
|
||||
{ 0x1A68 + 0x3860, 0x2A1F03E0 }, //MOV W0, WZR ; uart_port -> A.
|
||||
{ 0x1A68 + 0x3864, 0x72984001 }, //MOVK W1, #0xC200 ; baudrate.
|
||||
{ 0x1A68 + 0x3868, 0x94000C8C }, //uart_configure.
|
||||
{ 0x1A68 + 0x3A6C, _NOP() } // warmboot UARTA cfg.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_secmon_620_patchset,
|
||||
@@ -77,7 +87,48 @@ PATCHSET_DEF(_secmon_620_patchset,
|
||||
{ 0xDC8 + 0x604, _NOP() }, //package2 structure.
|
||||
{ 0xDC8 + 0x610, _NOP() }, //Version.
|
||||
{ 0xDC8 + 0xC74, _NOP() }, //Header signature.
|
||||
{ 0xDC8 + 0xF10, _NOP() } //Sections SHA2.
|
||||
{ 0xDC8 + 0xF10, _NOP() }, //Sections SHA2.
|
||||
// Fix sleep mode for debug.
|
||||
{ 0x2AC8 + 0x3854, 0x94000F42 }, //gpio_config_for_uart.
|
||||
{ 0x2AC8 + 0x3858, 0x97FFFC0F }, //clkrst_reboot_uarta.
|
||||
{ 0x2AC8 + 0x385C, 0x52A00021 }, //MOV W1, #0x10000 ; baudrate.
|
||||
{ 0x2AC8 + 0x3860, 0x2A1F03E0 }, //MOV W0, WZR ; uart_port -> A.
|
||||
{ 0x2AC8 + 0x3864, 0x72984001 }, //MOVK W1, #0xC200 ; baudrate.
|
||||
{ 0x2AC8 + 0x3868, 0x94000D89 }, //uart_configure.
|
||||
{ 0x2AC8 + 0x3A6C, _NOP() } // warmboot UARTA cfg.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_warmboot_1_patchset,
|
||||
{ 0x4DC, _NOPv7() } // Fuse check.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_warmboot_2_patchset,
|
||||
{ 0x4DC, _NOPv7() } // Fuse check.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_warmboot_3_patchset,
|
||||
{ 0x4DC, _NOPv7() }, // Fuse check.
|
||||
{ 0x4F0, _NOPv7() } // Segment id check.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_warmboot_4_patchset,
|
||||
{ 0x544, _NOPv7() }, // Fuse check.
|
||||
{ 0x558, _NOPv7() } // Segment id check.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_warmboot_5_patchset,
|
||||
{ 0x544, _NOPv7() }, // Fuse check.
|
||||
{ 0x558, _NOPv7() } // Segment id check.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_warmboot_6_patchset,
|
||||
{ 0x544, _NOPv7() }, // Fuse check.
|
||||
{ 0x558, _NOPv7() } // Segment id check.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_warmboot_620_patchset,
|
||||
{ 0x544, _NOPv7() }, // Fuse check.
|
||||
{ 0x558, _NOPv7() } // Segment id check.
|
||||
);
|
||||
|
||||
/*
|
||||
@@ -94,14 +145,14 @@ PATCHSET_DEF(_secmon_620_patchset,
|
||||
*/
|
||||
|
||||
static const pkg1_id_t _pkg1_ids[] = {
|
||||
{ "20161121183008", 0, 0x1900, 0x3FE0, { 2, 1, 0 }, SM_100_ADR, 0x8000D000, true, _secmon_1_patchset }, //1.0.0 (Patched relocator)
|
||||
{ "20170210155124", 0, 0x1900, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, true, _secmon_2_patchset }, //2.0.0 - 2.3.0
|
||||
{ "20170519101410", 1, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, true, _secmon_3_patchset }, //3.0.0
|
||||
{ "20170710161758", 2, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, true, _secmon_3_patchset }, //3.0.1 - 3.0.2
|
||||
{ "20170921172629", 3, 0x1800, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003B000, false, _secmon_4_patchset }, //4.0.0 - 4.1.0
|
||||
{ "20180220163747", 4, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003B000, false, _secmon_5_patchset }, //5.0.0 - 5.1.0
|
||||
{ "20180802162753", 5, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003D800, false, _secmon_6_patchset }, //6.0.0 - 6.1.0
|
||||
{ "20181107105733", 6, 0x0E00, 0x6FE0, { 1, 2, 0 }, 0x4002B000, 0x4003D800, false, _secmon_620_patchset }, //6.2.0
|
||||
{ "20161121183008", 0, 0x1900, 0x3FE0, { 2, 1, 0 }, SM_100_ADR, 0x8000D000, true, _secmon_1_patchset, _warmboot_1_patchset }, //1.0.0 (Patched relocator)
|
||||
{ "20170210155124", 0, 0x1900, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, true, _secmon_2_patchset, _warmboot_2_patchset }, //2.0.0 - 2.3.0
|
||||
{ "20170519101410", 1, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, true, _secmon_3_patchset, _warmboot_3_patchset }, //3.0.0
|
||||
{ "20170710161758", 2, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, true, _secmon_3_patchset, _warmboot_3_patchset }, //3.0.1 - 3.0.2
|
||||
{ "20170921172629", 3, 0x1800, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003B000, false, _secmon_4_patchset, _warmboot_4_patchset }, //4.0.0 - 4.1.0
|
||||
{ "20180220163747", 4, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003B000, false, _secmon_5_patchset, _warmboot_5_patchset }, //5.0.0 - 5.1.0
|
||||
{ "20180802162753", 5, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003D800, false, _secmon_6_patchset, _warmboot_6_patchset }, //6.0.0 - 6.1.0
|
||||
{ "20181107105733", 6, 0x0E00, 0x6FE0, { 1, 2, 0 }, 0x4002B000, 0x4003D800, false, _secmon_620_patchset, _warmboot_620_patchset }, //6.2.0
|
||||
{ NULL } //End.
|
||||
};
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ typedef struct _pkg1_id_t
|
||||
u32 warmboot_base;
|
||||
bool set_warmboot;
|
||||
patch_t *secmon_patchset;
|
||||
patch_t *warmboot_patchset;
|
||||
} pkg1_id_t;
|
||||
|
||||
typedef struct _pk11_hdr_t
|
||||
|
||||
@@ -219,6 +219,7 @@ KERNEL_PATCHSET_DEF(_kernel_4_patchset,
|
||||
);
|
||||
|
||||
KERNEL_PATCHSET_DEF(_kernel_5_patchset,
|
||||
{ SVC_GENERIC, 0x38C2C, _NOP(), NULL }, // Allow same process on svcControlCodeMemory.
|
||||
{ SVC_VERIFY_DS, 0x45E6C, _NOP(), NULL }, // Disable SVC verifications
|
||||
{ DEBUG_MODE_EN, 0x5513C, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch
|
||||
// Atmosphère kernel patches.
|
||||
@@ -233,6 +234,7 @@ KERNEL_PATCHSET_DEF(_kernel_5_patchset,
|
||||
);
|
||||
|
||||
KERNEL_PATCHSET_DEF(_kernel_6_patchset,
|
||||
{ SVC_GENERIC, 0x3A8CC, _NOP(), NULL }, // Allow same process on svcControlCodeMemory.
|
||||
{ SVC_VERIFY_DS, 0x47EA0, _NOP(), NULL }, // Disable SVC verifications
|
||||
{ DEBUG_MODE_EN, 0x57548, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch
|
||||
// Atmosphère kernel patches.
|
||||
@@ -571,7 +573,7 @@ int pkg2_decompress_kip(pkg2_kip1_info_t* ki, u32 sectsToDecomp)
|
||||
memcpy(&hdr, ki->kip1, sizeof(hdr));
|
||||
|
||||
unsigned int newKipSize = sizeof(hdr);
|
||||
for (u32 sectIdx=0; sectIdx<KIP1_NUM_SECTIONS; sectIdx++)
|
||||
for (u32 sectIdx = 0; sectIdx < KIP1_NUM_SECTIONS; sectIdx++)
|
||||
{
|
||||
u32 sectCompBit = 1u << sectIdx;
|
||||
// For compressed, cant get actual decompressed size without doing it, so use safe "output size".
|
||||
@@ -584,7 +586,7 @@ int pkg2_decompress_kip(pkg2_kip1_info_t* ki, u32 sectsToDecomp)
|
||||
pkg2_kip1_t* newKip = malloc(newKipSize);
|
||||
unsigned char* dstDataPtr = newKip->data;
|
||||
const unsigned char* srcDataPtr = ki->kip1->data;
|
||||
for (u32 sectIdx=0; sectIdx<KIP1_NUM_SECTIONS; sectIdx++)
|
||||
for (u32 sectIdx = 0; sectIdx < KIP1_NUM_SECTIONS; sectIdx++)
|
||||
{
|
||||
u32 sectCompBit = 1u << sectIdx;
|
||||
// Easy copy path for uncompressed or ones we dont want to uncompress.
|
||||
@@ -638,7 +640,7 @@ const char* pkg2_patch_kips(link_t *info, char* patchNames)
|
||||
static const u32 MAX_NUM_PATCHES_REQUESTED = sizeof(u32)*8;
|
||||
char* patches[MAX_NUM_PATCHES_REQUESTED];
|
||||
|
||||
u32 numPatches=1;
|
||||
u32 numPatches = 1;
|
||||
patches[0] = patchNames;
|
||||
{
|
||||
for (char* p = patchNames; *p != 0; p++)
|
||||
@@ -646,7 +648,7 @@ const char* pkg2_patch_kips(link_t *info, char* patchNames)
|
||||
if (*p == ',')
|
||||
{
|
||||
*p = 0;
|
||||
patches[numPatches++] = p+1;
|
||||
patches[numPatches++] = p + 1;
|
||||
if (numPatches >= MAX_NUM_PATCHES_REQUESTED)
|
||||
return "too_many_patches";
|
||||
}
|
||||
@@ -656,10 +658,10 @@ const char* pkg2_patch_kips(link_t *info, char* patchNames)
|
||||
}
|
||||
|
||||
u32 patchesApplied = 0; // Bitset over patches.
|
||||
for (u32 i=0; i<numPatches; i++)
|
||||
for (u32 i = 0; i < numPatches; i++)
|
||||
{
|
||||
// Eliminate leading spaces.
|
||||
for (const char* p=patches[i]; *p!=0; p++)
|
||||
for (const char* p = patches[i]; *p != 0; p++)
|
||||
{
|
||||
if (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n')
|
||||
patches[i]++;
|
||||
@@ -671,7 +673,7 @@ const char* pkg2_patch_kips(link_t *info, char* patchNames)
|
||||
continue;
|
||||
|
||||
// Eliminate trailing spaces.
|
||||
for (int chIdx=valueLen-1; chIdx>=0; chIdx--)
|
||||
for (int chIdx=valueLen - 1; chIdx >= 0; chIdx--)
|
||||
{
|
||||
const char* p = patches[i] + chIdx;
|
||||
if (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n')
|
||||
@@ -684,11 +686,11 @@ const char* pkg2_patch_kips(link_t *info, char* patchNames)
|
||||
DPRINTF("Requested patch: '%s'\n", patches[i]);
|
||||
}
|
||||
|
||||
u32 shaBuf[32/sizeof(u32)];
|
||||
u32 shaBuf[32 / sizeof(u32)];
|
||||
LIST_FOREACH_ENTRY(pkg2_kip1_info_t, ki, info, link)
|
||||
{
|
||||
shaBuf[0] = 0; // sha256 for this kip not yet calculated.
|
||||
for (u32 currKipIdx=0; currKipIdx<(sizeof(_kip_ids)/sizeof(_kip_ids[0])); currKipIdx++)
|
||||
for (u32 currKipIdx = 0; currKipIdx < (sizeof(_kip_ids) / sizeof(_kip_ids[0])); currKipIdx++)
|
||||
{
|
||||
if (strncmp((const char*)ki->kip1->name, _kip_ids[currKipIdx].name, sizeof(ki->kip1->name)) != 0)
|
||||
continue;
|
||||
@@ -697,7 +699,7 @@ const char* pkg2_patch_kips(link_t *info, char* patchNames)
|
||||
kip1_patchset_t* currPatchset = _kip_ids[currKipIdx].patchset;
|
||||
while (currPatchset != NULL && currPatchset->name != NULL)
|
||||
{
|
||||
for (u32 i=0; i<numPatches; i++)
|
||||
for (u32 i = 0; i < numPatches; i++)
|
||||
{
|
||||
if (strcmp(currPatchset->name, patches[i]) != 0)
|
||||
{
|
||||
@@ -728,7 +730,7 @@ const char* pkg2_patch_kips(link_t *info, char* patchNames)
|
||||
{
|
||||
if (currPatchset->patches != NULL)
|
||||
{
|
||||
for (u32 currEnabIdx=0; currEnabIdx<numPatches; currEnabIdx++)
|
||||
for (u32 currEnabIdx = 0; currEnabIdx < numPatches; currEnabIdx++)
|
||||
{
|
||||
if (strcmp(currPatchset->name, patches[currEnabIdx]))
|
||||
continue;
|
||||
@@ -752,13 +754,13 @@ const char* pkg2_patch_kips(link_t *info, char* patchNames)
|
||||
if (!se_calc_sha256(shaBuf, ki->kip1, ki->size))
|
||||
memset(shaBuf, 0, sizeof(shaBuf));
|
||||
|
||||
DPRINTF("%dms %s KIP1 size %d hash %08X\n", (postDecompTime-preDecompTime)/1000, ki->kip1->name, (int)ki->size, __builtin_bswap32(shaBuf[0]));
|
||||
DPRINTF("%dms %s KIP1 size %d hash %08X\n", (postDecompTime-preDecompTime) / 1000, ki->kip1->name, (int)ki->size, __builtin_bswap32(shaBuf[0]));
|
||||
#endif
|
||||
|
||||
currPatchset = _kip_ids[currKipIdx].patchset;
|
||||
while (currPatchset != NULL && currPatchset->name != NULL)
|
||||
{
|
||||
for (u32 currEnabIdx=0; currEnabIdx<numPatches; currEnabIdx++)
|
||||
for (u32 currEnabIdx = 0; currEnabIdx < numPatches; currEnabIdx++)
|
||||
{
|
||||
if (strcmp(currPatchset->name, patches[currEnabIdx]))
|
||||
continue;
|
||||
@@ -772,7 +774,7 @@ const char* pkg2_patch_kips(link_t *info, char* patchNames)
|
||||
}
|
||||
|
||||
unsigned char* kipSectData = ki->kip1->data;
|
||||
for (u32 currSectIdx=0; currSectIdx<KIP1_NUM_SECTIONS; currSectIdx++)
|
||||
for (u32 currSectIdx = 0; currSectIdx < KIP1_NUM_SECTIONS; currSectIdx++)
|
||||
{
|
||||
if (bitsAffected & (1u << currSectIdx))
|
||||
{
|
||||
@@ -806,7 +808,7 @@ const char* pkg2_patch_kips(link_t *info, char* patchNames)
|
||||
}
|
||||
}
|
||||
|
||||
for (u32 i=0; i<numPatches; i++)
|
||||
for (u32 i = 0; i < numPatches; i++)
|
||||
{
|
||||
if ((patchesApplied & (1u << i)) == 0)
|
||||
return patches[i];
|
||||
|
||||
@@ -44,8 +44,10 @@ typedef struct _kernel_patch_t
|
||||
|
||||
enum
|
||||
{
|
||||
// Generic instruction patches
|
||||
SVC_VERIFY_DS = 0x10, // 0x0-0xF are RESERVED.
|
||||
// Always applied.
|
||||
SVC_GENERIC = 0,
|
||||
// Generic instruction patches.
|
||||
SVC_VERIFY_DS = 0x10,
|
||||
DEBUG_MODE_EN,
|
||||
ATM_GEN_PATCH,
|
||||
// >4 bytes patches. Value is a pointer of a u32 array.
|
||||
|
||||
@@ -57,7 +57,7 @@ void config_exosphere(const char *id, u32 kb, bool debug)
|
||||
exoFlags |= EXO_FLAG_620_KGN;
|
||||
|
||||
if (debug)
|
||||
exoFlags |= EXO_FLAG_DBG_PRIV | EXO_FLAG_DBG_USER;
|
||||
exoFlags |= EXO_FLAG_DBG_PRIV;
|
||||
|
||||
// Set mailbox values.
|
||||
*mb_exo_magic = EXO_MAGIC_VAL;
|
||||
|
||||
@@ -84,7 +84,7 @@ void ianos_print_error(int errorno)
|
||||
gfx_printf(&gfx_con, "Error loading ELF!\n");
|
||||
break;
|
||||
case 5:
|
||||
gfx_printf(&gfx_con, "Error relcating ELF!\n");
|
||||
gfx_printf(&gfx_con, "Error relocating ELF!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "mem/heap.h"
|
||||
#include "mem/sdram.h"
|
||||
#include "power/max77620.h"
|
||||
#include "rtc/max77620-rtc.h"
|
||||
#include "soc/hw_init.h"
|
||||
#include "soc/i2c.h"
|
||||
#include "soc/pmc.h"
|
||||
@@ -229,6 +230,10 @@ void reboot_rcm()
|
||||
void power_off()
|
||||
{
|
||||
sd_unmount();
|
||||
|
||||
// Stop the alarm, in case we injected and powered off too fast.
|
||||
max77620_rtc_stop_alarm();
|
||||
|
||||
#ifdef MENU_LOGO_ENABLE
|
||||
free(Kc_MENU_LOGO);
|
||||
#endif //MENU_LOGO_ENABLE
|
||||
@@ -243,6 +248,10 @@ void check_power_off_from_hos()
|
||||
if (hosWakeup & MAX77620_IRQ_TOP_RTC_MASK)
|
||||
{
|
||||
sd_unmount();
|
||||
|
||||
// Stop the alarm, in case we injected too fast.
|
||||
max77620_rtc_stop_alarm();
|
||||
|
||||
if (h_cfg.autohosoff == 1)
|
||||
{
|
||||
gfx_clear_grey(&gfx_ctxt, 0x1B);
|
||||
@@ -269,6 +278,7 @@ void check_power_off_from_hos()
|
||||
#define COREBOOT_ADDR (0xD0000000 - 0x100000)
|
||||
|
||||
void (*ext_payload_ptr)() = (void *)EXT_PAYLOAD_ADDR;
|
||||
void (*update_ptr)() = (void *)RCM_PAYLOAD_ADDR;
|
||||
|
||||
void reloc_patcher(u32 payload_size)
|
||||
{
|
||||
@@ -289,7 +299,7 @@ void reloc_patcher(u32 payload_size)
|
||||
}
|
||||
}
|
||||
|
||||
#define BOOTLOADER_UPDATED_MAGIC 0x424f4f54 // "BOOT".
|
||||
#define BOOTLOADER_UPDATED_MAGIC 0x424F4F54 // "BOOT".
|
||||
#define BOOTLOADER_UPDATED_MAGIC_ADDR 0x4003E000
|
||||
|
||||
int launch_payload(char *path, bool update)
|
||||
@@ -375,7 +385,10 @@ int launch_payload(char *path, bool update)
|
||||
}
|
||||
|
||||
// Launch our payload.
|
||||
(*ext_payload_ptr)();
|
||||
if (!update)
|
||||
(*ext_payload_ptr)();
|
||||
else
|
||||
(*update_ptr)();
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -959,7 +972,6 @@ void auto_launch_firmware()
|
||||
#endif //MENU_LOGO_ENABLE
|
||||
|
||||
out:
|
||||
gfx_clear_grey(&gfx_ctxt, 0x1B);
|
||||
ini_free(&ini_sections);
|
||||
if (h_cfg.autoboot_list)
|
||||
ini_free(&ini_list_sections);
|
||||
@@ -1106,8 +1118,8 @@ ment_t ment_tools[] = {
|
||||
MDEF_CAPTION("-------- Misc --------", 0xFF0AB9E6),
|
||||
MDEF_HANDLER("Dump package1/2", dump_packages12),
|
||||
MDEF_HANDLER("Fix battery de-sync", fix_battery_desync),
|
||||
MDEF_HANDLER("Unset archive bit (switch folder)", fix_sd_switch_attr),
|
||||
MDEF_HANDLER("Unset archive bit (all sd files)", fix_sd_all_attr),
|
||||
MDEF_HANDLER("Fix archive bit (except Nintendo folder)", fix_sd_all_attr),
|
||||
MDEF_HANDLER("Fix archive bit (Nintendo folder)", fix_sd_nin_attr),
|
||||
//MDEF_HANDLER("Fix fuel gauge configuration", fix_fuel_gauge_configuration),
|
||||
//MDEF_HANDLER("Reset all battery cfg", reset_pmic_fuel_gauge_charger_config),
|
||||
//MDEF_HANDLER("Minerva", minerva), // Uncomment for testing Minerva Training Cell
|
||||
@@ -1138,16 +1150,15 @@ ment_t ment_top[] = {
|
||||
};
|
||||
menu_t menu_top = {
|
||||
ment_top,
|
||||
"hekate - CTCaer mod v4.5", 0, 0
|
||||
"hekate - CTCaer mod v4.6", 0, 0
|
||||
};
|
||||
|
||||
extern void pivot_stack(u32 stack_top);
|
||||
|
||||
void ipl_main()
|
||||
{
|
||||
// Skip config if we just updated the bootloader.
|
||||
if (*(vu32 *)BOOTLOADER_UPDATED_MAGIC_ADDR != BOOTLOADER_UPDATED_MAGIC)
|
||||
config_hw();
|
||||
// Do initial HW configuration. This is compatible with consecutive reruns without a reset.
|
||||
config_hw();
|
||||
|
||||
//Pivot the stack so we have enough space.
|
||||
pivot_stack(0x90010000);
|
||||
@@ -1155,14 +1166,16 @@ void ipl_main()
|
||||
//Tegra/Horizon configuration goes to 0x80000000+, package2 goes to 0xA9800000, we place our heap in between.
|
||||
heap_init(0x90020000);
|
||||
|
||||
//uart_send(UART_C, (u8 *)0x40000000, 0x10000);
|
||||
//uart_wait_idle(UART_C, UART_TX_IDLE);
|
||||
#ifdef DEBUG_UART_PORT
|
||||
uart_send(DEBUG_UART_PORT, (u8 *)"Hekate: Hello!\r\n", 18);
|
||||
uart_wait_idle(DEBUG_UART_PORT, UART_TX_IDLE);
|
||||
#endif
|
||||
|
||||
// Set bootloader's default configuration.
|
||||
set_default_configuration();
|
||||
|
||||
// Save sdram lp0 config.
|
||||
if (ianos_loader(true, "bootloader/sys/libsys_lp0.bso", DRAM_LIB, (void *)sdram_get_params()))
|
||||
if (ianos_loader(true, "bootloader/sys/libsys_lp0.bso", DRAM_LIB, (void *)sdram_get_params_patched()))
|
||||
h_cfg.errors |= ERR_LIBSYS_LP0;
|
||||
|
||||
display_init();
|
||||
|
||||
@@ -18,11 +18,11 @@
|
||||
#include "../soc/t210.h"
|
||||
#include "mc.h"
|
||||
#include "emc.h"
|
||||
#include "sdram_param_t210.h"
|
||||
#include "../soc/pmc.h"
|
||||
#include "../utils/util.h"
|
||||
#include "../soc/fuse.h"
|
||||
#include "../power/max77620.h"
|
||||
#include "../mem/sdram_param_t210.h"
|
||||
#include "../soc/clock.h"
|
||||
|
||||
#define CONFIG_SDRAM_COMPRESS_CFG
|
||||
@@ -388,9 +388,9 @@ break_nosleep:
|
||||
EMC(EMC_ACPD_CONTROL) = params->emc_acpd_control;
|
||||
EMC(EMC_TXDSRVTTGEN) = params->emc_txdsrvttgen;
|
||||
EMC(EMC_CFG) = (params->emc_cfg & 0xE) | 0x3C00000;
|
||||
if (params->boot_rom_patch_control & 0x80000000)
|
||||
if (params->boot_rom_patch_control & (1 << 31))
|
||||
{
|
||||
*(vu32 *)(4 * (params->boot_rom_patch_control + 0x1C000000)) = params->boot_rom_patch_data;
|
||||
*(vu32 *)(APB_MISC_BASE + params->boot_rom_patch_control * 4) = params->boot_rom_patch_data;
|
||||
MC(MC_TIMING_CONTROL) = 1;
|
||||
}
|
||||
PMC(APBDEV_PMC_IO_DPD3_REQ) = ((4 * params->emc_pmc_scratch1 >> 2) + 0x40000000) & 0xCFFF0000;
|
||||
@@ -489,19 +489,47 @@ break_nosleep:
|
||||
MC(MC_EMEM_CFG_ACCESS_CTRL) = 1; //Disable write access to a bunch of EMC registers.
|
||||
}
|
||||
|
||||
const void *sdram_get_params()
|
||||
sdram_params_t *sdram_get_params()
|
||||
{
|
||||
//TODO: sdram_id should be in [0, 7].
|
||||
|
||||
#ifdef CONFIG_SDRAM_COMPRESS_CFG
|
||||
u8 *buf = (u8 *)0x40030000;
|
||||
LZ_Uncompress(_dram_cfg_lz, buf, sizeof(_dram_cfg_lz));
|
||||
return (const void *)&buf[sizeof(sdram_params_t) * _get_sdram_id()];
|
||||
return (sdram_params_t *)&buf[sizeof(sdram_params_t) * _get_sdram_id()];
|
||||
#else
|
||||
return _dram_cfgs[_get_sdram_id()];
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Function: sdram_get_params_patched
|
||||
*
|
||||
* This code implements a warmboot exploit. Warmboot, that is actually so hot, it burns Nvidia once again.
|
||||
* If the boot_rom_patch_control's MSB is set, it uses it as an index to
|
||||
* APB_MISC_BASE (u32 array) and sets it to the value of boot_rom_patch_data.
|
||||
* (The MSB falls out when it gets multiplied by sizeof(u32)).
|
||||
* Because the bootrom does not do any boundary checks, it lets us write anywhere and anything.
|
||||
* Ipatch hardware let us apply 12 changes to the bootrom and can be changed any time.
|
||||
* The first patch is not needed any more when the exploit is triggered, so we overwrite that.
|
||||
* 0x10459E is the address where it returns an error when the signature is not valid.
|
||||
* We change that to MOV R0, #0, so we pass the check.
|
||||
*
|
||||
* Note: The modulus in the header must match and validated.
|
||||
*/
|
||||
|
||||
sdram_params_t *sdram_get_params_patched()
|
||||
{
|
||||
#define IPATCH_CONFIG(addr, data) (((addr - 0x100000) / 2) << 16 | (data & 0xffff))
|
||||
sdram_params_t *sdram_params = sdram_get_params();
|
||||
|
||||
// Disable Warmboot signature check.
|
||||
sdram_params->boot_rom_patch_control = (1 << 31) | (((IPATCH_BASE + 4) - APB_MISC_BASE) / 4);
|
||||
sdram_params->boot_rom_patch_data = IPATCH_CONFIG(0x10459E, 0x2000);
|
||||
|
||||
return sdram_params;
|
||||
}
|
||||
|
||||
void sdram_init()
|
||||
{
|
||||
//TODO: sdram_id should be in [0,4].
|
||||
|
||||
@@ -17,8 +17,11 @@
|
||||
#ifndef _SDRAM_H_
|
||||
#define _SDRAM_H_
|
||||
|
||||
#include "sdram_param_t210.h"
|
||||
|
||||
void sdram_init();
|
||||
const void *sdram_get_params();
|
||||
sdram_params_t *sdram_get_params();
|
||||
sdram_params_t *sdram_get_params_patched();
|
||||
void sdram_lp0_save_params(const void *params);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright 2014 Google Inc.
|
||||
* Copyright (C) 2018 naehrwert
|
||||
* Copyright (C) 2018 CTCaer
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 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,
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* TODO: the placement of the relocator is a bit fragile atm, maybe we
|
||||
* should include it in start.S and copy it to some known good
|
||||
* place in IRAM instead. Basically we want it as far back atm
|
||||
* as it might be overwritten during relocation.
|
||||
*/
|
||||
|
||||
.section .text.reloc
|
||||
.arm
|
||||
|
||||
.globl _reloc_ipl
|
||||
.type _reloc_ipl, %function
|
||||
_reloc_ipl:
|
||||
LDMIA R0!, {R4-R7}
|
||||
STMIA R1!, {R4-R7}
|
||||
SUBS R2, #0x10
|
||||
BNE _reloc_ipl
|
||||
BX R3
|
||||
77
bootloader/rtc/max77620-rtc.c
Normal file
77
bootloader/rtc/max77620-rtc.c
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* PMIC Real Time Clock driver for Nintendo Switch's MAX77620-RTC
|
||||
*
|
||||
* Copyright (c) 2018 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 "max77620-rtc.h"
|
||||
#include "../soc/i2c.h"
|
||||
#include "../utils/util.h"
|
||||
|
||||
void max77620_rtc_get_time(rtc_time_t *time)
|
||||
{
|
||||
u8 val = 0;
|
||||
|
||||
// Update RTC regs from RTC clock.
|
||||
i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_UPDATE0_REG, MAX77620_RTC_READ_UPDATE);
|
||||
|
||||
// Get control reg config.
|
||||
val = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_CONTROL_REG);
|
||||
// TODO: Check for binary format also?
|
||||
|
||||
// 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;
|
||||
|
||||
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.
|
||||
time->weekday = 0;
|
||||
val = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_WEEKDAY_REG);
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
time->weekday++;
|
||||
if (val & 1)
|
||||
break;
|
||||
val >>= 1;
|
||||
}
|
||||
|
||||
// Get date.
|
||||
time->date = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_DATE_REG) & 0x1f;
|
||||
time->month = (i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_MONTH_REG) & 0xF) - 1;
|
||||
time->year = (i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_YEAR_REG) & 0x7F) + 2000;
|
||||
}
|
||||
|
||||
void max77620_rtc_stop_alarm()
|
||||
{
|
||||
u8 val = 0;
|
||||
|
||||
// Update RTC regs from RTC clock.
|
||||
i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_UPDATE0_REG, MAX77620_RTC_READ_UPDATE);
|
||||
|
||||
// Stop alarm for both ALARM1 and ALARM2. Horizon uses ALARM2.
|
||||
for (int i = 0; i < (MAX77620_RTC_NR_TIME_REGS * 2); i++)
|
||||
{
|
||||
val = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM1_SEC_REG + i);
|
||||
val &= ~MAX77620_RTC_ALARM_EN_MASK;
|
||||
i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM1_SEC_REG + i, val);
|
||||
}
|
||||
|
||||
// Update RTC clock from RTC regs.
|
||||
i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_UPDATE0_REG, MAX77620_RTC_WRITE_UPDATE);
|
||||
}
|
||||
75
bootloader/rtc/max77620-rtc.h
Normal file
75
bootloader/rtc/max77620-rtc.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* PMIC Real Time Clock driver for Nintendo Switch's MAX77620-RTC
|
||||
*
|
||||
* Copyright (c) 2018 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 _MFD_MAX77620_RTC_H_
|
||||
#define _MFD_MAX77620_RTC_H_
|
||||
|
||||
#include "../utils/types.h"
|
||||
|
||||
#define MAX77620_RTC_I2C_ADDR 0x68
|
||||
|
||||
#define MAX77620_RTC_NR_TIME_REGS 7
|
||||
|
||||
#define MAX77620_RTC_CONTROLM_REG 0x02
|
||||
#define MAX77620_RTC_CONTROL_REG 0x03
|
||||
#define MAX77620_RTC_BIN_FORMAT (1 << 0)
|
||||
#define MAX77620_RTC_24H (1 << 1)
|
||||
|
||||
#define MAX77620_RTC_UPDATE0_REG 0x04
|
||||
#define MAX77620_RTC_WRITE_UPDATE (1 << 0)
|
||||
#define MAX77620_RTC_READ_UPDATE (1 << 4)
|
||||
|
||||
#define MAX77620_RTC_SEC_REG 0x07
|
||||
#define MAX77620_RTC_MIN_REG 0x08
|
||||
#define MAX77620_RTC_HOUR_REG 0x09
|
||||
#define MAX77620_RTC_HOUR_PM_MASK (1 << 6)
|
||||
#define MAX77620_RTC_WEEKDAY_REG 0x0A
|
||||
#define MAX77620_RTC_MONTH_REG 0x0B
|
||||
#define MAX77620_RTC_YEAR_REG 0x0C
|
||||
#define MAX77620_RTC_DATE_REG 0x0D
|
||||
|
||||
#define MAX77620_ALARM1_SEC_REG 0x0E
|
||||
#define MAX77620_ALARM1_MIN_REG 0x0F
|
||||
#define MAX77620_ALARM1_HOUR_REG 0x10
|
||||
#define MAX77620_ALARM1_WEEKDAY_REG 0x11
|
||||
#define MAX77620_ALARM1_MONTH_REG 0x12
|
||||
#define MAX77620_ALARM1_YEAR_REG 0x13
|
||||
#define MAX77620_ALARM1_DATE_REG 0x14
|
||||
#define MAX77620_ALARM2_SEC_REG 0x15
|
||||
#define MAX77620_ALARM2_MIN_REG 0x16
|
||||
#define MAX77620_ALARM2_HOUR_REG 0x17
|
||||
#define MAX77620_ALARM2_WEEKDAY_REG 0x18
|
||||
#define MAX77620_ALARM2_MONTH_REG 0x19
|
||||
#define MAX77620_ALARM2_YEAR_REG 0x1A
|
||||
#define MAX77620_ALARM2_DATE_REG 0x1B
|
||||
#define MAX77620_RTC_ALARM_EN_MASK (1 << 7)
|
||||
|
||||
typedef struct _rtc_time_t {
|
||||
u8 weekday;
|
||||
u8 sec;
|
||||
u8 min;
|
||||
u8 hour;
|
||||
u8 date;
|
||||
u8 month;
|
||||
u16 year;
|
||||
} rtc_time_t;
|
||||
|
||||
void max77620_rtc_get_time(rtc_time_t *time);
|
||||
void max77620_rtc_stop_alarm();
|
||||
|
||||
#endif /* _MFD_MAX77620_RTC_H_ */
|
||||
@@ -64,6 +64,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
int res = 0;
|
||||
u8 *fwbuf = NULL;
|
||||
u32 *pdir, *car, *fuse, *pmc, *flowctrl, *se, *mc, *iram, *evec;
|
||||
u32 *pkg11_magic_off;
|
||||
|
||||
//Enable clocks.
|
||||
clock_enable_host1x();
|
||||
@@ -161,6 +162,8 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
// IRAM
|
||||
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));
|
||||
smmu_map(pdir, 0x40010000, (u32)iram, 0x30, _READABLE | _WRITABLE | _NONSECURE);
|
||||
|
||||
// Exception vectors
|
||||
@@ -216,16 +219,17 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
u32 key[16] = {0};
|
||||
u32 kidx = 0;
|
||||
|
||||
while (memcmp((u8 *)(iram + ((tsec_ctxt->pkg11_off + 0x20) / 4)), "PK11", 4))
|
||||
while (*pkg11_magic_off != HOS_PKG11_MAGIC)
|
||||
{
|
||||
smmu_flush_all();
|
||||
|
||||
if (k == se[SE_KEYTABLE_DATA0_REG_OFFSET / 4])
|
||||
continue;
|
||||
k = se[SE_KEYTABLE_DATA0_REG_OFFSET / 4];
|
||||
key[kidx++] = k;
|
||||
|
||||
// Failsafe.
|
||||
if ((u32)get_tmr_us() - start > 500000)
|
||||
if ((u32)get_tmr_us() - start > 125000)
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -237,6 +241,9 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Give some extra time to make sure PKG1.1 is decrypted.
|
||||
msleep(50);
|
||||
|
||||
memcpy(tsec_keys, &key, 0x20);
|
||||
memcpy(tsec_ctxt->pkg1, iram, 0x30000);
|
||||
|
||||
|
||||
@@ -22,11 +22,11 @@
|
||||
/* clock_t: reset, enable, source, index, clk_src, clk_div */
|
||||
|
||||
static const clock_t _clock_uart[] = {
|
||||
/* UART A */ { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTA, 6, 0, 0 },
|
||||
/* UART B */ { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTB, 7, 0, 0 },
|
||||
/* UART C */ { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_UARTC, 0x17, 0, 0 },
|
||||
/* UART D */ { 0 },
|
||||
/* UART E */ { 0 }
|
||||
/* UART A */ { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTA, 6, 0, 0 },
|
||||
/* UART B */ { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTB, 7, 0, 0 },
|
||||
/* UART C */ { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_UARTC, 0x17, 0, 0 },
|
||||
/* UART D */ { 0 },
|
||||
/* UART E */ { 0 }
|
||||
};
|
||||
|
||||
static const clock_t _clock_i2c[] = {
|
||||
|
||||
@@ -222,7 +222,7 @@ int fuse_read_ipatch(void (*ipatch)(u32 offset, u32 value))
|
||||
{
|
||||
for (u32 i = 0; i < ipatch_count; i++)
|
||||
{
|
||||
u32 word = words[i];
|
||||
u32 word = words[i + 1];
|
||||
u32 addr = (word >> 16) * 2;
|
||||
u32 data = word & 0xffff;
|
||||
|
||||
|
||||
@@ -64,8 +64,12 @@ void _config_gpios()
|
||||
PINMUX_AUX(PINMUX_AUX_GPIO_PE6) = PINMUX_INPUT_ENABLE;
|
||||
PINMUX_AUX(PINMUX_AUX_GPIO_PH6) = PINMUX_INPUT_ENABLE;
|
||||
|
||||
#if !defined (DEBUG_UART_PORT) || DEBUG_UART_PORT != UART_B
|
||||
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_GPIO);
|
||||
#endif
|
||||
#if !defined (DEBUG_UART_PORT) || DEBUG_UART_PORT != UART_C
|
||||
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_GPIO);
|
||||
#endif
|
||||
gpio_config(GPIO_PORT_E, GPIO_PIN_6, GPIO_MODE_GPIO);
|
||||
gpio_config(GPIO_PORT_H, GPIO_PIN_6, GPIO_MODE_GPIO);
|
||||
gpio_output_enable(GPIO_PORT_G, GPIO_PIN_0, GPIO_OUTPUT_DISABLE);
|
||||
@@ -187,8 +191,10 @@ void config_hw()
|
||||
APB_MISC(APB_MISC_PP_PINMUX_GLOBAL) = 0;
|
||||
_config_gpios();
|
||||
|
||||
//clock_enable_uart(UART_C);
|
||||
//uart_init(UART_C, 115200);
|
||||
#ifdef DEBUG_UART_PORT
|
||||
clock_enable_uart(DEBUG_UART_PORT);
|
||||
uart_init(DEBUG_UART_PORT, 115200);
|
||||
#endif
|
||||
|
||||
clock_enable_cl_dvfs();
|
||||
|
||||
@@ -201,7 +207,7 @@ void config_hw()
|
||||
i2c_init(I2C_5);
|
||||
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CNFGBBC, 0x40);
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, 0x78);
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, 0x78); // PWR delay for forced shutdown off.
|
||||
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_CFG0, 0x38);
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_CFG1, 0x3A);
|
||||
@@ -241,6 +247,10 @@ void reconfig_hw_workaround(bool extra_reconfig, u32 magic)
|
||||
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO);
|
||||
gpio_config(GPIO_PORT_E, GPIO_PIN_6, GPIO_MODE_SPIO);
|
||||
gpio_config(GPIO_PORT_H, GPIO_PIN_6, GPIO_MODE_SPIO);
|
||||
|
||||
// Fix GPU after warmboot for Linux.
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO5, 2);
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO6, 2);
|
||||
}
|
||||
|
||||
// Power off display.
|
||||
@@ -255,4 +265,4 @@ void reconfig_hw_workaround(bool extra_reconfig, u32 magic)
|
||||
|
||||
msleep(200);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
void pinmux_config_uart(u32 idx)
|
||||
{
|
||||
PINMUX_AUX(PINMUX_AUX_UARTX_RX(idx)) = 0;
|
||||
PINMUX_AUX(PINMUX_AUX_UARTX_TX(idx)) = PINMUX_INPUT_ENABLE | PINMUX_PULL_UP;
|
||||
PINMUX_AUX(PINMUX_AUX_UARTX_TX(idx)) = 0;
|
||||
PINMUX_AUX(PINMUX_AUX_UARTX_RX(idx)) = PINMUX_INPUT_ENABLE | PINMUX_PULL_UP;
|
||||
PINMUX_AUX(PINMUX_AUX_UARTX_RTS(idx)) = 0;
|
||||
PINMUX_AUX(PINMUX_AUX_UARTX_CTS(idx)) = PINMUX_INPUT_ENABLE | PINMUX_PULL_DOWN;
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ void smmu_enable()
|
||||
|
||||
cluster_boot_cpu0((u32)smmu_payload);
|
||||
smmu_used = true;
|
||||
msleep(100);
|
||||
msleep(150);
|
||||
|
||||
smmu_flush_all();
|
||||
}
|
||||
|
||||
@@ -107,6 +107,8 @@
|
||||
#define APB_MISC_PP_STRAPPING_OPT_A 0x08
|
||||
#define APB_MISC_PP_PINMUX_GLOBAL 0x40
|
||||
#define APB_MISC_GP_LCD_BL_PWM_CFGPADCTRL 0xA34
|
||||
#define APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL 0xA98
|
||||
#define APB_MISC_GP_EMMC4_PAD_CFGPADCTRL 0xAB4
|
||||
#define APB_MISC_GP_WIFI_EN_CFGPADCTRL 0xB64
|
||||
#define APB_MISC_GP_WIFI_RST_CFGPADCTRL 0xB68
|
||||
|
||||
|
||||
@@ -25,32 +25,37 @@ void uart_init(u32 idx, u32 baud)
|
||||
{
|
||||
uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]);
|
||||
|
||||
//Set baud rate.
|
||||
u32 rate = (8 * baud + 408000000) / (16 * baud);
|
||||
uart->UART_LCR = 0x80; //Enable DLAB.
|
||||
uart->UART_THR_DLAB = (u8)rate; //Divisor latch LSB.
|
||||
uart->UART_IER_DLAB = (u8)(rate >> 8); //Divisor latch MSB.
|
||||
uart->UART_LCR = 0; //Diable DLAB.
|
||||
// Make sure no data is being sent.
|
||||
uart_wait_idle(idx, UART_TX_IDLE);
|
||||
|
||||
//Setup UART in fifo mode.
|
||||
uart->UART_IER_DLAB = 0;
|
||||
uart->UART_IIR_FCR = 7; //Enable and clear TX and RX FIFOs.
|
||||
(void)uart->UART_LSR;
|
||||
// Misc settings.
|
||||
u32 rate = (8 * baud + 408000000) / (16 * baud);
|
||||
uart->UART_IER_DLAB = 0; // Disable interrupts.
|
||||
uart->UART_MCR = 0; // Disable hardware flow control.
|
||||
uart->UART_LCR = UART_LCR_DLAB | UART_LCR_WORD_LENGTH_8; // Enable DLAB & set 8n1 mode.
|
||||
uart->UART_THR_DLAB = (u8)rate; // Divisor latch LSB.
|
||||
uart->UART_IER_DLAB = (u8)(rate >> 8); // Divisor latch MSB.
|
||||
uart->UART_LCR = UART_LCR_WORD_LENGTH_8; // Diable DLAB.
|
||||
|
||||
// Setup and flush fifo.
|
||||
uart->UART_IIR_FCR = UART_IIR_FCR_EN_FIFO | UART_IIR_FCR_RX_CLR | UART_IIR_FCR_TX_CLR;
|
||||
usleep(3 * ((baud + 999999) / baud));
|
||||
uart->UART_LCR = 3; //Set word length 8.
|
||||
uart->UART_MCR = 0;
|
||||
uart->UART_MSR = 0;
|
||||
uart->UART_IRDA_CSR = 0;
|
||||
uart->UART_RX_FIFO_CFG = 1;
|
||||
uart->UART_MIE = 0;
|
||||
uart->UART_ASR = 0;
|
||||
uart_wait_idle(idx, UART_TX_IDLE | UART_RX_IDLE);
|
||||
}
|
||||
|
||||
void uart_wait_idle(u32 idx, u32 which)
|
||||
{
|
||||
uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]);
|
||||
while (!(uart->UART_VENDOR_STATUS & which))
|
||||
;
|
||||
if (UART_TX_IDLE & which)
|
||||
{
|
||||
while (!(uart->UART_LSR & UART_LSR_TMTY))
|
||||
;
|
||||
}
|
||||
if (UART_RX_IDLE & which)
|
||||
{
|
||||
while (uart->UART_LSR & UART_LSR_RDR)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void uart_send(u32 idx, u8 *buf, u32 len)
|
||||
@@ -59,7 +64,7 @@ void uart_send(u32 idx, u8 *buf, u32 len)
|
||||
|
||||
for (u32 i = 0; i != len; i++)
|
||||
{
|
||||
while (uart->UART_LSR & UART_TX_FIFO_FULL)
|
||||
while (!(uart->UART_LSR & UART_LSR_THRE))
|
||||
;
|
||||
uart->UART_THR_DLAB = buf[i];
|
||||
};
|
||||
@@ -71,7 +76,7 @@ void uart_recv(u32 idx, u8 *buf, u32 len)
|
||||
|
||||
for (u32 i = 0; i != len; i++)
|
||||
{
|
||||
while (uart->UART_LSR & UART_RX_FIFO_EMPTY)
|
||||
while (!(uart->UART_LSR & UART_LSR_RDR))
|
||||
;
|
||||
buf[i] = uart->UART_THR_DLAB;
|
||||
};
|
||||
|
||||
@@ -28,11 +28,21 @@
|
||||
|
||||
#define BAUD_115200 115200
|
||||
|
||||
#define UART_TX_IDLE 0x00000001
|
||||
#define UART_RX_IDLE 0x00000002
|
||||
#define UART_TX_IDLE 0x1
|
||||
#define UART_RX_IDLE 0x2
|
||||
|
||||
#define UART_TX_FIFO_FULL 0x100
|
||||
#define UART_RX_FIFO_EMPTY 0x200
|
||||
|
||||
#define UART_LCR_DLAB 0x80
|
||||
#define UART_LCR_WORD_LENGTH_8 0x3
|
||||
#define UART_LSR_RDR 0x1
|
||||
#define UART_LSR_THRE 0x20
|
||||
#define UART_LSR_TMTY 0x40
|
||||
#define UART_IIR_FCR_TX_CLR 0x4
|
||||
#define UART_IIR_FCR_RX_CLR 0x2
|
||||
#define UART_IIR_FCR_EN_FIFO 0x1
|
||||
|
||||
typedef struct _uart_t
|
||||
{
|
||||
/* 0x00 */ vu32 UART_THR_DLAB;
|
||||
|
||||
@@ -143,8 +143,20 @@ static int _sdmmc_get_clkcon(sdmmc_t *sdmmc)
|
||||
static void _sdmmc_pad_config_fallback(sdmmc_t *sdmmc, u32 power)
|
||||
{
|
||||
_sdmmc_get_clkcon(sdmmc);
|
||||
if (sdmmc->id == SDMMC_4)
|
||||
*(vu32 *)0x70000AB4 = ((*(vu32 *)0x70000AB4) & 0x3FFC) | 0x1040;
|
||||
switch (sdmmc->id)
|
||||
{
|
||||
case SDMMC_1:
|
||||
if (power == SDMMC_POWER_OFF)
|
||||
break;
|
||||
if (power == SDMMC_POWER_1_8)
|
||||
APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL) = 0x304; // Up: 3, Dn: 4.
|
||||
else if (power == SDMMC_POWER_3_3)
|
||||
APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL) = 0x808; // Up: 8, Dn: 8.
|
||||
break;
|
||||
case SDMMC_4:
|
||||
APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) = (APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) & 0x3FFC) | 0x1040;
|
||||
break;
|
||||
}
|
||||
//TODO: load standard values for other controllers, can depend on power.
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user