Compare commits

..

25 Commits

Author SHA1 Message Date
Kostas Missos
4f2bbbf101 Fix GPU on Linux when booting from warmboot 2019-02-12 00:46:06 +02:00
Kostas Missos
b677d6cad3 Add max77620-rtc driver & disable alarm on shut off 2019-02-12 00:45:27 +02:00
Kostas Missos
b3f8961e45 Fix sleep with 6.X.X secmon when debug mode is on 2019-02-12 00:42:22 +02:00
Kostas Missos
2f37811aba Normalize brom patches & add sd autocalib fallback 2019-02-12 00:40:40 +02:00
Kostas Missos
5cd596e53c Add SVC generic patches
First patch allows same process on svcControlCodeMemory
2019-02-12 00:36:24 +02:00
Kostas Missos
4ae42c3a9d Small fixes and whitespace
Additionally make info functions smaller and show available fuses.
2019-02-12 00:34:35 +02:00
Kostas Missos
e105634b0d Proper warmboot exploit impl and documentation
Side effect:
Fixed a bug where the dumped patched bootrom had the warmboot exploit patch

Co-Authored-By: Balázs Triszka <balika011@gmail.com>
2018-12-17 21:10:13 +02:00
Kostas Missos
4781dc2ab4 Bump version to v4.6 2018-12-17 02:31:44 +02:00
Kostas Missos
e779e53406 Some tiny fixes 2018-12-17 02:31:00 +02:00
Kostas Missos
9f5b97620a Fix return to main when setting an autoboot option
This fixes the issue with "More configs".
2018-12-16 20:21:59 +02:00
Kostas Missos
98d715243a Fixes to update.bin reloc (breaking!)
This fixes a regression in chainloading update.bin where the added check for if it's update or not, didn't copy the reloc code. And the calling was not updated to reflect this.

Additionally:
- Delete the reloc.S relic
- Force running config_hw in case we change hw init again in the future.
2018-12-16 19:04:46 +02:00
Kostas Missos
e809745120 Auto HOS power off disabled by default
Enable it in options
2018-12-16 16:59:25 +02:00
Kostas Missos
0d9aebda7b Fix archive bits V2
It can now fix the whole nintendo folder.

A proposed usage is by using the first option and then the 2nd.
2018-12-16 16:57:49 +02:00
Kostas Missos
5ed875ce90 Make tsec checks faster and cover unluckiest cases
+ changes for readability
2018-12-16 16:55:56 +02:00
Kostas Missos
30d3c76655 Bugfixes 2018-12-16 16:52:38 +02:00
Kostas Missos
949a034500 Merge pull request #166 from balika011/warmboot
Add warmboot patches for efuse checks
2018-12-16 16:23:09 +02:00
balika011
b2893d7fb6 Add warmboot patches for efuse checks
Fixes sleep on downgrade
2018-12-16 15:21:17 +01:00
Kostas Missos
9a3fdd944e Merge pull request #165 from balika011/overclock
Fine-tune dram configs for OC
2018-12-16 16:17:51 +02:00
balika011
8b8f3c564c Fine-tune dram configs
Helps overclocking
2018-12-16 14:51:16 +01:00
Kostas Missos
cd1bb96241 Merge pull request #164 from balika011/ipatches_fix
Fix ipatch printing
2018-12-16 14:54:43 +02:00
balika011
8b59ddf3a8 Fix ipatch printing 2018-12-16 12:35:48 +01:00
Kostas Missos
09bfed9146 Merge pull request #162 from balika011/ipatches_fix
Fix ipatches backup on dumping
2018-12-15 21:45:26 +02:00
Kostas Missos
cbe75d7769 Merge pull request #158 from hyln9/master
Fix debug uart
2018-12-15 21:44:03 +02:00
balika011
dad380344f Fix ipatches backup on dumping 2018-12-15 17:04:14 +01:00
Yule Hou
71b0975730 Fix debug uart 2018-12-08 12:38:59 +08:00
34 changed files with 501 additions and 183 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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();

View File

@@ -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;

View File

@@ -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.
};

View File

@@ -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

View File

@@ -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];

View File

@@ -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.

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -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();

View File

@@ -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].

View File

@@ -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

View File

@@ -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,

View File

@@ -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

View 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);
}

View 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_ */

View File

@@ -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);

View File

@@ -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[] = {

View File

@@ -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;

View File

@@ -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);
}
}
}

View File

@@ -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;
}

View File

@@ -94,7 +94,7 @@ void smmu_enable()
cluster_boot_cpu0((u32)smmu_payload);
smmu_used = true;
msleep(100);
msleep(150);
smmu_flush_all();
}

View File

@@ -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

View File

@@ -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;
};

View File

@@ -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;

View File

@@ -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.
}