From 03872e814a3fc882c37d49ea2a2074739962ff23 Mon Sep 17 00:00:00 2001 From: "ctcaer@gmail.com" Date: Sun, 30 Jun 2019 03:55:19 +0300 Subject: [PATCH] [Nyx] Prep hekate main for nyx --- bootloader/config/config.c | 12 ++ bootloader/config/config.h | 2 + bootloader/hos/hos.c | 4 + bootloader/main.c | 67 ++++++++++++ bootloader/soc/bpmp.c | 217 +++++++++++++++++++++++++++++++++++++ bootloader/soc/bpmp.h | 51 +++++++++ bootloader/soc/hw_init.c | 6 + bootloader/utils/types.h | 3 + bootloader/utils/util.c | 5 + bootloader/utils/util.h | 14 +++ 10 files changed, 381 insertions(+) create mode 100644 bootloader/soc/bpmp.c create mode 100644 bootloader/soc/bpmp.h diff --git a/bootloader/config/config.c b/bootloader/config/config.c index 38f88db..810e2d3 100644 --- a/bootloader/config/config.c +++ b/bootloader/config/config.c @@ -42,6 +42,8 @@ void set_default_configuration() h_cfg.backlight = 100; h_cfg.autohosoff = 0; h_cfg.autonogc = 1; + h_cfg.brand = NULL; + h_cfg.tagline = NULL; h_cfg.errors = 0; h_cfg.sept_run = EMC(EMC_SCRATCH0) & EMC_SEPT_RUN; h_cfg.rcm_patched = true; @@ -104,6 +106,16 @@ int create_config_entry() f_puts("\nautonogc=", &fp); itoa(h_cfg.autonogc, lbuf, 10); f_puts(lbuf, &fp); + if (h_cfg.brand) + { + f_puts("\nbrand=", &fp); + f_puts(h_cfg.brand, &fp); + } + if (h_cfg.tagline) + { + f_puts("\ntagline=", &fp); + f_puts(h_cfg.tagline, &fp); + } f_puts("\n", &fp); if (mainIniFound) diff --git a/bootloader/config/config.h b/bootloader/config/config.h index 435c1ee..c972765 100644 --- a/bootloader/config/config.h +++ b/bootloader/config/config.h @@ -29,6 +29,8 @@ typedef struct _hekate_config u32 backlight; u32 autohosoff; u32 autonogc; + char *brand; + char *tagline; // Global temporary config. bool se_keygen_done; u32 sbar_time_keeping; diff --git a/bootloader/hos/hos.c b/bootloader/hos/hos.c index 56ae936..aa39205 100644 --- a/bootloader/hos/hos.c +++ b/bootloader/hos/hos.c @@ -32,6 +32,7 @@ #include "../sec/se.h" #include "../sec/se_t210.h" #include "../sec/tsec.h" +#include "../soc/bpmp.h" #include "../soc/cluster.h" #include "../soc/fuse.h" #include "../soc/pmc.h" @@ -677,6 +678,9 @@ int hos_launch(ini_sec_t *cfg) // Clear EMC_SCRATCH0. EMC(EMC_SCRATCH0) = 0; + // Flush cache and disable MMU. + bpmp_mmu_disable(); + bpmp_clk_rate_set(BPMP_CLK_NORMAL); minerva_change_freq(FREQ_800); // Wait for secmon to get ready. diff --git a/bootloader/main.c b/bootloader/main.c index 36276fd..9cfe0a0 100644 --- a/bootloader/main.c +++ b/bootloader/main.c @@ -35,6 +35,7 @@ #include "mem/sdram.h" #include "power/max77620.h" #include "rtc/max77620-rtc.h" +#include "soc/bpmp.h" #include "soc/fuse.h" #include "soc/hw_init.h" #include "soc/i2c.h" @@ -71,6 +72,8 @@ const volatile ipl_ver_meta_t __attribute__((section ("._ipl_version"))) ipl_ver .rsvd1 = 0 }; +volatile nyx_storage_t *nyx_str = (nyx_storage_t *)NYX_STORAGE_ADDR; + bool sd_mount() { if (sd_mounted) @@ -691,8 +694,56 @@ out: btn_wait(); } +void nyx_load_run() +{ + sd_mount(); + + u8 *nyx = sd_file_read("bootloader/sys/nyx.bin", false); + if (!nyx) + return; + + sd_unmount(); + + gfx_clear_grey(0x1B); + u8 *BOOTLOGO = (void *)malloc(0x4000); + blz_uncompress_srcdest(BOOTLOGO_BLZ, SZ_BOOTLOGO_BLZ, BOOTLOGO, SZ_BOOTLOGO); + gfx_set_rect_grey(BOOTLOGO, X_BOOTLOGO, Y_BOOTLOGO, 326, 544); + free(BOOTLOGO); + display_backlight_brightness(h_cfg.backlight, 1000); + + nyx_str->cfg = 0; + if (b_cfg.extra_cfg & EXTRA_CFG_NYX_DUMP) + { + b_cfg.extra_cfg &= ~(EXTRA_CFG_NYX_DUMP); + nyx_str->cfg |= NYX_CFG_DUMP; + } + if (nyx_str->mtc_cfg.mtc_table) + nyx_str->cfg |= NYX_CFG_MINERVA; + + nyx_str->version = ipl_ver.version - 0x303030; + + memcpy((u8 *)nyx_str->irama, (void *)IRAM_BASE, 0x8000); + volatile reloc_meta_t *reloc = (reloc_meta_t *)(IPL_LOAD_ADDR + RELOC_META_OFF); + memcpy((u8 *)nyx_str->hekate, (u8 *)reloc->start, reloc->end - reloc->start); + + void (*nyx_ptr)() = (void *)nyx; + + bpmp_mmu_disable(); + bpmp_clk_rate_set(BPMP_CLK_NORMAL); + msleep(100); + minerva_periodic_training(); + + (*nyx_ptr)(); +} + void auto_launch_firmware() { + if(!h_cfg.sept_run && (b_cfg.extra_cfg & EXTRA_CFG_NYX_DUMP)) + { + EMC(EMC_SCRATCH0) |= EMC_HEKA_UPD; + check_sept(); + } + if (!h_cfg.sept_run) auto_launch_update(); @@ -756,6 +807,16 @@ void auto_launch_firmware() h_cfg.autohosoff = atoi(kv->val); else if (!strcmp("autonogc", kv->key)) h_cfg.autonogc = atoi(kv->val); + else if (!strcmp("brand", kv->key)) + { + h_cfg.brand = malloc(strlen(kv->val) + 1); + strcpy(h_cfg.brand, kv->val); + } + else if (!strcmp("tagline", kv->key)) + { + h_cfg.tagline = malloc(strlen(kv->val) + 1); + strcpy(h_cfg.tagline, kv->val); + } } boot_entry_id++; @@ -949,6 +1010,9 @@ out: b_cfg.boot_cfg &= ~(BOOT_CFG_AUTOBOOT_EN | BOOT_CFG_FROM_LAUNCH); h_cfg.emummc_force_disable = false; + + nyx_load_run(); + sd_unmount(); } @@ -1197,6 +1261,9 @@ void ipl_main() display_backlight_pwm_init(); //display_backlight_brightness(h_cfg.backlight, 1000); + // Overclock BPMP. + bpmp_clk_rate_set(BPMP_CLK_SUPER_BOOST); + // Check if we had a panic while in CFW. secmon_exo_check_panic(); diff --git a/bootloader/soc/bpmp.c b/bootloader/soc/bpmp.c new file mode 100644 index 0000000..5fdc10e --- /dev/null +++ b/bootloader/soc/bpmp.c @@ -0,0 +1,217 @@ +/* + * BPMP-Lite Cache/MMU driver for Tegra X1 + * + * Copyright (c) 2019 CTCaer + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "bpmp.h" +#include "clock.h" +#include "t210.h" +#include "../utils/util.h" + +#define BPMP_CACHE_CONFIG 0x0 +#define CFG_ENABLE (1 << 0) +#define CFG_FORCE_WRITE_THROUGH (1 << 3) +#define CFG_DISABLE_WRITE_BUFFER (1 << 10) +#define CFG_DISABLE_READ_BUFFER (1 << 11) +#define CFG_FULL_LINE_DIRTY (1 << 13) +#define CFG_TAG_CHK_ABRT_ON_ERR (1 << 14) +#define BPMP_CACHE_LOCK 0x4 +#define BPMP_CACHE_SIZE 0xC +#define BPMP_CACHE_LFSR 0x10 +#define BPMP_CACHE_TAG_STATUS 0x14 +#define BPMP_CACHE_CLKEN_OVERRIDE 0x18 +#define BPMP_CACHE_MAINT_ADDR 0x20 +#define BPMP_CACHE_MAINT_DATA 0x24 +#define BPMP_CACHE_MAINT_REQ 0x28 +#define MAINT_REQ_WAY_BITMAP(x) ((x) << 8) + +#define BPMP_CACHE_INT_MASK 0x40 +#define BPMP_CACHE_INT_CLEAR 0x44 +#define INT_CLR_MAINT_DONE (1 << 0) + +#define BPMP_CACHE_INT_RAW_EVENT 0x48 +#define INT_RAW_EVENT_MAINT_DONE (1 << 0) +#define BPMP_CACHE_INT_STATUS 0x4C + +#define BPMP_CACHE_RB_CFG 0x80 +#define BPMP_CACHE_WB_CFG 0x84 + +#define BPMP_CACHE_MMU_FALLBACK_ENTRY 0xA0 +#define BPMP_CACHE_MMU_SHADOW_COPY_MASK 0xA4 +#define BPMP_CACHE_MMU_CFG 0xAC +#define MMU_CFG_SEQ_EN (1 << 1) +#define MMU_CFG_TLB_EN (1 << 2) +#define MMU_CFG_ABORT_STORE_LAST (1 << 4) +#define BPMP_CACHE_MMU_CMD 0xB0 +#define MMU_CMD_NOP 0 +#define MMU_CMD_INIT 1 +#define MMU_CMD_COPY_SHADOW 2 +#define BPMP_CACHE_MMU_ABORT_STAT 0xB4 +#define BPMP_CACHE_MMU_ABORT_ADDR 0xB8 +#define BPMP_CACHE_MMU_ACTIVE_ENTRIES 0xBC + +#define BPMP_MMU_SHADOW_ENTRY_BASE (BPMP_CACHE_BASE + 0x400) +#define BPMP_MMU_MAIN_ENTRY_BASE (BPMP_CACHE_BASE + 0x800) +#define MMU_ENTRY_ADDR_MASK 0xFFFFFFE0 + +#define MMU_EN_CACHED (1 << 0) +#define MMU_EN_EXEC (1 << 1) +#define MMU_EN_READ (1 << 2) +#define MMU_EN_WRITE (1 << 3) + +bpmp_mmu_entry_t mmu_entries[] = +{ + { 0x80000000, 0xFFFFFFFF, MMU_EN_READ | MMU_EN_WRITE | MMU_EN_EXEC | MMU_EN_CACHED, true }, + { IPL_LOAD_ADDR, 0x40040000, MMU_EN_READ | MMU_EN_WRITE | MMU_EN_EXEC | MMU_EN_CACHED, true } +}; + +void bpmp_mmu_maintenance(u32 op) +{ + if (!(BPMP_CACHE_CTRL(BPMP_CACHE_CONFIG) & CFG_ENABLE)) + return; + + //BPMP_CACHE_CTRL(BPMP_CACHE_INT_CLEAR) = INT_CLR_MAINT_DONE; + + // This is a blocking operation. + BPMP_CACHE_CTRL(BPMP_CACHE_MAINT_REQ) = MAINT_REQ_WAY_BITMAP(0xF) | op; + + //while(!(BPMP_CACHE_CTRL(BPMP_CACHE_INT_RAW_EVENT) & INT_RAW_EVENT_MAINT_DONE)) + // ; + + //BPMP_CACHE_CTRL(BPMP_CACHE_INT_CLEAR) = BPMP_CACHE_CTRL(BPMP_CACHE_INT_RAW_EVENT); +} + +void bpmp_mmu_set_entry(int idx, bpmp_mmu_entry_t *entry, bool apply) +{ + if (idx > 31) + return; + + volatile bpmp_mmu_entry_t *mmu_entry = (bpmp_mmu_entry_t *)(BPMP_MMU_SHADOW_ENTRY_BASE + sizeof(bpmp_mmu_entry_t) * idx); + + if (entry->enable) + { + mmu_entry->min_addr = entry->min_addr & MMU_ENTRY_ADDR_MASK; + mmu_entry->max_addr = entry->max_addr & MMU_ENTRY_ADDR_MASK; + mmu_entry->attr = entry->attr; + + BPMP_CACHE_CTRL(BPMP_CACHE_MMU_SHADOW_COPY_MASK) |= (1 << idx); + + if (apply) + BPMP_CACHE_CTRL(BPMP_CACHE_MMU_CMD) = MMU_CMD_COPY_SHADOW; + } +} + +void bpmp_mmu_enable() +{ + if (BPMP_CACHE_CTRL(BPMP_CACHE_CONFIG) & CFG_ENABLE) + return; + + // Init BPMP MMU. + BPMP_CACHE_CTRL(BPMP_CACHE_MMU_CMD) = MMU_CMD_INIT; + BPMP_CACHE_CTRL(BPMP_CACHE_MMU_FALLBACK_ENTRY) = MMU_EN_READ | MMU_EN_WRITE | MMU_EN_EXEC; // RWX for non-defined regions. + BPMP_CACHE_CTRL(BPMP_CACHE_MMU_CFG) = MMU_CFG_SEQ_EN | MMU_CFG_TLB_EN | MMU_CFG_ABORT_STORE_LAST; + + // Init BPMP MMU entries. + BPMP_CACHE_CTRL(BPMP_CACHE_MMU_SHADOW_COPY_MASK) = 0; + for (u32 idx = 0; idx < (sizeof(mmu_entries) / sizeof(bpmp_mmu_entry_t)); idx++) + bpmp_mmu_set_entry(idx, &mmu_entries[idx], false); + + BPMP_CACHE_CTRL(BPMP_CACHE_MMU_CMD) = MMU_CMD_COPY_SHADOW; + + // Invalidate cache. + bpmp_mmu_maintenance(BPMP_MMU_MAINT_INVALID_WAY); + + // Enable cache. + BPMP_CACHE_CTRL(BPMP_CACHE_CONFIG) = CFG_ENABLE | CFG_FORCE_WRITE_THROUGH | CFG_TAG_CHK_ABRT_ON_ERR; + + // HW bug. Invalidate cache again. + bpmp_mmu_maintenance(BPMP_MMU_MAINT_INVALID_WAY); +} + +void bpmp_mmu_disable() +{ + if (!(BPMP_CACHE_CTRL(BPMP_CACHE_CONFIG) & CFG_ENABLE)) + return; + + // Clean and invalidate cache. + bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY); + + // Enable cache. + BPMP_CACHE_CTRL(BPMP_CACHE_CONFIG) = 0; + + // HW bug. Invalidate cache again. + bpmp_mmu_maintenance(BPMP_MMU_MAINT_INVALID_WAY); +} + +static u8 pllc4_divn[] = { + 0, // BPMP_CLK_NORMAL: 408MHz 0% - 136MHz APB. + 85, // BPMP_CLK_LOW_BOOST: 544MHz 33% - 136MHz APB. + 90, // BPMP_CLK_MID_BOOST: 576MHz 41% - 144MHz APB. + 95 // BPMP_CLK_SUPER_BOOST: 608MHz 49% - 152MHz APB. +}; + +bpmp_freq_t bpmp_clock_set = BPMP_CLK_NORMAL; + +void bpmp_clk_rate_set(bpmp_freq_t fid) +{ + if (fid > (BPMP_CLK_MAX - 1)) + fid = BPMP_CLK_MAX - 1; + + if (bpmp_clock_set == fid) + return; + + if (fid) + { + if (bpmp_clock_set) + { + // Restore to PLLP source during PLLC4 configuration. + CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = + (CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) & 0xFFFF8888) | 0x3333; // PLLP_OUT. + // Wait a bit for clock source change. + msleep(10); + } + + CLOCK(CLK_RST_CONTROLLER_PLLC4_MISC) = (1 << 30); + CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) = 4 | (pllc4_divn[fid] << 8) | (1 << 30); // DIVM: 4, DIVP: 1. + + while (!(CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) & (1 << 27))) + ; + + CLOCK(CLK_RST_CONTROLLER_PLLC4_OUT) = (1 << 8) | (1 << 1); // 1.5 div. + CLOCK(CLK_RST_CONTROLLER_PLLC4_OUT) |= 1; // Get divider out of reset. + + // Wait a bit for PLLC4 to stabilize. + msleep(10); + CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 3; // PCLK = HCLK / 4. + CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = + (CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) & 0xFFFF8888) | 0x3323; // PLLC4_OUT3. + + bpmp_clock_set = fid; + } + else + { + CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = + (CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) & 0xFFFF8888) | 0x3333; // PLLP_OUT. + + // Wait a bit for clock source change. + msleep(10); + + CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; // PCLK = HCLK / 3. + CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) &= ~(1<<30); + bpmp_clock_set = BPMP_CLK_NORMAL; + } +} + diff --git a/bootloader/soc/bpmp.h b/bootloader/soc/bpmp.h new file mode 100644 index 0000000..bacb2d1 --- /dev/null +++ b/bootloader/soc/bpmp.h @@ -0,0 +1,51 @@ +/* + * BPMP-Lite Cache/MMU driver for Tegra X1 + * + * Copyright (c) 2019 CTCaer + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _BPMP_H_ +#define _BPMP_H_ + +#include "../utils/types.h" + +#define BPMP_MMU_MAINT_CLEAN_WAY 17 +#define BPMP_MMU_MAINT_INVALID_WAY 18 +#define BPMP_MMU_MAINT_CLN_INV_WAY 19 + +typedef struct _bpmp_mmu_entry_t +{ + u32 min_addr; + u32 max_addr; + u32 attr; + u32 enable; +} bpmp_mmu_entry_t; + +typedef enum +{ + BPMP_CLK_NORMAL, // 408MHz 0% - 136MHz APB. + BPMP_CLK_LOW_BOOST, // 544MHz 33% - 136MHz APB. + BPMP_CLK_MID_BOOST, // 576MHz 41% - 144MHz APB. + BPMP_CLK_SUPER_BOOST, // 608MHz 49% - 152MHz APB. + BPMP_CLK_MAX +} bpmp_freq_t; + +void bpmp_mmu_maintenance(u32 op); +void bpmp_mmu_set_entry(int idx, bpmp_mmu_entry_t *entry, bool apply); +void bpmp_mmu_enable(); +void bpmp_mmu_disable(); +void bpmp_clk_rate_set(bpmp_freq_t fid); + +#endif diff --git a/bootloader/soc/hw_init.c b/bootloader/soc/hw_init.c index 7d1f5f9..fd12236 100644 --- a/bootloader/soc/hw_init.c +++ b/bootloader/soc/hw_init.c @@ -18,6 +18,7 @@ #include #include "hw_init.h" +#include "bpmp.h" #include "clock.h" #include "fuse.h" #include "gpio.h" @@ -248,10 +249,15 @@ void config_hw() CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = (CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) & 0xFFFF8888) | 0x3333; sdram_init(); + + bpmp_mmu_enable(); } void reconfig_hw_workaround(bool extra_reconfig, u32 magic) { + // Flush and disable MMU. + bpmp_mmu_disable(); + bpmp_clk_rate_set(BPMP_CLK_NORMAL); minerva_change_freq(FREQ_204); // Re-enable clocks to Audio Processing Engine as a workaround to hanging. diff --git a/bootloader/utils/types.h b/bootloader/utils/types.h index abe237a..bbddae0 100644 --- a/bootloader/utils/types.h +++ b/bootloader/utils/types.h @@ -59,6 +59,9 @@ typedef int bool; #define EXTRA_CFG_PAYLOAD (1 << 1) #define EXTRA_CFG_MODULE (1 << 2) +#define EXTRA_CFG_NYX_RELOAD (1 << 6) +#define EXTRA_CFG_NYX_DUMP (1 << 7) + typedef struct __attribute__((__packed__)) _boot_cfg_t { u8 boot_cfg; diff --git a/bootloader/utils/util.c b/bootloader/utils/util.c index 4368a61..778db8e 100644 --- a/bootloader/utils/util.c +++ b/bootloader/utils/util.c @@ -19,6 +19,7 @@ #include "../gfx/di.h" #include "../power/max77620.h" #include "../rtc/max77620-rtc.h" +#include "../soc/bpmp.h" #include "../soc/i2c.h" #include "../soc/pmc.h" #include "../soc/t210.h" @@ -78,6 +79,8 @@ void panic(u32 val) void reboot_normal() { + bpmp_mmu_disable(); + sd_unmount(); display_end(); @@ -86,6 +89,8 @@ void reboot_normal() void reboot_rcm() { + bpmp_mmu_disable(); + sd_unmount(); display_end(); diff --git a/bootloader/utils/util.h b/bootloader/utils/util.h index f261035..ae736dd 100644 --- a/bootloader/utils/util.h +++ b/bootloader/utils/util.h @@ -19,6 +19,10 @@ #define _UTIL_H_ #include "types.h" +#include "../mem/minerva.h" + +#define NYX_CFG_DUMP (1 << 7) +#define NYX_CFG_MINERVA (1 << 8) #define byte_swap_32(num) (((num >> 24) & 0xff) | ((num << 8) & 0xff0000) | \ ((num >> 8 )& 0xff00) | ((num << 24) & 0xff000000)) @@ -29,6 +33,16 @@ typedef struct _cfg_op_t u32 val; } cfg_op_t; +typedef struct _nyx_storage_t +{ + u32 version; + u32 cfg; + u8 irama[0x8000]; + u8 hekate[0x30000]; + u8 rsvd[0x800000]; + mtc_config_t mtc_cfg; +} nyx_storage_t; + u32 get_tmr_us(); u32 get_tmr_ms(); u32 get_tmr_s();