Compare commits
51 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
814c9d1cfb | ||
|
|
9d7b548ce0 | ||
|
|
d779eea009 | ||
|
|
3038612774 | ||
|
|
59be817bb8 | ||
|
|
b965e3f335 | ||
|
|
43c0e39c34 | ||
|
|
0d8bde6079 | ||
|
|
38f942adf5 | ||
|
|
145ee8fcc8 | ||
|
|
48772307bf | ||
|
|
2619ccad0c | ||
|
|
6d5d97cfcd | ||
|
|
846f610fff | ||
|
|
2e8f06ef44 | ||
|
|
5fbd728962 | ||
|
|
11ec6a6912 | ||
|
|
b89f0e45ec | ||
|
|
18d998034d | ||
|
|
27994bb306 | ||
|
|
3e2ec256ab | ||
|
|
bf5bbfbcef | ||
|
|
d10621e832 | ||
|
|
d3b697fd1d | ||
|
|
daa7f5db79 | ||
|
|
4adc0e4096 | ||
|
|
8e3c34ea89 | ||
|
|
a85e20bcea | ||
|
|
879f8a5147 | ||
|
|
f78653d815 | ||
|
|
3c7c1fbd8a | ||
|
|
8efdd04fcd | ||
|
|
623b5f4eb9 | ||
|
|
af352e4f7f | ||
|
|
2866cb5fe6 | ||
|
|
b5becba8ff | ||
|
|
36c47a0014 | ||
|
|
0b0fdc5c58 | ||
|
|
5a15d62b8b | ||
|
|
d0404f3cc9 | ||
|
|
2ae298de24 | ||
|
|
a2d2b1b346 | ||
|
|
06e4b94674 | ||
|
|
f1a9dd8a98 | ||
|
|
0a18c63f24 | ||
|
|
f9a199557c | ||
|
|
0fdbdb1f4d | ||
|
|
e734b23f11 | ||
|
|
de1e6c9705 | ||
|
|
71b220a4e9 | ||
|
|
5448332009 |
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: ReSwitched Discord
|
||||
url: https://discordapp.com/invite/DThbZ7z
|
||||
about: Please ask questions here, instead of making GitHub issues.
|
||||
7
.github/ISSUE_TEMPLATE/question.md
vendored
7
.github/ISSUE_TEMPLATE/question.md
vendored
@@ -1,7 +0,0 @@
|
||||
---
|
||||
name: Question
|
||||
about: Please ask questions in the ReSwitched discord, instead of making issues.
|
||||
---
|
||||
We would like to use GitHub to keep track of problems/feature requests.
|
||||
If you have a question, please join the ReSwitched discord for help.
|
||||
- Discord link: https://discordapp.com/invite/DThbZ7z
|
||||
7
Makefile
7
Makefile
@@ -7,7 +7,7 @@ ifneq (, $(strip $(shell git status --porcelain 2>/dev/null)))
|
||||
AMSREV := $(AMSREV)-dirty
|
||||
endif
|
||||
|
||||
COMPONENTS := fusee stratosphere exosphere thermosphere troposphere libraries
|
||||
COMPONENTS := fusee stratosphere mesosphere exosphere thermosphere troposphere libraries
|
||||
|
||||
all: $(COMPONENTS)
|
||||
|
||||
@@ -20,13 +20,16 @@ exosphere: thermosphere
|
||||
stratosphere: exosphere libraries
|
||||
$(MAKE) -C stratosphere all
|
||||
|
||||
mesosphere: exosphere libraries
|
||||
$(MAKE) -C mesosphere all
|
||||
|
||||
troposphere: stratosphere
|
||||
$(MAKE) -C troposphere all
|
||||
|
||||
sept: exosphere
|
||||
$(MAKE) -C sept all
|
||||
|
||||
fusee: exosphere stratosphere sept
|
||||
fusee: exosphere mesosphere stratosphere sept
|
||||
$(MAKE) -C $@ all
|
||||
|
||||
libraries:
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
[hbl_config]
|
||||
; program_id=010000000000100D
|
||||
; Program Specific Config
|
||||
; Up to 8 program-specific configurations can be set.
|
||||
; These use `program_id_#` and `override_key_#`
|
||||
; where # is in range [0,7].
|
||||
; program_id_0=010000000000100D
|
||||
; override_key_0=!R
|
||||
|
||||
; Any Application Config
|
||||
; Note that this will only apply to program IDs that
|
||||
; are both applications and not specified above
|
||||
; by a program specific config.
|
||||
; override_any_app=true
|
||||
; path=atmosphere/hbl.nsp
|
||||
; override_key=!R
|
||||
; override_any_app_key=R
|
||||
; path=atmosphere/hbl.nsp
|
||||
|
||||
[default_config]
|
||||
; override_key=!L
|
||||
|
||||
@@ -32,6 +32,12 @@
|
||||
; NOTE: EXPERIMENTAL
|
||||
; If you do not know what you are doing, do not touch this yet.
|
||||
; fsmitm_redirect_saves_to_sd = u8!0x0
|
||||
; Controls whether to enable the deprecated hid mitm
|
||||
; to fix compatibility with old homebrew.
|
||||
; 0 = Do not enable, 1 = Enable.
|
||||
; Please note this setting may be removed in a
|
||||
; future release of Atmosphere.
|
||||
; enable_deprecated_hid_mitm = u8!0x0
|
||||
[hbloader]
|
||||
; Controls the size of the homebrew heap when running as applet.
|
||||
; If set to zero, all available applet memory is used as heap.
|
||||
|
||||
@@ -1,4 +1,38 @@
|
||||
# Changelog
|
||||
## 0.10.2
|
||||
+ hbl configuration was made more flexible.
|
||||
+ Up to eight specific program ids can now be specified to have their own override keys.
|
||||
+ This allows designating both the album applet and a specific game as hbl by default as desired.
|
||||
+ Configuration targeting a specific program is now mutually exclusive with override-any-app for that program.
|
||||
+ This fixes unintuitive behavior when override key differed for an application specific program.
|
||||
+ Loader's external content fileystem support was fixed (thanks @misson20000!).
|
||||
+ KernelLdr was reimplemented.
|
||||
+ This is the first step towards developing mesosphere, Atmosphere's planned reimplementation of the Switch's Kernel.
|
||||
+ The typical user won't notice anything different, as there are no extensions, but a lot of groundwork was laid for future development.
|
||||
+ Improvements were made to the way Atmosphere's buildsystem detects source code files.
|
||||
+ This significantly reduces compilation time (saving >30 seconds) on the machine that builds official releases.
|
||||
+ Certain device code was cleaned up and made more correct in fusee/sept/exosphere (thanks @hexkyz!).
|
||||
+ A number of changes were made to the way fs.mitm builds images when providing a layeredfs romfs.
|
||||
+ Some games (Resident Evil 6, Football Manager 2020 Touch, possibly others) have enormous numbers of files.
|
||||
+ Attempting to create a layeredfs mod for these games actually caused fs.mitm to run out of memory, causing a fatal error.
|
||||
+ The code that creates these images was changed to be significantly more memory efficient.
|
||||
+ However, these changes also cause a significant slowdown in the romfs building code (~2-5x).
|
||||
+ This introduced a noticeable stutter when launching a game, because the UI thread would block on the romfs creation.
|
||||
+ To solve this, fs.mitm now lazily initializes the image in a background thread.
|
||||
+ This fixes stutter issues, however some games may be slightly slower (~1-2s in the worst cases) to transition from the "loading" GIF to gameplay now.
|
||||
+ Please note: the slowdown is not noticeable in the common case where games don't have tons of files (typical is ~0.1-0.2 seconds).
|
||||
+ Once the image has been built, there is no further speed penalty at runtime -- only when the game is launched.
|
||||
+ A number of other bugs were fixed, including:
|
||||
+ Several minor logic inversions that could have caused fatal errors when modding games.
|
||||
+ Atmosphere's new-ipc code did not handle "automatic" recvlist buffers correctly, so some non-libnx homebrew could crash.
|
||||
+ fs.mitm now correctly mitms sdb, which makes redirection of certain system data archives work again.
|
||||
+ In 0.10.0/0.10.1, changing the system font/language did not work correctly due to this.
|
||||
+ A bug was fixed in process cleanup that caused the system to hang on < 5.0.0.
|
||||
+ The temporary hid-mitm added in Atmosphere 0.9.0 was disabled by default.
|
||||
+ Please ensure your homebrew is updated.
|
||||
+ For now, users may re-enable this mitm by use of a custom setting (`atmosphere!enable_deprecated_hid_mitm`) to ease the transition process some.
|
||||
+ Please note: support for this setting may be removed to save memory in a future atmosphere release.
|
||||
+ General system stability improvements to enhance the user's experience.
|
||||
## 0.10.1
|
||||
+ A bug was fixed that caused memory reallocation to the system pool to work improperly on firmware 5.0.0 and above.
|
||||
+ Atmosphere was always trying to deallocate memory away from the applet pool and towards the system pool.
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* 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 <stdint.h>
|
||||
|
||||
#include "utils.h"
|
||||
@@ -33,7 +33,7 @@ static inline uint32_t get_special_clk_reg(CarDevice dev) {
|
||||
case CARDEVICE_BPMP: return 0;
|
||||
default: reboot();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t get_special_clk_val(CarDevice dev) {
|
||||
switch (dev) {
|
||||
@@ -48,19 +48,19 @@ static inline uint32_t get_special_clk_val(CarDevice dev) {
|
||||
}
|
||||
|
||||
static uint32_t g_clk_reg_offsets[NUM_CAR_BANKS] = {0x010, 0x014, 0x018, 0x360, 0x364, 0x280, 0x298};
|
||||
static uint32_t g_rst_reg_offsets[NUM_CAR_BANKS] = {0x004, 0x008, 0x00C, 0x358, 0x35C, 0x28C, 0x2A4};
|
||||
static uint32_t g_rst_reg_offsets[NUM_CAR_BANKS] = {0x004, 0x008, 0x00C, 0x358, 0x35C, 0x28C, 0x2A4};
|
||||
|
||||
static uint32_t g_clk_clr_reg_offsets[NUM_CAR_BANKS] = {0x324, 0x32C, 0x334, 0x444, 0x44C, 0x228, 0x2A0};
|
||||
|
||||
void car_configure_oscillators(void) {
|
||||
/* Enable the crystal oscillator, setting drive strength to the saved value in PMC. */
|
||||
CLK_RST_CONTROLLER_OSC_CTRL_0 = (CLK_RST_CONTROLLER_OSC_CTRL_0 & 0xFFFFFC0E) | 1 | (((APBDEV_PMC_OSC_EDPD_OVER_0 >> 1) & 0x3F) << 4);
|
||||
|
||||
|
||||
/* Set CLK_M_DIVISOR to 1 (causes actual division by 2.) */
|
||||
CLK_RST_CONTROLLER_SPARE_REG0_0 = (1 << 2);
|
||||
/* Reading the register after writing it is required to ensure value takes. */
|
||||
(void)(CLK_RST_CONTROLLER_SPARE_REG0_0);
|
||||
|
||||
|
||||
/* Set TIMERUS_USEC_CFG to cycle at 0x60 / 0x5 = 19.2 MHz. */
|
||||
/* Value is (dividend << 8) | (divisor). */
|
||||
TIMERUS_USEC_CFG_0 = 0x45F;
|
||||
@@ -68,30 +68,30 @@ void car_configure_oscillators(void) {
|
||||
|
||||
void car_mbist_workaround(void) {
|
||||
/* This code works around MBIST bug. */
|
||||
|
||||
|
||||
/* Clear LVL2_CLK_GATE_OVR* registers. */
|
||||
CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRA_0 = 0;
|
||||
CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRB_0 = 0;
|
||||
CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRC_0 = 0;
|
||||
CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD_0 = 0;
|
||||
CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRE_0 = 0;
|
||||
|
||||
|
||||
/* Clear bit patterns in CAR. */
|
||||
/* L: Reset all but RTC, TMR, GPIO, BPMP Cache (CACHE2). */
|
||||
/* L: Reset all but RTC, TMR, GPIO, BPMP Cache (CACHE2). */
|
||||
MAKE_CAR_REG(g_clk_clr_reg_offsets[0]) = MAKE_CAR_REG(g_clk_reg_offsets[0]) & 0x7FFFFECF;
|
||||
/* H: Reset all but MC, PMC, FUSE, EMC. */
|
||||
/* H: Reset all but MC, PMC, FUSE, EMC. */
|
||||
MAKE_CAR_REG(g_clk_clr_reg_offsets[1]) = MAKE_CAR_REG(g_clk_reg_offsets[1]) & 0xFDFFFF3E;
|
||||
/* U: Reset all but CSITE, IRAM[A-D], BPMP Cache RAM (CRAM2). */
|
||||
/* U: Reset all but CSITE, IRAM[A-D], BPMP Cache RAM (CRAM2). */
|
||||
MAKE_CAR_REG(g_clk_clr_reg_offsets[2]) = MAKE_CAR_REG(g_clk_reg_offsets[2]) & 0xFE0FFDFF;
|
||||
/* V: Reset all but MSELECT, S/PDIF audio doubler, TZRAM, SE. */
|
||||
/* V: Reset all but MSELECT, S/PDIF audio doubler, TZRAM, SE. */
|
||||
MAKE_CAR_REG(g_clk_clr_reg_offsets[3]) = MAKE_CAR_REG(g_clk_reg_offsets[3]) & 0x3FBFFFF7;
|
||||
/* W: Reset all but PCIERX[0-5], ENTROPY. */
|
||||
/* W: Reset all but PCIERX[0-5], ENTROPY. */
|
||||
MAKE_CAR_REG(g_clk_clr_reg_offsets[4]) = MAKE_CAR_REG(g_clk_reg_offsets[4]) & 0xFFDFFF03;
|
||||
/* X: Reset all but ETC, MCLK, MCLK2, I2C6, EMC_DLL, GPU, DBGAPB, PLLG_REF, . */
|
||||
/* X: Reset all but ETC, MCLK, MCLK2, I2C6, EMC_DLL, GPU, DBGAPB, PLLG_REF, . */
|
||||
MAKE_CAR_REG(g_clk_clr_reg_offsets[5]) = MAKE_CAR_REG(g_clk_reg_offsets[5]) & 0xDCFFB87F;
|
||||
/* Y: Reset all but MC_CDPA, MC_CCPA. */
|
||||
/* Y: Reset all but MC_CDPA, MC_CCPA. */
|
||||
MAKE_CAR_REG(g_clk_clr_reg_offsets[6]) = MAKE_CAR_REG(g_clk_reg_offsets[6]) & 0xFFFFFCFF;
|
||||
|
||||
|
||||
/* Enable clock to MC1, if CH1 is enabled in EMC. */
|
||||
if (EMC_FBIO_CFG7_0 & 4) { /* CH1_ENABLE */
|
||||
CLK_RST_CONTROLLER_CLK_ENB_W_SET_0 |= 0x40000000; /* SET_CLK_ENB_MC1 */
|
||||
@@ -132,3 +132,7 @@ void clkrst_reboot(CarDevice dev) {
|
||||
clkrst_disable(dev);
|
||||
clkrst_enable(dev);
|
||||
}
|
||||
|
||||
void clkrst_enable_fuse_regs(bool enable) {
|
||||
CLK_RST_CONTROLLER_MISC_CLK_ENB_0 = ((CLK_RST_CONTROLLER_MISC_CLK_ENB_0 & 0xEFFFFFFF) | ((enable & 1) << 28));
|
||||
}
|
||||
@@ -103,7 +103,8 @@ void rst_disable(CarDevice dev);
|
||||
|
||||
void clkrst_enable(CarDevice dev);
|
||||
void clkrst_disable(CarDevice dev);
|
||||
|
||||
void clkrst_reboot(CarDevice dev);
|
||||
|
||||
void clkrst_enable_fuse_regs(bool enable);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -29,7 +29,7 @@ bool fuse_check_downgrade_status(void) {
|
||||
}
|
||||
|
||||
void fuse_disable_programming(void) {
|
||||
FUSE_REGS->FUSE_DIS_PGM = 1;
|
||||
FUSE_REGS->FUSE_DISABLEREGPROGRAM = 1;
|
||||
}
|
||||
|
||||
static fuse_bypass_data_t g_fuse_bypass_entries[NUM_FUSE_BYPASS_ENTRIES] = {
|
||||
@@ -37,13 +37,14 @@ static fuse_bypass_data_t g_fuse_bypass_entries[NUM_FUSE_BYPASS_ENTRIES] = {
|
||||
};
|
||||
|
||||
void fuse_configure_fuse_bypass(void) {
|
||||
/* Enable fuses in CAR? This seems to affect fuse data visibility. */
|
||||
CLK_RST_CONTROLLER_MISC_CLK_ENB_0 |= 0x10000000;
|
||||
/* Make all fuse registers visible. */
|
||||
clkrst_enable_fuse_regs(true);
|
||||
|
||||
/* Configure bypass/override, only if programming is allowed. */
|
||||
if (!(FUSE_REGS->FUSE_DIS_PGM & 1)) {
|
||||
/* Enable write access. */
|
||||
FUSE_REGS->FUSE_WRITE_ACCESS = (FUSE_REGS->FUSE_WRITE_ACCESS & ~0x1) | 0x10000;
|
||||
/* Configure bypass/override, only if programming is allowed. */
|
||||
if (!(FUSE_REGS->FUSE_DISABLEREGPROGRAM & 1)) {
|
||||
/* Enable write access and flush status. */
|
||||
FUSE_REGS->FUSE_WRITE_ACCESS_SW = (FUSE_REGS->FUSE_WRITE_ACCESS_SW & ~0x1) | 0x10000;
|
||||
|
||||
/* Enable fuse bypass config. */
|
||||
FUSE_REGS->FUSE_FUSEBYPASS = 1;
|
||||
|
||||
@@ -53,7 +54,7 @@ void fuse_configure_fuse_bypass(void) {
|
||||
}
|
||||
|
||||
/* Disable fuse write access. */
|
||||
FUSE_REGS->FUSE_WRITE_ACCESS |= 1;
|
||||
FUSE_REGS->FUSE_WRITE_ACCESS_SW |= 1;
|
||||
|
||||
/* Enable fuse bypass config. */
|
||||
/* I think this is a bug, and Nintendo meant to write 0 here? */
|
||||
@@ -63,7 +64,7 @@ void fuse_configure_fuse_bypass(void) {
|
||||
/* I have no idea why this happens. What? */
|
||||
/* This is probably also either a bug or does nothing. */
|
||||
/* Is this bit even clearable? */
|
||||
FUSE_REGS->FUSE_DIS_PGM &= 0xFFFFFFFE;
|
||||
FUSE_REGS->FUSE_DISABLEREGPROGRAM &= 0xFFFFFFFE;
|
||||
|
||||
/* Restore saved private key disable bit. */
|
||||
FUSE_REGS->FUSE_PRIVATEKEYDISABLE |= (APBDEV_PMC_SECURE_SCRATCH21_0 & 0x10);
|
||||
@@ -71,5 +72,4 @@ void fuse_configure_fuse_bypass(void) {
|
||||
/* Lock private key disable secure scratch. */
|
||||
APBDEV_PMC_SEC_DISABLE2_0 |= 0x4000000;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -23,154 +23,167 @@
|
||||
#include "utils.h"
|
||||
|
||||
typedef struct {
|
||||
uint32_t FUSE_CTRL;
|
||||
uint32_t FUSE_REG_ADDR;
|
||||
uint32_t FUSE_REG_READ;
|
||||
uint32_t FUSE_REG_WRITE;
|
||||
uint32_t FUSE_TIME_RD1;
|
||||
uint32_t FUSE_TIME_RD2;
|
||||
uint32_t FUSE_TIME_PGM1;
|
||||
uint32_t FUSE_TIME_PGM2;
|
||||
uint32_t FUSE_PRIV2INTFC;
|
||||
uint32_t FUSE_FUSECTRL;
|
||||
uint32_t FUSE_FUSEADDR;
|
||||
uint32_t FUSE_FUSERDATA;
|
||||
uint32_t FUSE_FUSEWDATA;
|
||||
uint32_t FUSE_FUSETIME_RD1;
|
||||
uint32_t FUSE_FUSETIME_RD2;
|
||||
uint32_t FUSE_FUSETIME_PGM1;
|
||||
uint32_t FUSE_FUSETIME_PGM2;
|
||||
uint32_t FUSE_PRIV2INTFC_START;
|
||||
uint32_t FUSE_FUSEBYPASS;
|
||||
uint32_t FUSE_PRIVATEKEYDISABLE;
|
||||
uint32_t FUSE_DIS_PGM;
|
||||
uint32_t FUSE_WRITE_ACCESS;
|
||||
uint32_t FUSE_DISABLEREGPROGRAM;
|
||||
uint32_t FUSE_WRITE_ACCESS_SW;
|
||||
uint32_t FUSE_PWR_GOOD_SW;
|
||||
uint32_t _0x38[0x32];
|
||||
} fuse_registers_t;
|
||||
uint32_t _0x38;
|
||||
uint32_t FUSE_PRIV2RESHIFT;
|
||||
uint32_t _0x40[0x3];
|
||||
uint32_t FUSE_FUSETIME_RD3;
|
||||
uint32_t _0x50[0xC];
|
||||
uint32_t FUSE_PRIVATE_KEY0_NONZERO;
|
||||
uint32_t FUSE_PRIVATE_KEY1_NONZERO;
|
||||
uint32_t FUSE_PRIVATE_KEY2_NONZERO;
|
||||
uint32_t FUSE_PRIVATE_KEY3_NONZERO;
|
||||
uint32_t FUSE_PRIVATE_KEY4_NONZERO;
|
||||
uint32_t _0x90[0x1C];
|
||||
} tegra_fuse_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t FUSE_PRODUCTION_MODE;
|
||||
uint32_t _0x4;
|
||||
uint32_t _0x8;
|
||||
uint32_t _0xC;
|
||||
uint32_t FUSE_JTAG_SECUREID_VALID;
|
||||
uint32_t FUSE_ODM_LOCK;
|
||||
uint32_t FUSE_OPT_OPENGL_EN;
|
||||
uint32_t FUSE_SKU_INFO;
|
||||
uint32_t FUSE_CPU_SPEEDO_0;
|
||||
uint32_t FUSE_CPU_IDDQ;
|
||||
uint32_t _0x1C;
|
||||
uint32_t _0x20;
|
||||
uint32_t _0x24;
|
||||
uint32_t FUSE_FT_REV;
|
||||
uint32_t FUSE_CPU_SPEEDO_1;
|
||||
uint32_t FUSE_CPU_SPEEDO_2;
|
||||
uint32_t FUSE_SOC_SPEEDO_0;
|
||||
uint32_t FUSE_SOC_SPEEDO_1;
|
||||
uint32_t FUSE_SOC_SPEEDO_2;
|
||||
uint32_t FUSE_SOC_IDDQ;
|
||||
uint32_t _0x44;
|
||||
uint32_t FUSE_CPU_SPEEDO_0_CALIB;
|
||||
uint32_t FUSE_CPU_IDDQ_CALIB;
|
||||
uint32_t FUSE_DAC_CRT_CALIB;
|
||||
uint32_t FUSE_DAC_HDTV_CALIB;
|
||||
uint32_t FUSE_DAC_SDTV_CALIB;
|
||||
uint32_t FUSE_OPT_FT_REV;
|
||||
uint32_t FUSE_CPU_SPEEDO_1_CALIB;
|
||||
uint32_t FUSE_CPU_SPEEDO_2_CALIB;
|
||||
uint32_t FUSE_SOC_SPEEDO_0_CALIB;
|
||||
uint32_t FUSE_SOC_SPEEDO_1_CALIB;
|
||||
uint32_t FUSE_SOC_SPEEDO_2_CALIB;
|
||||
uint32_t FUSE_SOC_IDDQ_CALIB;
|
||||
uint32_t FUSE_RESERVED_PRODUCTION_WP;
|
||||
uint32_t FUSE_FA;
|
||||
uint32_t _0x4C;
|
||||
uint32_t _0x50;
|
||||
uint32_t _0x54;
|
||||
uint32_t _0x58;
|
||||
uint32_t _0x5C;
|
||||
uint32_t _0x60;
|
||||
uint32_t FUSE_RESERVED_PRODUCTION;
|
||||
uint32_t FUSE_HDMI_LANE0_CALIB;
|
||||
uint32_t FUSE_HDMI_LANE1_CALIB;
|
||||
uint32_t FUSE_HDMI_LANE2_CALIB;
|
||||
uint32_t FUSE_HDMI_LANE3_CALIB;
|
||||
uint32_t FUSE_ENCRYPTION_RATE;
|
||||
uint32_t FUSE_PUBLIC_KEY[0x8];
|
||||
uint32_t FUSE_TSENSOR_1;
|
||||
uint32_t FUSE_TSENSOR_2;
|
||||
uint32_t _0x8C;
|
||||
uint32_t FUSE_CP_REV;
|
||||
uint32_t _0x94;
|
||||
uint32_t FUSE_TSENSOR_0;
|
||||
uint32_t FUSE_FIRST_BOOTROM_PATCH_SIZE_REG;
|
||||
uint32_t FUSE_TSENSOR1_CALIB;
|
||||
uint32_t FUSE_TSENSOR2_CALIB;
|
||||
uint32_t FUSE_VSENSOR_CALIB;
|
||||
uint32_t FUSE_OPT_CP_REV;
|
||||
uint32_t FUSE_OPT_PFG;
|
||||
uint32_t FUSE_TSENSOR0_CALIB;
|
||||
uint32_t FUSE_FIRST_BOOTROM_PATCH_SIZE;
|
||||
uint32_t FUSE_SECURITY_MODE;
|
||||
uint32_t FUSE_PRIVATE_KEY[0x4];
|
||||
uint32_t FUSE_DEVICE_KEY;
|
||||
uint32_t _0xB8;
|
||||
uint32_t _0xBC;
|
||||
uint32_t FUSE_PRIVATE_KEY[0x5];
|
||||
uint32_t FUSE_ARM_JTAG_DIS;
|
||||
uint32_t FUSE_BOOT_DEVICE_INFO;
|
||||
uint32_t FUSE_RESERVED_SW;
|
||||
uint32_t FUSE_VP8_ENABLE;
|
||||
uint32_t FUSE_OPT_VP9_DISABLE;
|
||||
uint32_t FUSE_RESERVED_ODM[0x8];
|
||||
uint32_t _0xE8;
|
||||
uint32_t _0xEC;
|
||||
uint32_t FUSE_SKU_USB_CALIB;
|
||||
uint32_t FUSE_OBS_DIS;
|
||||
uint32_t FUSE_NOR_INFO;
|
||||
uint32_t FUSE_USB_CALIB;
|
||||
uint32_t FUSE_SKU_DIRECT_CONFIG;
|
||||
uint32_t _0xF8;
|
||||
uint32_t _0xFC;
|
||||
uint32_t FUSE_VENDOR_CODE;
|
||||
uint32_t FUSE_FAB_CODE;
|
||||
uint32_t FUSE_LOT_CODE_0;
|
||||
uint32_t FUSE_LOT_CODE_1;
|
||||
uint32_t FUSE_WAFER_ID;
|
||||
uint32_t FUSE_X_COORDINATE;
|
||||
uint32_t FUSE_Y_COORDINATE;
|
||||
uint32_t _0x11C;
|
||||
uint32_t _0x120;
|
||||
uint32_t FUSE_KFUSE_PRIVKEY_CTRL;
|
||||
uint32_t FUSE_PACKAGE_INFO;
|
||||
uint32_t FUSE_OPT_VENDOR_CODE;
|
||||
uint32_t FUSE_OPT_FAB_CODE;
|
||||
uint32_t FUSE_OPT_LOT_CODE_0;
|
||||
uint32_t FUSE_OPT_LOT_CODE_1;
|
||||
uint32_t FUSE_OPT_WAFER_ID;
|
||||
uint32_t FUSE_OPT_X_COORDINATE;
|
||||
uint32_t FUSE_OPT_Y_COORDINATE;
|
||||
uint32_t FUSE_OPT_SEC_DEBUG_EN;
|
||||
uint32_t FUSE_OPT_OPS_RESERVED;
|
||||
uint32_t FUSE_SATA_CALIB;
|
||||
uint32_t FUSE_GPU_IDDQ;
|
||||
uint32_t FUSE_TSENSOR_3;
|
||||
uint32_t _0x130;
|
||||
uint32_t _0x134;
|
||||
uint32_t _0x138;
|
||||
uint32_t _0x13C;
|
||||
uint32_t _0x140;
|
||||
uint32_t _0x144;
|
||||
uint32_t FUSE_GPU_IDDQ_CALIB;
|
||||
uint32_t FUSE_TSENSOR3_CALIB;
|
||||
uint32_t FUSE_SKU_BOND_OUT_L;
|
||||
uint32_t FUSE_SKU_BOND_OUT_H;
|
||||
uint32_t FUSE_SKU_BOND_OUT_U;
|
||||
uint32_t FUSE_SKU_BOND_OUT_V;
|
||||
uint32_t FUSE_SKU_BOND_OUT_W;
|
||||
uint32_t FUSE_OPT_SAMPLE_TYPE;
|
||||
uint32_t FUSE_OPT_SUBREVISION;
|
||||
uint32_t _0x14C;
|
||||
uint32_t _0x150;
|
||||
uint32_t FUSE_TSENSOR_4;
|
||||
uint32_t FUSE_TSENSOR_5;
|
||||
uint32_t FUSE_TSENSOR_6;
|
||||
uint32_t FUSE_TSENSOR_7;
|
||||
uint32_t FUSE_OPT_PRIV_SEC_DIS;
|
||||
uint32_t FUSE_OPT_SW_RESERVED_0;
|
||||
uint32_t FUSE_OPT_SW_RESERVED_1;
|
||||
uint32_t FUSE_TSENSOR4_CALIB;
|
||||
uint32_t FUSE_TSENSOR5_CALIB;
|
||||
uint32_t FUSE_TSENSOR6_CALIB;
|
||||
uint32_t FUSE_TSENSOR7_CALIB;
|
||||
uint32_t FUSE_OPT_PRIV_SEC_EN;
|
||||
uint32_t FUSE_PKC_DISABLE;
|
||||
uint32_t _0x16C;
|
||||
uint32_t _0x170;
|
||||
uint32_t _0x174;
|
||||
uint32_t _0x178;
|
||||
uint32_t _0x17C;
|
||||
uint32_t FUSE_FUSE2TSEC_DEBUG_DISABLE;
|
||||
uint32_t FUSE_TSENSOR_COMMON;
|
||||
uint32_t _0x184;
|
||||
uint32_t _0x188;
|
||||
uint32_t _0x18C;
|
||||
uint32_t _0x190;
|
||||
uint32_t FUSE_OPT_CP_BIN;
|
||||
uint32_t FUSE_OPT_GPU_DISABLE;
|
||||
uint32_t FUSE_OPT_FT_BIN;
|
||||
uint32_t FUSE_OPT_DONE_MAP;
|
||||
uint32_t _0x194;
|
||||
uint32_t _0x198;
|
||||
uint32_t FUSE_DEBUG_AUTH_OVERRIDE;
|
||||
uint32_t FUSE_APB2JTAG_DISABLE;
|
||||
uint32_t FUSE_ODM_INFO;
|
||||
uint32_t _0x1A0;
|
||||
uint32_t _0x1A4;
|
||||
uint32_t _0x1A8;
|
||||
uint32_t FUSE_ARM_CRYPT_DE_FEATURE;
|
||||
uint32_t _0x1AC;
|
||||
uint32_t _0x1B0;
|
||||
uint32_t _0x1B4;
|
||||
uint32_t _0x1B8;
|
||||
uint32_t _0x1BC;
|
||||
uint32_t _0x1D0;
|
||||
uint32_t FUSE_TSENSOR_8;
|
||||
uint32_t FUSE_WOA_SKU_FLAG;
|
||||
uint32_t FUSE_ECO_RESERVE_1;
|
||||
uint32_t FUSE_GCPLEX_CONFIG_FUSE;
|
||||
uint32_t FUSE_PRODUCTION_MONTH;
|
||||
uint32_t FUSE_RAM_REPAIR_INDICATOR;
|
||||
uint32_t FUSE_TSENSOR9_CALIB;
|
||||
uint32_t _0x1D8;
|
||||
uint32_t _0x1DC;
|
||||
uint32_t _0x1E0;
|
||||
uint32_t _0x1E4;
|
||||
uint32_t _0x1E8;
|
||||
uint32_t _0x1EC;
|
||||
uint32_t _0x1F0;
|
||||
uint32_t _0x1F4;
|
||||
uint32_t _0x1F8;
|
||||
uint32_t FUSE_VMIN_CALIBRATION;
|
||||
uint32_t FUSE_AGING_SENSOR_CALIBRATION;
|
||||
uint32_t FUSE_DEBUG_AUTHENTICATION;
|
||||
uint32_t FUSE_SECURE_PROVISION_INDEX;
|
||||
uint32_t FUSE_SECURE_PROVISION_INFO;
|
||||
uint32_t FUSE_OPT_GPU_DISABLE_CP1;
|
||||
uint32_t FUSE_SPARE_ENDIS;
|
||||
uint32_t FUSE_ECO_RESERVE_0;
|
||||
uint32_t _0x1FC;
|
||||
uint32_t _0x200;
|
||||
uint32_t FUSE_RESERVED_CALIB;
|
||||
uint32_t _0x208;
|
||||
uint32_t _0x20C;
|
||||
uint32_t _0x210;
|
||||
uint32_t _0x214;
|
||||
uint32_t _0x218;
|
||||
uint32_t FUSE_TSENSOR_9;
|
||||
uint32_t _0x220;
|
||||
uint32_t _0x224;
|
||||
uint32_t _0x228;
|
||||
uint32_t _0x22C;
|
||||
uint32_t _0x230;
|
||||
uint32_t _0x234;
|
||||
uint32_t _0x238;
|
||||
uint32_t _0x23C;
|
||||
uint32_t _0x240;
|
||||
uint32_t _0x244;
|
||||
uint32_t _0x248;
|
||||
uint32_t _0x24C;
|
||||
uint32_t FUSE_RESERVED_CALIB0;
|
||||
uint32_t FUSE_RESERVED_CALIB1;
|
||||
uint32_t FUSE_OPT_GPU_TPC0_DISABLE;
|
||||
uint32_t FUSE_OPT_GPU_TPC0_DISABLE_CP1;
|
||||
uint32_t FUSE_OPT_CPU_DISABLE;
|
||||
uint32_t FUSE_OPT_CPU_DISABLE_CP1;
|
||||
uint32_t FUSE_TSENSOR10_CALIB;
|
||||
uint32_t FUSE_TSENSOR10_CALIB_AUX;
|
||||
uint32_t FUSE_OPT_RAM_SVOP_DP;
|
||||
uint32_t FUSE_OPT_RAM_SVOP_PDP;
|
||||
uint32_t FUSE_OPT_RAM_SVOP_REG;
|
||||
uint32_t FUSE_OPT_RAM_SVOP_SP;
|
||||
uint32_t FUSE_OPT_RAM_SVOP_SMPDP;
|
||||
uint32_t FUSE_OPT_GPU_TPC0_DISABLE_CP2;
|
||||
uint32_t FUSE_OPT_GPU_TPC1_DISABLE;
|
||||
uint32_t FUSE_OPT_GPU_TPC1_DISABLE_CP1;
|
||||
uint32_t FUSE_OPT_GPU_TPC1_DISABLE_CP2;
|
||||
uint32_t FUSE_OPT_CPU_DISABLE_CP2;
|
||||
uint32_t FUSE_OPT_GPU_DISABLE_CP2;
|
||||
uint32_t FUSE_USB_CALIB_EXT;
|
||||
uint32_t _0x254;
|
||||
uint32_t _0x258;
|
||||
uint32_t FUSE_RESERVED_FIELD;
|
||||
uint32_t FUSE_OPT_ECC_EN;
|
||||
uint32_t _0x25C;
|
||||
uint32_t _0x260;
|
||||
uint32_t _0x264;
|
||||
@@ -179,12 +192,12 @@ typedef struct {
|
||||
uint32_t _0x270;
|
||||
uint32_t _0x274;
|
||||
uint32_t _0x278;
|
||||
uint32_t _0x27C;
|
||||
uint32_t FUSE_SPARE_REALIGNMENT_REG;
|
||||
uint32_t FUSE_SPARE_BIT[0x20];
|
||||
} fuse_chip_registers_t;
|
||||
} tegra_fuse_chip_t;
|
||||
|
||||
#define FUSE_REGS ((volatile fuse_registers_t *)(0x7000F800))
|
||||
#define FUSE_CHIP_REGS ((volatile fuse_chip_registers_t *)(0x7000F900))
|
||||
#define FUSE_REGS ((volatile tegra_fuse_t *)(0x7000F800))
|
||||
#define FUSE_CHIP_REGS ((volatile tegra_fuse_chip_t *)(0x7000F900))
|
||||
|
||||
#define MAKE_FUSE_REG(n) MAKE_REG32(0x7000F800 + n)
|
||||
|
||||
@@ -194,9 +207,7 @@ typedef struct {
|
||||
} fuse_bypass_data_t;
|
||||
|
||||
bool fuse_check_downgrade_status(void);
|
||||
|
||||
void fuse_configure_fuse_bypass(void);
|
||||
|
||||
void fuse_disable_programming(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -23,26 +23,26 @@
|
||||
#include "pmc.h"
|
||||
|
||||
void misc_configure_device_dbg_settings(void) {
|
||||
/* Enable RTCK daisychaining by setting TBE bit. */
|
||||
/* Set APB_MISC_PP_CONFIG_CTL_TBE (enables RTCK daisy-chaining). */
|
||||
APB_MISC_PP_CONFIG_CTL_0 = 0x80;
|
||||
|
||||
/* Literally none of this is documented in the TRM, lol. */
|
||||
/* Configure JTAG and debug bits. */
|
||||
if (FUSE_CHIP_REGS->FUSE_SECURITY_MODE == 1) {
|
||||
uint32_t secure_boot_val = 0b0100; /* Sets NIDEN for aarch64. */
|
||||
uint32_t misc_val = 0x40;
|
||||
uint32_t secure_boot_val = 0b0100; /* Set NIDEN for aarch64. */
|
||||
uint32_t pp_config_ctl_val = 0x40; /* Set APB_MISC_PP_CONFIG_CTL_JTAG. */
|
||||
if (APBDEV_PMC_STICKY_BITS_0 & 0x40) {
|
||||
misc_val = 0x0;
|
||||
pp_config_ctl_val = 0x0;
|
||||
} else {
|
||||
secure_boot_val = 0b1101; /* Sets SPNIDEN, NIDEN, DBGEN for aarch64. */
|
||||
secure_boot_val = 0b1101; /* Set SPNIDEN, NIDEN, DBGEN for aarch64. */
|
||||
}
|
||||
SB_PFCFG_0 = (SB_PFCFG_0 & ~0b1111) | secure_boot_val; /* Configures debug bits. */
|
||||
APB_MISC_PP_CONFIG_CTL_0 |= misc_val; /* Undocumented, seems to control invasive debugging/JTAG. */
|
||||
SB_PFCFG_0 = (SB_PFCFG_0 & ~0b1111) | secure_boot_val; /* Configure debug bits. */
|
||||
APB_MISC_PP_CONFIG_CTL_0 |= pp_config_ctl_val; /* Configure JTAG. */
|
||||
}
|
||||
|
||||
/* Set sticky bits based SECURITY_MODE. */
|
||||
/* Set HDA_LPBK_DIS if FUSE_SECURITY_MODE is set (disables HDA codec loopback). */
|
||||
APBDEV_PMC_STICKY_BITS_0 |= FUSE_CHIP_REGS->FUSE_SECURITY_MODE;
|
||||
|
||||
/* Set E_INPUT in PINMUX_AUX_GPIO_PA6_0 */
|
||||
/* Set E_INPUT in PINMUX_AUX_GPIO_PA6_0 (needed by the XUSB and SATA controllers). */
|
||||
PINMUX_AUX_GPIO_PA6_0 |= 0x40;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,17 +26,14 @@
|
||||
#define MAKE_MISC_REG(n) MAKE_REG32(MISC_BASE + n)
|
||||
|
||||
#define APB_MISC_PP_CONFIG_CTL_0 MAKE_MISC_REG(0x024)
|
||||
|
||||
#define APB_MISC_GP_ASDBGREG_0 MAKE_MISC_REG(0x810)
|
||||
|
||||
#define PINMUX_AUX_PWR_I2C_SCL_0 MAKE_MISC_REG(0x30DC)
|
||||
#define PINMUX_AUX_PWR_I2C_SDA_0 MAKE_MISC_REG(0x30E0)
|
||||
#define PINMUX_AUX_DVFS_PWM_0 MAKE_MISC_REG(0x3184)
|
||||
|
||||
#define PINMUX_AUX_GPIO_PA6_0 MAKE_MISC_REG(0x3244)
|
||||
|
||||
void misc_configure_device_dbg_settings(void);
|
||||
|
||||
void misc_restore_ram_svop(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -23,47 +23,35 @@
|
||||
|
||||
#define MAKE_PMC_REG(ofs) (MAKE_REG32(PMC_BASE + ofs))
|
||||
|
||||
#define APBDEV_PMC_CNTRL_0 MAKE_PMC_REG(0x000)
|
||||
|
||||
#define APBDEV_PMC_DPD_SAMPLE_0 MAKE_PMC_REG(0x020)
|
||||
|
||||
#define APBDEV_PMC_DPD_ENABLE_0 MAKE_PMC_REG(0x024)
|
||||
|
||||
#define APBDEV_PMC_CLAMP_STATUS_0 MAKE_PMC_REG(0x02C)
|
||||
|
||||
#define APBDEV_PMC_PWRGATE_TOGGLE_0 MAKE_PMC_REG(0x030)
|
||||
#define APBDEV_PMC_REMOVE_CLAMPING_CMD_0 MAKE_PMC_REG(0x034)
|
||||
#define APBDEV_PMC_PWRGATE_STATUS_0 MAKE_PMC_REG(0x038)
|
||||
|
||||
#define APBDEV_PMC_SCRATCH12_0 MAKE_PMC_REG(0x080)
|
||||
#define APBDEV_PMC_SCRATCH13_0 MAKE_PMC_REG(0x084)
|
||||
#define APBDEV_PMC_SCRATCH18_0 MAKE_PMC_REG(0x098)
|
||||
#define APBDEV_PMC_SCRATCH190_0 MAKE_PMC_REG(0x818)
|
||||
|
||||
#define APBDEV_PMC_OSC_EDPD_OVER_0 MAKE_PMC_REG(0x1A4)
|
||||
|
||||
#define APBDEV_PMC_STICKY_BITS_0 MAKE_PMC_REG(0x2C0)
|
||||
#define APBDEV_PMC_SEC_DISABLE2_0 MAKE_PMC_REG(0x2C4)
|
||||
#define APBDEV_PMC_WEAK_BIAS_0 MAKE_PMC_REG(0x2C8)
|
||||
|
||||
#define APBDEV_PMC_SECURE_SCRATCH21_0 MAKE_PMC_REG(0x334)
|
||||
#define APBDEV_PMC_SECURE_SCRATCH32_0 MAKE_PMC_REG(0x360)
|
||||
#define APBDEV_PMC_SECURE_SCRATCH34_0 MAKE_PMC_REG(0x368)
|
||||
#define APBDEV_PMC_SECURE_SCRATCH35_0 MAKE_PMC_REG(0x36C)
|
||||
|
||||
#define APBDEV_PMC_SECURE_SCRATCH112_0 MAKE_PMC_REG(0xB18)
|
||||
#define APBDEV_PMC_SECURE_SCRATCH113_0 MAKE_PMC_REG(0xB1C)
|
||||
#define APBDEV_PMC_SECURE_SCRATCH114_0 MAKE_PMC_REG(0xB20)
|
||||
#define APBDEV_PMC_SECURE_SCRATCH115_0 MAKE_PMC_REG(0xB24)
|
||||
|
||||
#define APBDEV_PMC_IO_DPD3_REQ_0 MAKE_PMC_REG(0x45C)
|
||||
#define APBDEV_PMC_IO_DPD3_STATUS_0 MAKE_PMC_REG(0x460)
|
||||
|
||||
#define APBDEV_PMC_IO_DPD4_REQ_0 MAKE_PMC_REG(0x464)
|
||||
#define APBDEV_PMC_IO_DPD4_STATUS_0 MAKE_PMC_REG(0x468)
|
||||
|
||||
#define APBDEV_PMC_SET_SW_CLAMP_0 MAKE_PMC_REG(0x47C)
|
||||
|
||||
#define APBDEV_PMC_DDR_CNTRL_0 MAKE_PMC_REG(0x4E4)
|
||||
#define APBDEV_PMC_CNTRL_0 MAKE_PMC_REG(0x000)
|
||||
#define APBDEV_PMC_DPD_SAMPLE_0 MAKE_PMC_REG(0x020)
|
||||
#define APBDEV_PMC_DPD_ENABLE_0 MAKE_PMC_REG(0x024)
|
||||
#define APBDEV_PMC_CLAMP_STATUS_0 MAKE_PMC_REG(0x02C)
|
||||
#define APBDEV_PMC_PWRGATE_TOGGLE_0 MAKE_PMC_REG(0x030)
|
||||
#define APBDEV_PMC_REMOVE_CLAMPING_CMD_0 MAKE_PMC_REG(0x034)
|
||||
#define APBDEV_PMC_PWRGATE_STATUS_0 MAKE_PMC_REG(0x038)
|
||||
#define APBDEV_PMC_SCRATCH12_0 MAKE_PMC_REG(0x080)
|
||||
#define APBDEV_PMC_SCRATCH13_0 MAKE_PMC_REG(0x084)
|
||||
#define APBDEV_PMC_SCRATCH18_0 MAKE_PMC_REG(0x098)
|
||||
#define APBDEV_PMC_SCRATCH190_0 MAKE_PMC_REG(0x818)
|
||||
#define APBDEV_PMC_OSC_EDPD_OVER_0 MAKE_PMC_REG(0x1A4)
|
||||
#define APBDEV_PMC_STICKY_BITS_0 MAKE_PMC_REG(0x2C0)
|
||||
#define APBDEV_PMC_SEC_DISABLE2_0 MAKE_PMC_REG(0x2C4)
|
||||
#define APBDEV_PMC_WEAK_BIAS_0 MAKE_PMC_REG(0x2C8)
|
||||
#define APBDEV_PMC_SECURE_SCRATCH21_0 MAKE_PMC_REG(0x334)
|
||||
#define APBDEV_PMC_SECURE_SCRATCH32_0 MAKE_PMC_REG(0x360)
|
||||
#define APBDEV_PMC_SECURE_SCRATCH34_0 MAKE_PMC_REG(0x368)
|
||||
#define APBDEV_PMC_SECURE_SCRATCH35_0 MAKE_PMC_REG(0x36C)
|
||||
#define APBDEV_PMC_SECURE_SCRATCH112_0 MAKE_PMC_REG(0xB18)
|
||||
#define APBDEV_PMC_SECURE_SCRATCH113_0 MAKE_PMC_REG(0xB1C)
|
||||
#define APBDEV_PMC_SECURE_SCRATCH114_0 MAKE_PMC_REG(0xB20)
|
||||
#define APBDEV_PMC_SECURE_SCRATCH115_0 MAKE_PMC_REG(0xB24)
|
||||
#define APBDEV_PMC_FUSE_CTRL MAKE_PMC_REG(0x450)
|
||||
#define APBDEV_PMC_IO_DPD3_REQ_0 MAKE_PMC_REG(0x45C)
|
||||
#define APBDEV_PMC_IO_DPD3_STATUS_0 MAKE_PMC_REG(0x460)
|
||||
#define APBDEV_PMC_IO_DPD4_REQ_0 MAKE_PMC_REG(0x464)
|
||||
#define APBDEV_PMC_IO_DPD4_STATUS_0 MAKE_PMC_REG(0x468)
|
||||
#define APBDEV_PMC_SET_SW_CLAMP_0 MAKE_PMC_REG(0x47C)
|
||||
#define APBDEV_PMC_DDR_CNTRL_0 MAKE_PMC_REG(0x4E4)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -36,20 +36,20 @@ static void __attribute__((__noinline__)) ll_init(volatile se_ll_t *ll, void *bu
|
||||
}
|
||||
|
||||
void se_check_error_status_reg(void) {
|
||||
if (se_get_regs()->ERR_STATUS_REG) {
|
||||
if (se_get_regs()->SE_ERR_STATUS) {
|
||||
reboot();
|
||||
}
|
||||
}
|
||||
|
||||
void se_check_for_error(void) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
if (se->INT_STATUS_REG & 0x10000 || se->FLAGS_REG & 3 || se->ERR_STATUS_REG) {
|
||||
if (se->SE_INT_STATUS & 0x10000 || se->SE_STATUS & 3 || se->SE_ERR_STATUS) {
|
||||
reboot();
|
||||
}
|
||||
}
|
||||
|
||||
void se_verify_flags_cleared(void) {
|
||||
if (se_get_regs()->FLAGS_REG & 3) {
|
||||
if (se_get_regs()->SE_STATUS & 3) {
|
||||
reboot();
|
||||
}
|
||||
}
|
||||
@@ -63,8 +63,8 @@ void clear_aes_keyslot(unsigned int keyslot) {
|
||||
|
||||
/* Zero out the whole keyslot and IV. */
|
||||
for (unsigned int i = 0; i < 0x10; i++) {
|
||||
se->AES_KEYTABLE_ADDR = (keyslot << 4) | i;
|
||||
se->AES_KEYTABLE_DATA = 0;
|
||||
se->SE_CRYPTO_KEYTABLE_ADDR = (keyslot << 4) | i;
|
||||
se->SE_CRYPTO_KEYTABLE_DATA = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,13 +78,13 @@ void clear_rsa_keyslot(unsigned int keyslot) {
|
||||
/* Zero out the whole keyslot. */
|
||||
for (unsigned int i = 0; i < 0x40; i++) {
|
||||
/* Select Keyslot Modulus[i] */
|
||||
se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i | 0x40;
|
||||
se->RSA_KEYTABLE_DATA = 0;
|
||||
se->SE_RSA_KEYTABLE_ADDR = (keyslot << 7) | i | 0x40;
|
||||
se->SE_RSA_KEYTABLE_DATA = 0;
|
||||
}
|
||||
for (unsigned int i = 0; i < 0x40; i++) {
|
||||
/* Select Keyslot Expontent[i] */
|
||||
se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i;
|
||||
se->RSA_KEYTABLE_DATA = 0;
|
||||
se->SE_RSA_KEYTABLE_ADDR = (keyslot << 7) | i;
|
||||
se->SE_RSA_KEYTABLE_DATA = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,8 +96,8 @@ void clear_aes_keyslot_iv(unsigned int keyslot) {
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < (0x10 >> 2); i++) {
|
||||
se->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i;
|
||||
se->AES_KEYTABLE_DATA = 0;
|
||||
se->SE_CRYPTO_KEYTABLE_ADDR = (keyslot << 4) | 8 | i;
|
||||
se->SE_CRYPTO_KEYTABLE_DATA = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,15 +111,15 @@ void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const v
|
||||
ll_init(&out_ll, dst, dst_size);
|
||||
|
||||
/* Set the LLs. */
|
||||
se->IN_LL_ADDR_REG = (uint32_t)(&in_ll);
|
||||
se->OUT_LL_ADDR_REG = (uint32_t) (&out_ll);
|
||||
se->SE_IN_LL_ADDR = (uint32_t)(&in_ll);
|
||||
se->SE_OUT_LL_ADDR = (uint32_t) (&out_ll);
|
||||
|
||||
/* Set registers for operation. */
|
||||
se->ERR_STATUS_REG = se->ERR_STATUS_REG;
|
||||
se->INT_STATUS_REG = se->INT_STATUS_REG;
|
||||
se->OPERATION_REG = op;
|
||||
se->SE_ERR_STATUS = se->SE_ERR_STATUS;
|
||||
se->SE_INT_STATUS = se->SE_INT_STATUS;
|
||||
se->SE_OPERATION = op;
|
||||
|
||||
while (!(se->INT_STATUS_REG & 0x10)) { /* Wait a while */ }
|
||||
while (!(se->SE_INT_STATUS & 0x10)) { /* Wait a while */ }
|
||||
se_check_for_error();
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src,
|
||||
}
|
||||
|
||||
/* Trigger AES operation. */
|
||||
se_get_regs()->BLOCK_COUNT_REG = 0;
|
||||
se_get_regs()->SE_CRYPTO_LAST_BLOCK = 0;
|
||||
trigger_se_blocking_op(OP_START, block, sizeof(block), block, sizeof(block));
|
||||
|
||||
/* Copy output data into dst. */
|
||||
@@ -154,8 +154,8 @@ void se_aes_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size,
|
||||
}
|
||||
|
||||
/* Set configuration high (256-bit vs 128-bit) based on parameter. */
|
||||
se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY) | (config_high << 16);
|
||||
se->CRYPTO_REG = keyslot << 24 | 0x100;
|
||||
se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY) | (config_high << 16);
|
||||
se->SE_CRYPTO_CONFIG = keyslot << 24 | 0x100;
|
||||
se_perform_aes_block_operation(dst, 0x10, src, 0x10);
|
||||
}
|
||||
|
||||
@@ -166,8 +166,8 @@ void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size,
|
||||
reboot();
|
||||
}
|
||||
|
||||
se->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY);
|
||||
se->CRYPTO_REG = keyslot << 24;
|
||||
se->SE_CONFIG = (ALG_AES_DEC | DST_MEMORY);
|
||||
se->SE_CRYPTO_CONFIG = keyslot << 24;
|
||||
se_perform_aes_block_operation(dst, 0x10, src, 0x10);
|
||||
}
|
||||
|
||||
@@ -198,16 +198,16 @@ void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, con
|
||||
shift_left_xor_rb(derived_key);
|
||||
}
|
||||
|
||||
se->CONFIG_REG = (ALG_AES_ENC | DST_HASHREG) | (config_high << 16);
|
||||
se->CRYPTO_REG = (keyslot << 24) | (0x145);
|
||||
se->SE_CONFIG = (ALG_AES_ENC | DST_HASHREG) | (config_high << 16);
|
||||
se->SE_CRYPTO_CONFIG = (keyslot << 24) | (0x145);
|
||||
clear_aes_keyslot_iv(keyslot);
|
||||
|
||||
unsigned int num_blocks = (data_size + 0xF) >> 4;
|
||||
/* Handle aligned blocks. */
|
||||
if (num_blocks > 1) {
|
||||
se->BLOCK_COUNT_REG = num_blocks - 2;
|
||||
se->SE_CRYPTO_LAST_BLOCK = num_blocks - 2;
|
||||
trigger_se_blocking_op(OP_START, NULL, 0, data, data_size);
|
||||
se->CRYPTO_REG |= 0x80;
|
||||
se->SE_CRYPTO_CONFIG |= 0x80;
|
||||
}
|
||||
|
||||
/* Create final block. */
|
||||
@@ -224,12 +224,12 @@ void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, con
|
||||
}
|
||||
|
||||
/* Perform last operation. */
|
||||
se->BLOCK_COUNT_REG = 0;
|
||||
se->SE_CRYPTO_LAST_BLOCK = 0;
|
||||
trigger_se_blocking_op(OP_START, NULL, 0, last_block, sizeof(last_block));
|
||||
|
||||
/* Copy output CMAC. */
|
||||
for (unsigned int i = 0; i < (cmac_size >> 2); i++) {
|
||||
((uint32_t *)cmac)[i] = ((volatile uint32_t *)se->HASH_RESULT_REG)[i];
|
||||
((uint32_t *)cmac)[i] = ((volatile uint32_t *)se->SE_HASH_RESULT)[i];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,9 +244,9 @@ void se_aes_256_cbc_decrypt(unsigned int keyslot, void *dst, size_t dst_size, co
|
||||
reboot();
|
||||
}
|
||||
|
||||
se->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY) | (0x202 << 16);
|
||||
se->CRYPTO_REG = (keyslot << 24) | 0x66;
|
||||
se->SE_CONFIG = (ALG_AES_DEC | DST_MEMORY) | (0x202 << 16);
|
||||
se->SE_CRYPTO_CONFIG = (keyslot << 24) | 0x66;
|
||||
clear_aes_keyslot_iv(keyslot);
|
||||
se->BLOCK_COUNT_REG = (src_size >> 4) - 1;
|
||||
se->SE_CRYPTO_LAST_BLOCK = (src_size >> 4) - 1;
|
||||
trigger_se_blocking_op(OP_START, dst, dst_size, src, src_size);
|
||||
}
|
||||
@@ -92,71 +92,59 @@
|
||||
#define RSA_2048_BYTES 0x100
|
||||
|
||||
typedef struct {
|
||||
uint32_t _0x0;
|
||||
uint32_t _0x4;
|
||||
uint32_t OPERATION_REG;
|
||||
uint32_t INT_ENABLE_REG;
|
||||
uint32_t INT_STATUS_REG;
|
||||
uint32_t CONFIG_REG;
|
||||
uint32_t IN_LL_ADDR_REG;
|
||||
uint32_t _0x1C;
|
||||
uint32_t _0x20;
|
||||
uint32_t OUT_LL_ADDR_REG;
|
||||
uint32_t _0x28;
|
||||
uint32_t _0x2C;
|
||||
uint8_t HASH_RESULT_REG[0x20];
|
||||
uint8_t _0x50[0x20];
|
||||
uint32_t CONTEXT_SAVE_CONFIG_REG;
|
||||
uint8_t _0x74[0x18C];
|
||||
uint32_t SHA_CONFIG_REG;
|
||||
uint32_t SHA_MSG_LENGTH_REG;
|
||||
uint32_t _0x208;
|
||||
uint32_t _0x20C;
|
||||
uint32_t _0x210;
|
||||
uint32_t SHA_MSG_LEFT_REG;
|
||||
uint32_t _0x218;
|
||||
uint32_t _0x21C;
|
||||
uint32_t _0x220;
|
||||
uint32_t _0x224;
|
||||
uint8_t _0x228[0x58];
|
||||
uint32_t AES_KEY_READ_DISABLE_REG;
|
||||
uint32_t AES_KEYSLOT_FLAGS[0x10];
|
||||
uint8_t _0x2C4[0x3C];
|
||||
uint32_t _0x300;
|
||||
uint32_t CRYPTO_REG;
|
||||
uint32_t CRYPTO_CTR_REG[4];
|
||||
uint32_t BLOCK_COUNT_REG;
|
||||
uint32_t AES_KEYTABLE_ADDR;
|
||||
uint32_t AES_KEYTABLE_DATA;
|
||||
uint32_t _0x324;
|
||||
uint32_t _0x328;
|
||||
uint32_t _0x32C;
|
||||
uint32_t CRYPTO_KEYTABLE_DST_REG;
|
||||
uint8_t _0x334[0xC];
|
||||
uint32_t RNG_CONFIG_REG;
|
||||
uint32_t RNG_SRC_CONFIG_REG;
|
||||
uint32_t RNG_RESEED_INTERVAL_REG;
|
||||
uint8_t _0x34C[0xB4];
|
||||
uint32_t RSA_CONFIG;
|
||||
uint32_t RSA_KEY_SIZE_REG;
|
||||
uint32_t RSA_EXP_SIZE_REG;
|
||||
uint32_t RSA_KEY_READ_DISABLE_REG;
|
||||
uint32_t RSA_KEYSLOT_FLAGS[2];
|
||||
uint32_t _0x418;
|
||||
uint32_t _0x41C;
|
||||
uint32_t RSA_KEYTABLE_ADDR;
|
||||
uint32_t RSA_KEYTABLE_DATA;
|
||||
uint8_t RSA_OUTPUT[0x100];
|
||||
uint8_t _0x528[0x2D8];
|
||||
uint32_t FLAGS_REG;
|
||||
uint32_t ERR_STATUS_REG;
|
||||
uint32_t _0x808;
|
||||
uint32_t SPARE_0;
|
||||
uint32_t _0x810;
|
||||
uint32_t SE_SE_SECURITY;
|
||||
uint32_t SE_TZRAM_SECURITY;
|
||||
uint32_t SE_OPERATION;
|
||||
uint32_t SE_INT_ENABLE;
|
||||
uint32_t SE_INT_STATUS;
|
||||
uint32_t SE_CONFIG;
|
||||
uint32_t SE_IN_LL_ADDR;
|
||||
uint32_t SE_IN_CUR_BYTE_ADDR;
|
||||
uint32_t SE_IN_CUR_LL_ID;
|
||||
uint32_t SE_OUT_LL_ADDR;
|
||||
uint32_t SE_OUT_CUR_BYTE_ADDR;
|
||||
uint32_t SE_OUT_CUR_LL_ID;
|
||||
uint32_t SE_HASH_RESULT[0x10];
|
||||
uint32_t SE_CTX_SAVE_CONFIG;
|
||||
uint32_t _0x74[0x63];
|
||||
uint32_t SE_SHA_CONFIG;
|
||||
uint32_t SE_SHA_MSG_LENGTH[0x4];
|
||||
uint32_t SE_SHA_MSG_LEFT[0x4];
|
||||
uint32_t _0x224[0x17];
|
||||
uint32_t SE_CRYPTO_SECURITY_PERKEY;
|
||||
uint32_t SE_CRYPTO_KEYTABLE_ACCESS[0x10];
|
||||
uint32_t _0x2C4[0x10];
|
||||
uint32_t SE_CRYPTO_CONFIG;
|
||||
uint32_t SE_CRYPTO_LINEAR_CTR[0x4];
|
||||
uint32_t SE_CRYPTO_LAST_BLOCK;
|
||||
uint32_t SE_CRYPTO_KEYTABLE_ADDR;
|
||||
uint32_t SE_CRYPTO_KEYTABLE_DATA;
|
||||
uint32_t _0x324[0x3];
|
||||
uint32_t SE_CRYPTO_KEYTABLE_DST;
|
||||
uint32_t _0x334[0x3];
|
||||
uint32_t SE_RNG_CONFIG;
|
||||
uint32_t SE_RNG_SRC_CONFIG;
|
||||
uint32_t SE_RNG_RESEED_INTERVAL;
|
||||
uint32_t _0x34C[0x2D];
|
||||
uint32_t SE_RSA_CONFIG;
|
||||
uint32_t SE_RSA_KEY_SIZE;
|
||||
uint32_t SE_RSA_EXP_SIZE;
|
||||
uint32_t SE_RSA_SECURITY_PERKEY;
|
||||
uint32_t SE_RSA_KEYTABLE_ACCESS[0x2];
|
||||
uint32_t _0x418[0x2];
|
||||
uint32_t SE_RSA_KEYTABLE_ADDR;
|
||||
uint32_t SE_RSA_KEYTABLE_DATA;
|
||||
uint32_t SE_RSA_OUTPUT[0x40];
|
||||
uint32_t _0x528[0xB6];
|
||||
uint32_t SE_STATUS;
|
||||
uint32_t SE_ERR_STATUS;
|
||||
uint32_t SE_MISC;
|
||||
uint32_t SE_SPARE;
|
||||
uint32_t SE_ENTROPY_DEBUG_COUNTER;
|
||||
uint32_t _0x814;
|
||||
uint32_t _0x818;
|
||||
uint32_t _0x81C;
|
||||
uint8_t _0x820[0x17E0];
|
||||
uint32_t _0x820[0x5F8];
|
||||
} tegra_se_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -46,7 +46,7 @@ void secmon_restore_to_tzram(const uint32_t target_firmware) {
|
||||
}
|
||||
|
||||
/* Make security engine require secure busmaster. */
|
||||
se_get_regs()->_0x4 = 0;
|
||||
se_get_regs()->SE_TZRAM_SECURITY = 0;
|
||||
|
||||
/* TODO: se_verify_keys_unreadable(); */
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* 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 <stdint.h>
|
||||
|
||||
#include "utils.h"
|
||||
@@ -30,7 +30,7 @@ static inline uint32_t get_special_clk_reg(CarDevice dev) {
|
||||
case CARDEVICE_BPMP: return 0;
|
||||
default: generic_panic();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t get_special_clk_val(CarDevice dev) {
|
||||
switch (dev) {
|
||||
@@ -45,7 +45,7 @@ static inline uint32_t get_special_clk_val(CarDevice dev) {
|
||||
}
|
||||
|
||||
static uint32_t g_clk_reg_offsets[NUM_CAR_BANKS] = {0x010, 0x014, 0x018, 0x360, 0x364, 0x280, 0x298};
|
||||
static uint32_t g_rst_reg_offsets[NUM_CAR_BANKS] = {0x004, 0x008, 0x00C, 0x358, 0x35C, 0x28C, 0x2A4};
|
||||
static uint32_t g_rst_reg_offsets[NUM_CAR_BANKS] = {0x004, 0x008, 0x00C, 0x358, 0x35C, 0x28C, 0x2A4};
|
||||
|
||||
void clk_enable(CarDevice dev) {
|
||||
uint32_t special_reg;
|
||||
@@ -67,7 +67,6 @@ void rst_disable(CarDevice dev) {
|
||||
MAKE_CAR_REG(g_rst_reg_offsets[dev >> 5]) &= ~(BIT(dev & 0x1F));
|
||||
}
|
||||
|
||||
|
||||
void clkrst_enable(CarDevice dev) {
|
||||
clk_enable(dev);
|
||||
rst_disable(dev);
|
||||
@@ -82,3 +81,7 @@ void clkrst_reboot(CarDevice dev) {
|
||||
clkrst_disable(dev);
|
||||
clkrst_enable(dev);
|
||||
}
|
||||
|
||||
void clkrst_enable_fuse_regs(bool enable) {
|
||||
CLK_RST_CONTROLLER_MISC_CLK_ENB_0 = ((CLK_RST_CONTROLLER_MISC_CLK_ENB_0 & 0xEFFFFFFF) | ((enable & 1) << 28));
|
||||
}
|
||||
@@ -51,7 +51,8 @@ void rst_disable(CarDevice dev);
|
||||
|
||||
void clkrst_enable(CarDevice dev);
|
||||
void clkrst_disable(CarDevice dev);
|
||||
|
||||
void clkrst_reboot(CarDevice dev);
|
||||
|
||||
void clkrst_enable_fuse_regs(bool enable);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -187,11 +187,10 @@ uint32_t configitem_get(bool privileged, ConfigItem item, uint64_t *p_outvalue)
|
||||
*p_outvalue = INTERRUPT_ID_USER_SECURITY_ENGINE;
|
||||
break;
|
||||
case CONFIGITEM_VERSION:
|
||||
/* Always returns maxver - 1 on hardware. */
|
||||
*p_outvalue = PACKAGE2_MAXVER_400_410 - 1;
|
||||
*p_outvalue = fuse_get_expected_fuse_version(exosphere_get_target_firmware());
|
||||
break;
|
||||
case CONFIGITEM_HARDWARETYPE:
|
||||
*p_outvalue = fuse_get_hardware_type();
|
||||
*p_outvalue = fuse_get_hardware_type(exosphere_get_target_firmware());
|
||||
break;
|
||||
case CONFIGITEM_ISRETAIL:
|
||||
*p_outvalue = fuse_get_retail_type();
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Declare the exception vector table, enforcing it is aligned on a
|
||||
@@ -92,7 +92,7 @@ vector_entry fiq_spx
|
||||
vector_entry serror_spx
|
||||
b unknown_exception
|
||||
check_vector_size serror_spx
|
||||
|
||||
|
||||
/* Lower EL, A64 */
|
||||
vector_entry synch_a64
|
||||
stp x29, x30, [sp, #-0x10]!
|
||||
|
||||
@@ -13,185 +13,168 @@
|
||||
* 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 <string.h>
|
||||
#include <vapours/ams_version.h>
|
||||
|
||||
#include "car.h"
|
||||
#include "fuse.h"
|
||||
#include "utils.h"
|
||||
#include "timers.h"
|
||||
#include "exocfg.h"
|
||||
|
||||
#include "masterkey.h"
|
||||
#include "pmc.h"
|
||||
#include "timers.h"
|
||||
|
||||
static bool g_has_checked_for_rcm_bug_patch = false;
|
||||
static bool g_has_rcm_bug_patch = false;
|
||||
|
||||
/* Prototypes for internal commands. */
|
||||
void fuse_make_regs_visible(void);
|
||||
|
||||
void fuse_enable_power(void);
|
||||
void fuse_disable_power(void);
|
||||
void fuse_wait_idle(void);
|
||||
|
||||
/* Initialize the FUSE driver */
|
||||
void fuse_init(void)
|
||||
{
|
||||
fuse_make_regs_visible();
|
||||
fuse_secondary_private_key_disable();
|
||||
/* Initialize the fuse driver */
|
||||
void fuse_init(void) {
|
||||
/* Make all fuse registers visible, disable the private key and disable programming. */
|
||||
clkrst_enable_fuse_regs(true);
|
||||
fuse_disable_private_key();
|
||||
fuse_disable_programming();
|
||||
|
||||
|
||||
/* TODO: Should we allow this to be done later? */
|
||||
if (!g_has_checked_for_rcm_bug_patch) {
|
||||
(void)(fuse_has_rcm_bug_patch());
|
||||
}
|
||||
|
||||
/* TODO: Overrides (iROM patches) and various reads happen here */
|
||||
}
|
||||
|
||||
/* Make all fuse registers visible */
|
||||
void fuse_make_regs_visible(void)
|
||||
{
|
||||
CLK_RST_CONTROLLER_MISC_CLK_ENB_0 |= BIT(28);
|
||||
}
|
||||
|
||||
/* Enable power to the fuse hardware array */
|
||||
void fuse_enable_power(void)
|
||||
{
|
||||
FUSE_REGS->FUSE_PWR_GOOD_SW = 1;
|
||||
wait(1);
|
||||
}
|
||||
|
||||
/* Disable power to the fuse hardware array */
|
||||
void fuse_disable_power(void)
|
||||
{
|
||||
FUSE_REGS->FUSE_PWR_GOOD_SW = 0;
|
||||
wait(1);
|
||||
}
|
||||
|
||||
/* Wait for the fuse driver to go idle */
|
||||
void fuse_wait_idle(void)
|
||||
{
|
||||
uint32_t ctrl_val = 0;
|
||||
|
||||
/* Wait for STATE_IDLE */
|
||||
while ((ctrl_val & (0xF0000)) != 0x40000)
|
||||
{
|
||||
wait(1);
|
||||
ctrl_val = FUSE_REGS->FUSE_CTRL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read a fuse from the hardware array */
|
||||
uint32_t fuse_hw_read(uint32_t addr)
|
||||
{
|
||||
fuse_wait_idle();
|
||||
|
||||
/* Program the target address */
|
||||
FUSE_REGS->FUSE_REG_ADDR = addr;
|
||||
|
||||
/* Enable read operation in control register */
|
||||
uint32_t ctrl_val = FUSE_REGS->FUSE_CTRL;
|
||||
ctrl_val &= ~0x3;
|
||||
ctrl_val |= 0x1; /* Set FUSE_READ command */
|
||||
FUSE_REGS->FUSE_CTRL = ctrl_val;
|
||||
|
||||
fuse_wait_idle();
|
||||
|
||||
return FUSE_REGS->FUSE_REG_READ;
|
||||
}
|
||||
|
||||
/* Write a fuse in the hardware array */
|
||||
void fuse_hw_write(uint32_t value, uint32_t addr)
|
||||
{
|
||||
fuse_wait_idle();
|
||||
|
||||
/* Program the target address and value */
|
||||
FUSE_REGS->FUSE_REG_ADDR = addr;
|
||||
FUSE_REGS->FUSE_REG_WRITE = value;
|
||||
|
||||
/* Enable write operation in control register */
|
||||
uint32_t ctrl_val = FUSE_REGS->FUSE_CTRL;
|
||||
ctrl_val &= ~0x3;
|
||||
ctrl_val |= 0x2; /* Set FUSE_WRITE command */
|
||||
FUSE_REGS->FUSE_CTRL = ctrl_val;
|
||||
|
||||
fuse_wait_idle();
|
||||
}
|
||||
|
||||
/* Sense the fuse hardware array into the shadow cache */
|
||||
void fuse_hw_sense(void)
|
||||
{
|
||||
fuse_wait_idle();
|
||||
|
||||
/* Enable sense operation in control register */
|
||||
uint32_t ctrl_val = FUSE_REGS->FUSE_CTRL;
|
||||
ctrl_val &= ~0x3;
|
||||
ctrl_val |= 0x3; /* Set FUSE_SENSE command */
|
||||
FUSE_REGS->FUSE_CTRL = ctrl_val;
|
||||
|
||||
fuse_wait_idle();
|
||||
/* Disable access to the private key and set the TZ sticky bit. */
|
||||
void fuse_disable_private_key(void) {
|
||||
FUSE_REGS->FUSE_PRIVATEKEYDISABLE = 0x10;
|
||||
}
|
||||
|
||||
/* Disables all fuse programming. */
|
||||
void fuse_disable_programming(void) {
|
||||
FUSE_REGS->FUSE_DIS_PGM = 1;
|
||||
FUSE_REGS->FUSE_DISABLEREGPROGRAM = 1;
|
||||
}
|
||||
|
||||
/* Unknown exactly what this does, but it alters the contents read from the fuse cache. */
|
||||
void fuse_secondary_private_key_disable(void) {
|
||||
FUSE_REGS->FUSE_PRIVATEKEYDISABLE = 0x10;
|
||||
/* Enable power to the fuse hardware array. */
|
||||
void fuse_enable_power(void) {
|
||||
APBDEV_PMC_FUSE_CTRL &= ~(0x200); /* Clear PMC_FUSE_CTRL_PS18_LATCH_CLEAR. */
|
||||
mdelay(1);
|
||||
APBDEV_PMC_FUSE_CTRL |= 0x100; /* Set PMC_FUSE_CTRL_PS18_LATCH_SET. */
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
/* Disable power to the fuse hardware array. */
|
||||
void fuse_disable_power(void) {
|
||||
APBDEV_PMC_FUSE_CTRL &= ~(0x100); /* Clear PMC_FUSE_CTRL_PS18_LATCH_SET. */
|
||||
mdelay(1);
|
||||
APBDEV_PMC_FUSE_CTRL |= 0x200; /* Set PMC_FUSE_CTRL_PS18_LATCH_CLEAR. */
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
/* Read the SKU info register from the shadow cache */
|
||||
uint32_t fuse_get_sku_info(void)
|
||||
{
|
||||
/* Wait for the fuse driver to go idle. */
|
||||
void fuse_wait_idle(void) {
|
||||
uint32_t ctrl_val = 0;
|
||||
|
||||
/* Wait for STATE_IDLE */
|
||||
while ((ctrl_val & (0xF0000)) != 0x40000)
|
||||
ctrl_val = FUSE_REGS->FUSE_FUSECTRL;
|
||||
}
|
||||
|
||||
/* Read a fuse from the hardware array. */
|
||||
uint32_t fuse_hw_read(uint32_t addr) {
|
||||
/* Wait for idle state. */
|
||||
fuse_wait_idle();
|
||||
|
||||
/* Program the target address. */
|
||||
FUSE_REGS->FUSE_FUSEADDR = addr;
|
||||
|
||||
/* Enable read operation in control register. */
|
||||
uint32_t ctrl_val = FUSE_REGS->FUSE_FUSECTRL;
|
||||
ctrl_val &= ~0x3;
|
||||
ctrl_val |= 0x1; /* Set READ command. */
|
||||
FUSE_REGS->FUSE_FUSECTRL = ctrl_val;
|
||||
|
||||
/* Wait for idle state. */
|
||||
fuse_wait_idle();
|
||||
|
||||
return FUSE_REGS->FUSE_FUSERDATA;
|
||||
}
|
||||
|
||||
/* Write a fuse in the hardware array. */
|
||||
void fuse_hw_write(uint32_t value, uint32_t addr) {
|
||||
/* Wait for idle state. */
|
||||
fuse_wait_idle();
|
||||
|
||||
/* Program the target address and value. */
|
||||
FUSE_REGS->FUSE_FUSEADDR = addr;
|
||||
FUSE_REGS->FUSE_FUSEWDATA = value;
|
||||
|
||||
/* Enable write operation in control register. */
|
||||
uint32_t ctrl_val = FUSE_REGS->FUSE_FUSECTRL;
|
||||
ctrl_val &= ~0x3;
|
||||
ctrl_val |= 0x2; /* Set WRITE command. */
|
||||
FUSE_REGS->FUSE_FUSECTRL = ctrl_val;
|
||||
|
||||
/* Wait for idle state. */
|
||||
fuse_wait_idle();
|
||||
}
|
||||
|
||||
/* Sense the fuse hardware array into the shadow cache. */
|
||||
void fuse_hw_sense(void) {
|
||||
/* Wait for idle state. */
|
||||
fuse_wait_idle();
|
||||
|
||||
/* Enable sense operation in control register */
|
||||
uint32_t ctrl_val = FUSE_REGS->FUSE_FUSECTRL;
|
||||
ctrl_val &= ~0x3;
|
||||
ctrl_val |= 0x3; /* Set SENSE_CTRL command */
|
||||
FUSE_REGS->FUSE_FUSECTRL = ctrl_val;
|
||||
|
||||
/* Wait for idle state. */
|
||||
fuse_wait_idle();
|
||||
}
|
||||
|
||||
/* Read the SKU info register from the shadow cache. */
|
||||
uint32_t fuse_get_sku_info(void) {
|
||||
return FUSE_CHIP_REGS->FUSE_SKU_INFO;
|
||||
}
|
||||
|
||||
/* Read the bootrom patch version from a register in the shadow cache */
|
||||
uint32_t fuse_get_bootrom_patch_version(void)
|
||||
{
|
||||
return FUSE_CHIP_REGS->FUSE_SOC_SPEEDO_1;
|
||||
/* Read the bootrom patch version from a register in the shadow cache. */
|
||||
uint32_t fuse_get_bootrom_patch_version(void) {
|
||||
return FUSE_CHIP_REGS->FUSE_SOC_SPEEDO_1_CALIB;
|
||||
}
|
||||
|
||||
/* Read a spare bit register from the shadow cache */
|
||||
uint32_t fuse_get_spare_bit(uint32_t idx)
|
||||
{
|
||||
if (idx >= 32) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return FUSE_CHIP_REGS->FUSE_SPARE_BIT[idx];
|
||||
}
|
||||
|
||||
/* Read a reserved ODM register from the shadow cache */
|
||||
uint32_t fuse_get_reserved_odm(uint32_t idx)
|
||||
{
|
||||
if (idx >= 8) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return FUSE_CHIP_REGS->FUSE_RESERVED_ODM[idx];
|
||||
}
|
||||
|
||||
uint32_t fuse_get_5x_key_generation(void) {
|
||||
if ((fuse_get_reserved_odm(4) & 0x800) && fuse_get_reserved_odm(0) == 0x8E61ECAE && fuse_get_reserved_odm(1) == 0xF2BA3BB2) {
|
||||
return fuse_get_reserved_odm(2) & 0x1F;
|
||||
uint32_t fuse_get_spare_bit(uint32_t idx) {
|
||||
if (idx < 32) {
|
||||
return FUSE_CHIP_REGS->FUSE_SPARE_BIT[idx];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Derive the Device ID using values in the shadow cache */
|
||||
/* Read a reserved ODM register from the shadow cache. */
|
||||
uint32_t fuse_get_reserved_odm(uint32_t idx) {
|
||||
if (idx < 8) {
|
||||
return FUSE_CHIP_REGS->FUSE_RESERVED_ODM[idx];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the DRAM ID using values in the shadow cache. */
|
||||
uint32_t fuse_get_dram_id(void) {
|
||||
return ((fuse_get_reserved_odm(4) >> 3) & 0x7);
|
||||
}
|
||||
|
||||
/* Derive the Device ID using values in the shadow cache. */
|
||||
uint64_t fuse_get_device_id(void) {
|
||||
uint64_t device_id = 0;
|
||||
uint64_t y_coord = FUSE_CHIP_REGS->FUSE_Y_COORDINATE & 0x1FF;
|
||||
uint64_t x_coord = FUSE_CHIP_REGS->FUSE_X_COORDINATE & 0x1FF;
|
||||
uint64_t wafer_id = FUSE_CHIP_REGS->FUSE_WAFER_ID & 0x3F;
|
||||
uint32_t lot_code = FUSE_CHIP_REGS->FUSE_LOT_CODE_0;
|
||||
uint64_t fab_code = FUSE_CHIP_REGS->FUSE_FAB_CODE & 0x3F;
|
||||
uint64_t y_coord = FUSE_CHIP_REGS->FUSE_OPT_Y_COORDINATE & 0x1FF;
|
||||
uint64_t x_coord = FUSE_CHIP_REGS->FUSE_OPT_X_COORDINATE & 0x1FF;
|
||||
uint64_t wafer_id = FUSE_CHIP_REGS->FUSE_OPT_WAFER_ID & 0x3F;
|
||||
uint32_t lot_code = FUSE_CHIP_REGS->FUSE_OPT_LOT_CODE_0;
|
||||
uint64_t fab_code = FUSE_CHIP_REGS->FUSE_OPT_FAB_CODE & 0x3F;
|
||||
|
||||
uint64_t derived_lot_code = 0;
|
||||
for (unsigned int i = 0; i < 5; i++) {
|
||||
derived_lot_code = (derived_lot_code * 0x24) + ((lot_code >> (24 - 6*i)) & 0x3F);
|
||||
@@ -203,40 +186,41 @@ uint64_t fuse_get_device_id(void) {
|
||||
device_id |= wafer_id << 18;
|
||||
device_id |= derived_lot_code << 24;
|
||||
device_id |= fab_code << 50;
|
||||
|
||||
return device_id;
|
||||
}
|
||||
|
||||
/* Get the DRAM ID using values in the shadow cache */
|
||||
uint32_t fuse_get_dram_id(void) {
|
||||
return (FUSE_CHIP_REGS->FUSE_RESERVED_ODM[4] >> 3) & 0x7;
|
||||
}
|
||||
/* Derive the Hardware Type using values in the shadow cache. */
|
||||
uint32_t fuse_get_hardware_type(uint32_t target_firmware) {
|
||||
uint32_t fuse_reserved_odm4 = fuse_get_reserved_odm(4);
|
||||
uint32_t hardware_type = (((fuse_reserved_odm4 >> 7) & 2) | ((fuse_reserved_odm4 >> 2) & 1));
|
||||
|
||||
/* Derive the Hardware Type using values in the shadow cache */
|
||||
uint32_t fuse_get_hardware_type(void) {
|
||||
/* This function is very different between 4.x and < 4.x */
|
||||
uint32_t hardware_type = ((FUSE_CHIP_REGS->FUSE_RESERVED_ODM[4] >> 7) & 2) | ((FUSE_CHIP_REGS->FUSE_RESERVED_ODM[4] >> 2) & 1);
|
||||
|
||||
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) {
|
||||
static const uint32_t types[] = {0,1,4,3};
|
||||
|
||||
hardware_type |= (FUSE_CHIP_REGS->FUSE_RESERVED_ODM[4] >> 14) & 0x3C;
|
||||
hardware_type--;
|
||||
return hardware_type > 3 ? 4 : types[hardware_type];
|
||||
} else {
|
||||
/* Firmware from versions 1.0.0 to 3.0.2. */
|
||||
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
if (hardware_type >= 1) {
|
||||
return hardware_type > 2 ? 3 : hardware_type - 1;
|
||||
} else if ((FUSE_CHIP_REGS->FUSE_SPARE_BIT[9] & 1) == 0) {
|
||||
return (hardware_type > 2) ? 3 : hardware_type - 1;
|
||||
} else if ((fuse_chip->FUSE_SPARE_BIT[9] & 1) == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return 3;
|
||||
}
|
||||
} else if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_700) { /* Firmware versions from 4.0.0 to 6.2.0. */
|
||||
static const uint32_t types[] = {0,1,4,3};
|
||||
hardware_type |= ((fuse_reserved_odm4 >> 14) & 0x3C);
|
||||
hardware_type--;
|
||||
return (hardware_type > 3) ? 4 : types[hardware_type];
|
||||
} else { /* Firmware versions from 7.0.0 onwards. */
|
||||
/* Always return 0 in retail. */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Derive the Retail Type using values in the shadow cache */
|
||||
/* Derive the Retail Type using values in the shadow cache. */
|
||||
uint32_t fuse_get_retail_type(void) {
|
||||
/* Retail type = IS_RETAIL | UNIT_TYPE */
|
||||
uint32_t retail_type = ((FUSE_CHIP_REGS->FUSE_RESERVED_ODM[4] >> 7) & 4) | (FUSE_CHIP_REGS->FUSE_RESERVED_ODM[4] & 3);
|
||||
/* Retail Type = IS_RETAIL | UNIT_TYPE. */
|
||||
uint32_t fuse_reserved_odm4 = fuse_get_reserved_odm(4);
|
||||
uint32_t retail_type = (((fuse_reserved_odm4 >> 7) & 4) | (fuse_reserved_odm4 & 3));
|
||||
if (retail_type == 4) { /* Standard retail unit, IS_RETAIL | 0. */
|
||||
return 1;
|
||||
} else if (retail_type == 3) { /* Standard dev unit, 0 | DEV_UNIT. */
|
||||
@@ -249,17 +233,17 @@ uint32_t fuse_get_retail_type(void) {
|
||||
void fuse_get_hardware_info(void *dst) {
|
||||
uint32_t hw_info[0x4];
|
||||
|
||||
uint32_t unk_hw_fuse = FUSE_CHIP_REGS->_0x120 & 0x3F;
|
||||
uint32_t y_coord = FUSE_CHIP_REGS->FUSE_Y_COORDINATE & 0x1FF;
|
||||
uint32_t x_coord = FUSE_CHIP_REGS->FUSE_X_COORDINATE & 0x1FF;
|
||||
uint32_t wafer_id = FUSE_CHIP_REGS->FUSE_WAFER_ID & 0x3F;
|
||||
uint32_t lot_code_0 = FUSE_CHIP_REGS->FUSE_LOT_CODE_0;
|
||||
uint32_t lot_code_1 = FUSE_CHIP_REGS->FUSE_LOT_CODE_1 & 0x0FFFFFFF;
|
||||
uint32_t fab_code = FUSE_CHIP_REGS->FUSE_FAB_CODE & 0x3F;
|
||||
uint32_t vendor_code = FUSE_CHIP_REGS->FUSE_VENDOR_CODE & 0xF;
|
||||
uint32_t ops_reserved = FUSE_CHIP_REGS->FUSE_OPT_OPS_RESERVED & 0x3F;
|
||||
uint32_t y_coord = FUSE_CHIP_REGS->FUSE_OPT_Y_COORDINATE & 0x1FF;
|
||||
uint32_t x_coord = FUSE_CHIP_REGS->FUSE_OPT_X_COORDINATE & 0x1FF;
|
||||
uint32_t wafer_id = FUSE_CHIP_REGS->FUSE_OPT_WAFER_ID & 0x3F;
|
||||
uint32_t lot_code_0 = FUSE_CHIP_REGS->FUSE_OPT_LOT_CODE_0;
|
||||
uint32_t lot_code_1 = FUSE_CHIP_REGS->FUSE_OPT_LOT_CODE_1 & 0x0FFFFFFF;
|
||||
uint32_t fab_code = FUSE_CHIP_REGS->FUSE_OPT_FAB_CODE & 0x3F;
|
||||
uint32_t vendor_code = FUSE_CHIP_REGS->FUSE_OPT_VENDOR_CODE & 0xF;
|
||||
|
||||
/* Hardware Info = unk_hw_fuse || Y_COORD || X_COORD || WAFER_ID || LOT_CODE || FAB_CODE || VENDOR_ID */
|
||||
hw_info[0] = (uint32_t)((lot_code_1 << 30) | (wafer_id << 24) | (x_coord << 15) | (y_coord << 6) | (unk_hw_fuse));
|
||||
/* Hardware Info = OPS_RESERVED || Y_COORD || X_COORD || WAFER_ID || LOT_CODE || FAB_CODE || VENDOR_ID */
|
||||
hw_info[0] = (uint32_t)((lot_code_1 << 30) | (wafer_id << 24) | (x_coord << 15) | (y_coord << 6) | (ops_reserved));
|
||||
hw_info[1] = (uint32_t)((lot_code_0 << 26) | (lot_code_1 >> 2));
|
||||
hw_info[2] = (uint32_t)((fab_code << 26) | (lot_code_0 >> 6));
|
||||
hw_info[3] = (uint32_t)(vendor_code);
|
||||
@@ -267,15 +251,50 @@ void fuse_get_hardware_info(void *dst) {
|
||||
memcpy(dst, hw_info, 0x10);
|
||||
}
|
||||
|
||||
/* Get the Key Generation value. */
|
||||
uint32_t fuse_get_5x_key_generation(void) {
|
||||
if ((fuse_get_reserved_odm(4) & 0x800) && (fuse_get_reserved_odm(0) == 0x8E61ECAE) && (fuse_get_reserved_odm(1) == 0xF2BA3BB2)) {
|
||||
return (fuse_get_reserved_odm(2) & 0x1F);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns the fuse version expected for the firmware. */
|
||||
uint32_t fuse_get_expected_fuse_version(uint32_t target_firmware) {
|
||||
static const uint8_t expected_versions[ATMOSPHERE_TARGET_FIRMWARE_COUNT+1] = {
|
||||
[ATMOSPHERE_TARGET_FIRMWARE_100] = 1,
|
||||
[ATMOSPHERE_TARGET_FIRMWARE_200] = 2,
|
||||
[ATMOSPHERE_TARGET_FIRMWARE_300] = 3,
|
||||
/* [ATMOSPHERE_TARGET_FIRMWARE_302] = 4, */
|
||||
[ATMOSPHERE_TARGET_FIRMWARE_400] = 5,
|
||||
[ATMOSPHERE_TARGET_FIRMWARE_500] = 6,
|
||||
[ATMOSPHERE_TARGET_FIRMWARE_600] = 7,
|
||||
[ATMOSPHERE_TARGET_FIRMWARE_620] = 8,
|
||||
[ATMOSPHERE_TARGET_FIRMWARE_700] = 9,
|
||||
[ATMOSPHERE_TARGET_FIRMWARE_800] = 9,
|
||||
[ATMOSPHERE_TARGET_FIRMWARE_810] = 10,
|
||||
[ATMOSPHERE_TARGET_FIRMWARE_900] = 11,
|
||||
[ATMOSPHERE_TARGET_FIRMWARE_910] = 12,
|
||||
};
|
||||
|
||||
if (target_firmware > ATMOSPHERE_TARGET_FIRMWARE_COUNT) {
|
||||
generic_panic();
|
||||
}
|
||||
|
||||
return expected_versions[target_firmware];
|
||||
}
|
||||
|
||||
/* Check for RCM bug patches. */
|
||||
bool fuse_has_rcm_bug_patch(void) {
|
||||
/* Only check for RCM bug patch once, and cache our result. */
|
||||
if (!g_has_checked_for_rcm_bug_patch) {
|
||||
/* Patched units have this bit set in reserved_sw, according to reports. */
|
||||
/* Some patched units use XUSB in RCM. */
|
||||
if (FUSE_CHIP_REGS->FUSE_RESERVED_SW & 0x80) {
|
||||
g_has_rcm_bug_patch = true;
|
||||
}
|
||||
|
||||
/* Also check for an ipatch. */
|
||||
/* Other units have a proper ipatch instead. */
|
||||
{
|
||||
uint32_t word_count = FUSE_CHIP_REGS->FUSE_FIRST_BOOTROM_PATCH_SIZE & 0x7f;
|
||||
uint32_t word_addr = 191;
|
||||
@@ -301,4 +320,4 @@ bool fuse_has_rcm_bug_patch(void) {
|
||||
g_has_checked_for_rcm_bug_patch = true;
|
||||
|
||||
return g_has_rcm_bug_patch;
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
* 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 EXOSPHERE_FUSE_H
|
||||
#define EXOSPHERE_FUSE_H
|
||||
|
||||
@@ -24,154 +24,167 @@
|
||||
/* Exosphere driver for the Tegra X1 FUSE registers. */
|
||||
|
||||
typedef struct {
|
||||
uint32_t FUSE_CTRL;
|
||||
uint32_t FUSE_REG_ADDR;
|
||||
uint32_t FUSE_REG_READ;
|
||||
uint32_t FUSE_REG_WRITE;
|
||||
uint32_t FUSE_TIME_RD1;
|
||||
uint32_t FUSE_TIME_RD2;
|
||||
uint32_t FUSE_TIME_PGM1;
|
||||
uint32_t FUSE_TIME_PGM2;
|
||||
uint32_t FUSE_PRIV2INTFC;
|
||||
uint32_t FUSE_FUSECTRL;
|
||||
uint32_t FUSE_FUSEADDR;
|
||||
uint32_t FUSE_FUSERDATA;
|
||||
uint32_t FUSE_FUSEWDATA;
|
||||
uint32_t FUSE_FUSETIME_RD1;
|
||||
uint32_t FUSE_FUSETIME_RD2;
|
||||
uint32_t FUSE_FUSETIME_PGM1;
|
||||
uint32_t FUSE_FUSETIME_PGM2;
|
||||
uint32_t FUSE_PRIV2INTFC_START;
|
||||
uint32_t FUSE_FUSEBYPASS;
|
||||
uint32_t FUSE_PRIVATEKEYDISABLE;
|
||||
uint32_t FUSE_DIS_PGM;
|
||||
uint32_t FUSE_WRITE_ACCESS;
|
||||
uint32_t FUSE_DISABLEREGPROGRAM;
|
||||
uint32_t FUSE_WRITE_ACCESS_SW;
|
||||
uint32_t FUSE_PWR_GOOD_SW;
|
||||
uint32_t _0x38[0x32];
|
||||
} fuse_registers_t;
|
||||
uint32_t _0x38;
|
||||
uint32_t FUSE_PRIV2RESHIFT;
|
||||
uint32_t _0x40[0x3];
|
||||
uint32_t FUSE_FUSETIME_RD3;
|
||||
uint32_t _0x50[0xC];
|
||||
uint32_t FUSE_PRIVATE_KEY0_NONZERO;
|
||||
uint32_t FUSE_PRIVATE_KEY1_NONZERO;
|
||||
uint32_t FUSE_PRIVATE_KEY2_NONZERO;
|
||||
uint32_t FUSE_PRIVATE_KEY3_NONZERO;
|
||||
uint32_t FUSE_PRIVATE_KEY4_NONZERO;
|
||||
uint32_t _0x90[0x1C];
|
||||
} tegra_fuse_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t FUSE_PRODUCTION_MODE;
|
||||
uint32_t _0x4;
|
||||
uint32_t _0x8;
|
||||
uint32_t _0xC;
|
||||
uint32_t FUSE_JTAG_SECUREID_VALID;
|
||||
uint32_t FUSE_ODM_LOCK;
|
||||
uint32_t FUSE_OPT_OPENGL_EN;
|
||||
uint32_t FUSE_SKU_INFO;
|
||||
uint32_t FUSE_CPU_SPEEDO_0;
|
||||
uint32_t FUSE_CPU_IDDQ;
|
||||
uint32_t _0x1C;
|
||||
uint32_t _0x20;
|
||||
uint32_t _0x24;
|
||||
uint32_t FUSE_FT_REV;
|
||||
uint32_t FUSE_CPU_SPEEDO_1;
|
||||
uint32_t FUSE_CPU_SPEEDO_2;
|
||||
uint32_t FUSE_SOC_SPEEDO_0;
|
||||
uint32_t FUSE_SOC_SPEEDO_1;
|
||||
uint32_t FUSE_SOC_SPEEDO_2;
|
||||
uint32_t FUSE_SOC_IDDQ;
|
||||
uint32_t _0x44;
|
||||
uint32_t FUSE_CPU_SPEEDO_0_CALIB;
|
||||
uint32_t FUSE_CPU_IDDQ_CALIB;
|
||||
uint32_t FUSE_DAC_CRT_CALIB;
|
||||
uint32_t FUSE_DAC_HDTV_CALIB;
|
||||
uint32_t FUSE_DAC_SDTV_CALIB;
|
||||
uint32_t FUSE_OPT_FT_REV;
|
||||
uint32_t FUSE_CPU_SPEEDO_1_CALIB;
|
||||
uint32_t FUSE_CPU_SPEEDO_2_CALIB;
|
||||
uint32_t FUSE_SOC_SPEEDO_0_CALIB;
|
||||
uint32_t FUSE_SOC_SPEEDO_1_CALIB;
|
||||
uint32_t FUSE_SOC_SPEEDO_2_CALIB;
|
||||
uint32_t FUSE_SOC_IDDQ_CALIB;
|
||||
uint32_t FUSE_RESERVED_PRODUCTION_WP;
|
||||
uint32_t FUSE_FA;
|
||||
uint32_t _0x4C;
|
||||
uint32_t _0x50;
|
||||
uint32_t _0x54;
|
||||
uint32_t _0x58;
|
||||
uint32_t _0x5C;
|
||||
uint32_t _0x60;
|
||||
uint32_t FUSE_RESERVED_PRODUCTION;
|
||||
uint32_t FUSE_HDMI_LANE0_CALIB;
|
||||
uint32_t FUSE_HDMI_LANE1_CALIB;
|
||||
uint32_t FUSE_HDMI_LANE2_CALIB;
|
||||
uint32_t FUSE_HDMI_LANE3_CALIB;
|
||||
uint32_t FUSE_ENCRYPTION_RATE;
|
||||
uint32_t FUSE_PUBLIC_KEY[0x8];
|
||||
uint32_t FUSE_TSENSOR_1;
|
||||
uint32_t FUSE_TSENSOR_2;
|
||||
uint32_t _0x8C;
|
||||
uint32_t FUSE_CP_REV;
|
||||
uint32_t _0x94;
|
||||
uint32_t FUSE_TSENSOR_0;
|
||||
uint32_t FUSE_TSENSOR1_CALIB;
|
||||
uint32_t FUSE_TSENSOR2_CALIB;
|
||||
uint32_t FUSE_VSENSOR_CALIB;
|
||||
uint32_t FUSE_OPT_CP_REV;
|
||||
uint32_t FUSE_OPT_PFG;
|
||||
uint32_t FUSE_TSENSOR0_CALIB;
|
||||
uint32_t FUSE_FIRST_BOOTROM_PATCH_SIZE;
|
||||
uint32_t FUSE_SECURITY_MODE;
|
||||
uint32_t FUSE_PRIVATE_KEY[0x4];
|
||||
uint32_t FUSE_DEVICE_KEY;
|
||||
uint32_t _0xB8;
|
||||
uint32_t _0xBC;
|
||||
uint32_t FUSE_PRIVATE_KEY[0x5];
|
||||
uint32_t FUSE_ARM_JTAG_DIS;
|
||||
uint32_t FUSE_BOOT_DEVICE_INFO;
|
||||
uint32_t FUSE_RESERVED_SW;
|
||||
uint32_t FUSE_VP8_ENABLE;
|
||||
uint32_t FUSE_OPT_VP9_DISABLE;
|
||||
uint32_t FUSE_RESERVED_ODM[0x8];
|
||||
uint32_t _0xE8;
|
||||
uint32_t _0xEC;
|
||||
uint32_t FUSE_SKU_USB_CALIB;
|
||||
uint32_t FUSE_OBS_DIS;
|
||||
uint32_t FUSE_NOR_INFO;
|
||||
uint32_t FUSE_USB_CALIB;
|
||||
uint32_t FUSE_SKU_DIRECT_CONFIG;
|
||||
uint32_t _0xF8;
|
||||
uint32_t _0xFC;
|
||||
uint32_t FUSE_VENDOR_CODE;
|
||||
uint32_t FUSE_FAB_CODE;
|
||||
uint32_t FUSE_LOT_CODE_0;
|
||||
uint32_t FUSE_LOT_CODE_1;
|
||||
uint32_t FUSE_WAFER_ID;
|
||||
uint32_t FUSE_X_COORDINATE;
|
||||
uint32_t FUSE_Y_COORDINATE;
|
||||
uint32_t _0x11C;
|
||||
uint32_t _0x120;
|
||||
uint32_t FUSE_KFUSE_PRIVKEY_CTRL;
|
||||
uint32_t FUSE_PACKAGE_INFO;
|
||||
uint32_t FUSE_OPT_VENDOR_CODE;
|
||||
uint32_t FUSE_OPT_FAB_CODE;
|
||||
uint32_t FUSE_OPT_LOT_CODE_0;
|
||||
uint32_t FUSE_OPT_LOT_CODE_1;
|
||||
uint32_t FUSE_OPT_WAFER_ID;
|
||||
uint32_t FUSE_OPT_X_COORDINATE;
|
||||
uint32_t FUSE_OPT_Y_COORDINATE;
|
||||
uint32_t FUSE_OPT_SEC_DEBUG_EN;
|
||||
uint32_t FUSE_OPT_OPS_RESERVED;
|
||||
uint32_t FUSE_SATA_CALIB;
|
||||
uint32_t FUSE_GPU_IDDQ;
|
||||
uint32_t FUSE_TSENSOR_3;
|
||||
uint32_t _0x130;
|
||||
uint32_t _0x134;
|
||||
uint32_t _0x138;
|
||||
uint32_t _0x13C;
|
||||
uint32_t _0x140;
|
||||
uint32_t _0x144;
|
||||
uint32_t FUSE_GPU_IDDQ_CALIB;
|
||||
uint32_t FUSE_TSENSOR3_CALIB;
|
||||
uint32_t FUSE_SKU_BOND_OUT_L;
|
||||
uint32_t FUSE_SKU_BOND_OUT_H;
|
||||
uint32_t FUSE_SKU_BOND_OUT_U;
|
||||
uint32_t FUSE_SKU_BOND_OUT_V;
|
||||
uint32_t FUSE_SKU_BOND_OUT_W;
|
||||
uint32_t FUSE_OPT_SAMPLE_TYPE;
|
||||
uint32_t FUSE_OPT_SUBREVISION;
|
||||
uint32_t _0x14C;
|
||||
uint32_t _0x150;
|
||||
uint32_t FUSE_TSENSOR_4;
|
||||
uint32_t FUSE_TSENSOR_5;
|
||||
uint32_t FUSE_TSENSOR_6;
|
||||
uint32_t FUSE_TSENSOR_7;
|
||||
uint32_t FUSE_OPT_PRIV_SEC_DIS;
|
||||
uint32_t FUSE_OPT_SW_RESERVED_0;
|
||||
uint32_t FUSE_OPT_SW_RESERVED_1;
|
||||
uint32_t FUSE_TSENSOR4_CALIB;
|
||||
uint32_t FUSE_TSENSOR5_CALIB;
|
||||
uint32_t FUSE_TSENSOR6_CALIB;
|
||||
uint32_t FUSE_TSENSOR7_CALIB;
|
||||
uint32_t FUSE_OPT_PRIV_SEC_EN;
|
||||
uint32_t FUSE_PKC_DISABLE;
|
||||
uint32_t _0x16C;
|
||||
uint32_t _0x170;
|
||||
uint32_t _0x174;
|
||||
uint32_t _0x178;
|
||||
uint32_t _0x17C;
|
||||
uint32_t FUSE_FUSE2TSEC_DEBUG_DISABLE;
|
||||
uint32_t FUSE_TSENSOR_COMMON;
|
||||
uint32_t _0x184;
|
||||
uint32_t _0x188;
|
||||
uint32_t _0x18C;
|
||||
uint32_t _0x190;
|
||||
uint32_t FUSE_OPT_CP_BIN;
|
||||
uint32_t FUSE_OPT_GPU_DISABLE;
|
||||
uint32_t FUSE_OPT_FT_BIN;
|
||||
uint32_t FUSE_OPT_DONE_MAP;
|
||||
uint32_t _0x194;
|
||||
uint32_t _0x198;
|
||||
uint32_t FUSE_DEBUG_AUTH_OVERRIDE;
|
||||
uint32_t FUSE_APB2JTAG_DISABLE;
|
||||
uint32_t FUSE_ODM_INFO;
|
||||
uint32_t _0x1A0;
|
||||
uint32_t _0x1A4;
|
||||
uint32_t _0x1A8;
|
||||
uint32_t FUSE_ARM_CRYPT_DE_FEATURE;
|
||||
uint32_t _0x1AC;
|
||||
uint32_t _0x1B0;
|
||||
uint32_t _0x1B4;
|
||||
uint32_t _0x1B8;
|
||||
uint32_t _0x1BC;
|
||||
uint32_t _0x1D0;
|
||||
uint32_t FUSE_TSENSOR_8;
|
||||
uint32_t FUSE_WOA_SKU_FLAG;
|
||||
uint32_t FUSE_ECO_RESERVE_1;
|
||||
uint32_t FUSE_GCPLEX_CONFIG_FUSE;
|
||||
uint32_t FUSE_PRODUCTION_MONTH;
|
||||
uint32_t FUSE_RAM_REPAIR_INDICATOR;
|
||||
uint32_t FUSE_TSENSOR9_CALIB;
|
||||
uint32_t _0x1D8;
|
||||
uint32_t _0x1DC;
|
||||
uint32_t _0x1E0;
|
||||
uint32_t _0x1E4;
|
||||
uint32_t _0x1E8;
|
||||
uint32_t _0x1EC;
|
||||
uint32_t _0x1F0;
|
||||
uint32_t _0x1F4;
|
||||
uint32_t _0x1F8;
|
||||
uint32_t FUSE_VMIN_CALIBRATION;
|
||||
uint32_t FUSE_AGING_SENSOR_CALIBRATION;
|
||||
uint32_t FUSE_DEBUG_AUTHENTICATION;
|
||||
uint32_t FUSE_SECURE_PROVISION_INDEX;
|
||||
uint32_t FUSE_SECURE_PROVISION_INFO;
|
||||
uint32_t FUSE_OPT_GPU_DISABLE_CP1;
|
||||
uint32_t FUSE_SPARE_ENDIS;
|
||||
uint32_t FUSE_ECO_RESERVE_0;
|
||||
uint32_t _0x1FC;
|
||||
uint32_t _0x200;
|
||||
uint32_t FUSE_RESERVED_CALIB;
|
||||
uint32_t _0x208;
|
||||
uint32_t _0x20C;
|
||||
uint32_t _0x210;
|
||||
uint32_t _0x214;
|
||||
uint32_t _0x218;
|
||||
uint32_t FUSE_TSENSOR_9;
|
||||
uint32_t _0x220;
|
||||
uint32_t _0x224;
|
||||
uint32_t _0x228;
|
||||
uint32_t _0x22C;
|
||||
uint32_t _0x230;
|
||||
uint32_t _0x234;
|
||||
uint32_t _0x238;
|
||||
uint32_t _0x23C;
|
||||
uint32_t _0x240;
|
||||
uint32_t _0x244;
|
||||
uint32_t _0x248;
|
||||
uint32_t _0x24C;
|
||||
uint32_t FUSE_RESERVED_CALIB0;
|
||||
uint32_t FUSE_RESERVED_CALIB1;
|
||||
uint32_t FUSE_OPT_GPU_TPC0_DISABLE;
|
||||
uint32_t FUSE_OPT_GPU_TPC0_DISABLE_CP1;
|
||||
uint32_t FUSE_OPT_CPU_DISABLE;
|
||||
uint32_t FUSE_OPT_CPU_DISABLE_CP1;
|
||||
uint32_t FUSE_TSENSOR10_CALIB;
|
||||
uint32_t FUSE_TSENSOR10_CALIB_AUX;
|
||||
uint32_t FUSE_OPT_RAM_SVOP_DP;
|
||||
uint32_t FUSE_OPT_RAM_SVOP_PDP;
|
||||
uint32_t FUSE_OPT_RAM_SVOP_REG;
|
||||
uint32_t FUSE_OPT_RAM_SVOP_SP;
|
||||
uint32_t FUSE_OPT_RAM_SVOP_SMPDP;
|
||||
uint32_t FUSE_OPT_GPU_TPC0_DISABLE_CP2;
|
||||
uint32_t FUSE_OPT_GPU_TPC1_DISABLE;
|
||||
uint32_t FUSE_OPT_GPU_TPC1_DISABLE_CP1;
|
||||
uint32_t FUSE_OPT_GPU_TPC1_DISABLE_CP2;
|
||||
uint32_t FUSE_OPT_CPU_DISABLE_CP2;
|
||||
uint32_t FUSE_OPT_GPU_DISABLE_CP2;
|
||||
uint32_t FUSE_USB_CALIB_EXT;
|
||||
uint32_t _0x254;
|
||||
uint32_t _0x258;
|
||||
uint32_t FUSE_RESERVED_FIELD;
|
||||
uint32_t FUSE_OPT_ECC_EN;
|
||||
uint32_t _0x25C;
|
||||
uint32_t _0x260;
|
||||
uint32_t _0x264;
|
||||
@@ -180,41 +193,42 @@ typedef struct {
|
||||
uint32_t _0x270;
|
||||
uint32_t _0x274;
|
||||
uint32_t _0x278;
|
||||
uint32_t _0x27C;
|
||||
uint32_t FUSE_SPARE_REALIGNMENT_REG;
|
||||
uint32_t FUSE_SPARE_BIT[0x20];
|
||||
} fuse_chip_registers_t;
|
||||
} tegra_fuse_chip_t;
|
||||
|
||||
static inline volatile fuse_registers_t *get_fuse_regs(void) {
|
||||
return (volatile fuse_registers_t *)(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_FUSE) + 0x800);
|
||||
static inline volatile tegra_fuse_t *fuse_get_regs(void) {
|
||||
return (volatile tegra_fuse_t *)(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_FUSE) + 0x800);
|
||||
}
|
||||
|
||||
static inline volatile fuse_chip_registers_t *get_fuse_chip_regs(void) {
|
||||
return (volatile fuse_chip_registers_t *)(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_FUSE) + 0x900);
|
||||
static inline volatile tegra_fuse_chip_t *fuse_chip_get_regs(void) {
|
||||
return (volatile tegra_fuse_chip_t *)(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_FUSE) + 0x900);
|
||||
}
|
||||
#define FUSE_REGS (get_fuse_regs())
|
||||
#define FUSE_CHIP_REGS (get_fuse_chip_regs())
|
||||
|
||||
#define FUSE_REGS (fuse_get_regs())
|
||||
#define FUSE_CHIP_REGS (fuse_chip_get_regs())
|
||||
|
||||
void fuse_init(void);
|
||||
|
||||
uint32_t fuse_hw_read(uint32_t addr);
|
||||
void fuse_hw_write(uint32_t value, uint32_t addr);
|
||||
void fuse_hw_sense(void);
|
||||
void fuse_disable_programming(void);
|
||||
void fuse_secondary_private_key_disable(void);
|
||||
void fuse_disable_private_key(void);
|
||||
|
||||
uint32_t fuse_get_sku_info(void);
|
||||
uint32_t fuse_get_spare_bit(uint32_t idx);
|
||||
uint32_t fuse_get_reserved_odm(uint32_t idx);
|
||||
|
||||
uint32_t fuse_get_5x_key_generation(void);
|
||||
|
||||
uint32_t fuse_get_bootrom_patch_version(void);
|
||||
uint64_t fuse_get_device_id(void);
|
||||
uint32_t fuse_get_dram_id(void);
|
||||
uint32_t fuse_get_hardware_type(void);
|
||||
uint32_t fuse_get_hardware_type(uint32_t target_firmware);
|
||||
uint32_t fuse_get_retail_type(void);
|
||||
void fuse_get_hardware_info(void *dst);
|
||||
|
||||
uint32_t fuse_get_5x_key_generation(void);
|
||||
bool fuse_has_rcm_bug_patch(void);
|
||||
|
||||
uint32_t fuse_hw_read(uint32_t addr);
|
||||
void fuse_hw_write(uint32_t value, uint32_t addr);
|
||||
void fuse_hw_sense(void);
|
||||
|
||||
|
||||
uint32_t fuse_get_expected_fuse_version(uint32_t target_firmware);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -106,15 +106,15 @@ static void setup_se(void) {
|
||||
|
||||
/* Perform some sanity initialization. */
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
se->_0x0 &= 0xFFFEFFFF; /* Clear bit 16. */
|
||||
(void)(se->FLAGS_REG);
|
||||
se->SE_SE_SECURITY &= 0xFFFEFFFF; /* Clear bit 16. */
|
||||
(void)(se->SE_STATUS);
|
||||
__dsb_sy();
|
||||
|
||||
/* NOTE: On 8.1.0+, Nintendo does not make keyslots 0-5 unreadable. */
|
||||
se->_0x4 = 0;
|
||||
se->AES_KEY_READ_DISABLE_REG = 0;
|
||||
se->RSA_KEY_READ_DISABLE_REG = 0;
|
||||
se->_0x0 &= 0xFFFFFFFB;
|
||||
se->SE_TZRAM_SECURITY = 0;
|
||||
se->SE_CRYPTO_SECURITY_PERKEY = 0;
|
||||
se->SE_RSA_SECURITY_PERKEY = 0;
|
||||
se->SE_SE_SECURITY &= 0xFFFFFFFB;
|
||||
|
||||
/* Currently unknown what each flag does. */
|
||||
for (unsigned int i = 0; i < KEYSLOT_AES_MAX; i++) {
|
||||
|
||||
@@ -29,32 +29,24 @@ static inline uintptr_t get_pmc_base(void) {
|
||||
#define PMC_BASE (get_pmc_base())
|
||||
|
||||
#define APBDEV_PMC_DPD_ENABLE_0 MAKE_REG32(PMC_BASE + 0x24)
|
||||
|
||||
#define APBDEV_PMC_PWRGATE_TOGGLE_0 MAKE_REG32(PMC_BASE + 0x30)
|
||||
#define APBDEV_PMC_PWRGATE_STATUS_0 MAKE_REG32(PMC_BASE + 0x38)
|
||||
|
||||
#define APBDEV_PMC_SCRATCH0_0 MAKE_REG32(PMC_BASE + 0x50)
|
||||
|
||||
#define APBDEV_PMC_CRYPTO_OP_0 MAKE_REG32(PMC_BASE + 0xF4)
|
||||
|
||||
#define APBDEV_PM_0 MAKE_REG32(PMC_BASE + 0x14)
|
||||
#define APBDEV_PMC_WAKE2_STATUS_0 MAKE_REG32(PMC_BASE + 0x168)
|
||||
#define APBDEV_PMC_CNTRL2_0 MAKE_REG32(PMC_BASE + 0x440)
|
||||
|
||||
#define APBDEV_PMC_FUSE_CTRL MAKE_REG32(PMC_BASE + 0x450)
|
||||
#define APBDEV_PMC_SCRATCH43_0 MAKE_REG32(PMC_BASE + 0x22C)
|
||||
#define APBDEV_PMC_SEC_DISABLE8_0 MAKE_REG32(PMC_BASE + 0x5C0)
|
||||
#define APBDEV_PMC_SECURE_SCRATCH112_0 MAKE_REG32(PMC_BASE + 0xB18)
|
||||
#define APBDEV_PMC_SECURE_SCRATCH113_0 MAKE_REG32(PMC_BASE + 0xB1C)
|
||||
#define APBDEV_PMC_SECURE_SCRATCH114_0 MAKE_REG32(PMC_BASE + 0xB20)
|
||||
#define APBDEV_PMC_SECURE_SCRATCH115_0 MAKE_REG32(PMC_BASE + 0xB24)
|
||||
|
||||
#define APBDEV_PMC_SCRATCH200_0 MAKE_REG32(PMC_BASE + 0x840)
|
||||
|
||||
|
||||
#define APBDEV_PMC_SEC_DISABLE3_0 MAKE_REG32(PMC_BASE + 0x2D8)
|
||||
#define APBDEV_PMC_SECURE_SCRATCH34_0 MAKE_REG32(PMC_BASE + 0x368)
|
||||
#define APBDEV_PMC_SECURE_SCRATCH35_0 MAKE_REG32(PMC_BASE + 0x36C)
|
||||
|
||||
#define APBDEV_PMC_SECURE_SCRATCH16_0 MAKE_REG32(PMC_BASE + 0x320)
|
||||
#define APBDEV_PMC_SECURE_SCRATCH51_0 MAKE_REG32(PMC_BASE + 0x3AC)
|
||||
#define APBDEV_PMC_SECURE_SCRATCH55_0 MAKE_REG32(PMC_BASE + 0x3BC)
|
||||
@@ -70,5 +62,4 @@ static inline uintptr_t get_pmc_base(void) {
|
||||
#define APBDEV_PMC_SECURE_SCRATCH103_0 MAKE_REG32(PMC_BASE + 0xAF4)
|
||||
#define APBDEV_PMC_SECURE_SCRATCH39_0 MAKE_REG32(PMC_BASE + 0x37C)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -61,7 +61,7 @@ void set_security_engine_callback(unsigned int (*callback)(void)) {
|
||||
|
||||
/* Fires on Security Engine operation completion. */
|
||||
void se_operation_completed(void) {
|
||||
se_get_regs()->INT_ENABLE_REG = 0;
|
||||
se_get_regs()->SE_INT_ENABLE = 0;
|
||||
if (g_se_callback != NULL) {
|
||||
g_se_callback();
|
||||
g_se_callback = NULL;
|
||||
@@ -69,14 +69,14 @@ void se_operation_completed(void) {
|
||||
}
|
||||
|
||||
void se_check_error_status_reg(void) {
|
||||
if (se_get_regs()->ERR_STATUS_REG) {
|
||||
if (se_get_regs()->SE_ERR_STATUS) {
|
||||
generic_panic();
|
||||
}
|
||||
}
|
||||
|
||||
void se_check_for_error(void) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
if (se->INT_STATUS_REG & 0x10000 || se->FLAGS_REG & 3 || se->ERR_STATUS_REG) {
|
||||
if (se->SE_INT_STATUS & 0x10000 || se->SE_STATUS & 3 || se->SE_ERR_STATUS) {
|
||||
generic_panic();
|
||||
}
|
||||
}
|
||||
@@ -86,7 +86,7 @@ void se_trigger_interrupt(void) {
|
||||
}
|
||||
|
||||
void se_verify_flags_cleared(void) {
|
||||
if (se_get_regs()->FLAGS_REG & 3) {
|
||||
if (se_get_regs()->SE_STATUS & 3) {
|
||||
generic_panic();
|
||||
}
|
||||
}
|
||||
@@ -129,12 +129,12 @@ void set_aes_keyslot_flags(unsigned int keyslot, unsigned int flags) {
|
||||
|
||||
/* Misc flags. */
|
||||
if (flags & ~0x80) {
|
||||
se->AES_KEYSLOT_FLAGS[keyslot] = ~flags;
|
||||
se->SE_CRYPTO_KEYTABLE_ACCESS[keyslot] = ~flags;
|
||||
}
|
||||
|
||||
/* Disable keyslot reads. */
|
||||
if (flags & 0x80) {
|
||||
se->AES_KEY_READ_DISABLE_REG &= ~(1 << keyslot);
|
||||
se->SE_CRYPTO_SECURITY_PERKEY &= ~(1 << keyslot);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,12 +149,12 @@ void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags) {
|
||||
/* Misc flags. */
|
||||
if (flags & ~0x80) {
|
||||
/* TODO: Why are flags assigned this way? */
|
||||
se->RSA_KEYSLOT_FLAGS[keyslot] = (((flags >> 4) & 4) | (flags & 3)) ^ 7;
|
||||
se->SE_RSA_KEYTABLE_ACCESS[keyslot] = (((flags >> 4) & 4) | (flags & 3)) ^ 7;
|
||||
}
|
||||
|
||||
/* Disable keyslot reads. */
|
||||
if (flags & 0x80) {
|
||||
se->RSA_KEY_READ_DISABLE_REG &= ~(1 << keyslot);
|
||||
se->SE_RSA_SECURITY_PERKEY &= ~(1 << keyslot);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,8 +167,8 @@ void clear_aes_keyslot(unsigned int keyslot) {
|
||||
|
||||
/* Zero out the whole keyslot and IV. */
|
||||
for (unsigned int i = 0; i < 0x10; i++) {
|
||||
se->AES_KEYTABLE_ADDR = (keyslot << 4) | i;
|
||||
se->AES_KEYTABLE_DATA = 0;
|
||||
se->SE_CRYPTO_KEYTABLE_ADDR = (keyslot << 4) | i;
|
||||
se->SE_CRYPTO_KEYTABLE_DATA = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,13 +182,13 @@ void clear_rsa_keyslot(unsigned int keyslot) {
|
||||
/* Zero out the whole keyslot. */
|
||||
for (unsigned int i = 0; i < 0x40; i++) {
|
||||
/* Select Keyslot Modulus[i] */
|
||||
se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i | 0x40;
|
||||
se->RSA_KEYTABLE_DATA = 0;
|
||||
se->SE_RSA_KEYTABLE_ADDR = (keyslot << 7) | i | 0x40;
|
||||
se->SE_RSA_KEYTABLE_DATA = 0;
|
||||
}
|
||||
for (unsigned int i = 0; i < 0x40; i++) {
|
||||
/* Select Keyslot Expontent[i] */
|
||||
se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i;
|
||||
se->RSA_KEYTABLE_DATA = 0;
|
||||
se->SE_RSA_KEYTABLE_ADDR = (keyslot << 7) | i;
|
||||
se->SE_RSA_KEYTABLE_DATA = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,8 +200,8 @@ void set_aes_keyslot(unsigned int keyslot, const void *key, size_t key_size) {
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < (key_size >> 2); i++) {
|
||||
se->AES_KEYTABLE_ADDR = (keyslot << 4) | i;
|
||||
se->AES_KEYTABLE_DATA = read32le(key, 4 * i);
|
||||
se->SE_CRYPTO_KEYTABLE_ADDR = (keyslot << 4) | i;
|
||||
se->SE_CRYPTO_KEYTABLE_DATA = read32le(key, 4 * i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,13 +213,13 @@ void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < (modulus_size >> 2); i++) {
|
||||
se->RSA_KEYTABLE_ADDR = (keyslot << 7) | 0x40 | i;
|
||||
se->RSA_KEYTABLE_DATA = read32be(modulus, (4 * (modulus_size >> 2)) - (4 * i) - 4);
|
||||
se->SE_RSA_KEYTABLE_ADDR = (keyslot << 7) | 0x40 | i;
|
||||
se->SE_RSA_KEYTABLE_DATA = read32be(modulus, (4 * (modulus_size >> 2)) - (4 * i) - 4);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < (exp_size >> 2); i++) {
|
||||
se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i;
|
||||
se->RSA_KEYTABLE_DATA = read32be(exponent, (4 * (exp_size >> 2)) - (4 * i) - 4);
|
||||
se->SE_RSA_KEYTABLE_ADDR = (keyslot << 7) | i;
|
||||
se->SE_RSA_KEYTABLE_DATA = read32be(exponent, (4 * (exp_size >> 2)) - (4 * i) - 4);
|
||||
}
|
||||
|
||||
g_se_modulus_sizes[keyslot] = modulus_size;
|
||||
@@ -234,8 +234,8 @@ void set_aes_keyslot_iv(unsigned int keyslot, const void *iv, size_t iv_size) {
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < (iv_size >> 2); i++) {
|
||||
se->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i;
|
||||
se->AES_KEYTABLE_DATA = read32le(iv, 4 * i);
|
||||
se->SE_CRYPTO_KEYTABLE_ADDR = (keyslot << 4) | 8 | i;
|
||||
se->SE_CRYPTO_KEYTABLE_DATA = read32le(iv, 4 * i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,14 +247,14 @@ void clear_aes_keyslot_iv(unsigned int keyslot) {
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < (0x10 >> 2); i++) {
|
||||
se->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i;
|
||||
se->AES_KEYTABLE_DATA = 0;
|
||||
se->SE_CRYPTO_KEYTABLE_ADDR = (keyslot << 4) | 8 | i;
|
||||
se->SE_CRYPTO_KEYTABLE_DATA = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void set_se_ctr(const void *ctr) {
|
||||
for (unsigned int i = 0; i < 4; i++) {
|
||||
se_get_regs()->CRYPTO_CTR_REG[i] = read32le(ctr, i * 4);
|
||||
se_get_regs()->SE_CRYPTO_LINEAR_CTR[i] = read32le(ctr, i * 4);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,10 +265,10 @@ void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_sr
|
||||
generic_panic();
|
||||
}
|
||||
|
||||
se->CONFIG_REG = (ALG_AES_DEC | DST_KEYTAB);
|
||||
se->CRYPTO_REG = keyslot_src << 24;
|
||||
se->BLOCK_COUNT_REG = 0;
|
||||
se->CRYPTO_KEYTABLE_DST_REG = keyslot_dst << 8;
|
||||
se->SE_CONFIG = (ALG_AES_DEC | DST_KEYTAB);
|
||||
se->SE_CRYPTO_CONFIG = keyslot_src << 24;
|
||||
se->SE_CRYPTO_LAST_BLOCK = 0;
|
||||
se->SE_CRYPTO_KEYTABLE_DST = keyslot_dst << 8;
|
||||
|
||||
flush_dcache_range(wrapped_key, (const uint8_t *)wrapped_key + wrapped_key_size);
|
||||
trigger_se_blocking_op(OP_START, NULL, 0, wrapped_key, wrapped_key_size);
|
||||
@@ -287,35 +287,35 @@ void se_aes_crypt_insecure_internal(unsigned int keyslot, uint32_t out_ll_paddr,
|
||||
|
||||
/* Setup Config register. */
|
||||
if (encrypt) {
|
||||
se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY);
|
||||
se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY);
|
||||
} else {
|
||||
se->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY);
|
||||
se->SE_CONFIG = (ALG_AES_DEC | DST_MEMORY);
|
||||
}
|
||||
|
||||
/* Setup Crypto register. */
|
||||
se->CRYPTO_REG = crypt_config | (keyslot << 24) | (encrypt << 8);
|
||||
se->SE_CRYPTO_CONFIG = crypt_config | (keyslot << 24) | (encrypt << 8);
|
||||
|
||||
/* Mark this encryption as insecure -- this makes the SE not a secure busmaster. */
|
||||
se->CRYPTO_REG |= 0x80000000;
|
||||
se->SE_CRYPTO_CONFIG |= 0x80000000;
|
||||
|
||||
/* Appropriate number of blocks. */
|
||||
se->BLOCK_COUNT_REG = (size >> 4) - 1;
|
||||
se->SE_CRYPTO_LAST_BLOCK = (size >> 4) - 1;
|
||||
|
||||
/* Set the callback, for after the async operation. */
|
||||
set_security_engine_callback(callback);
|
||||
|
||||
/* Enable SE Interrupt firing for async op. */
|
||||
se->INT_ENABLE_REG = 0x10;
|
||||
se->SE_INT_ENABLE = 0x10;
|
||||
|
||||
/* Setup Input/Output lists */
|
||||
se->IN_LL_ADDR_REG = in_ll_paddr;
|
||||
se->OUT_LL_ADDR_REG = out_ll_paddr;
|
||||
se->SE_IN_LL_ADDR = in_ll_paddr;
|
||||
se->SE_OUT_LL_ADDR = out_ll_paddr;
|
||||
|
||||
/* Set registers for operation. */
|
||||
se->ERR_STATUS_REG = se->ERR_STATUS_REG;
|
||||
se->INT_STATUS_REG = se->INT_STATUS_REG;
|
||||
se->OPERATION_REG = 1;
|
||||
(void)(se->OPERATION_REG);
|
||||
se->SE_ERR_STATUS = se->SE_ERR_STATUS;
|
||||
se->SE_INT_STATUS = se->SE_INT_STATUS;
|
||||
se->SE_OPERATION = 1;
|
||||
(void)(se->SE_OPERATION);
|
||||
|
||||
/* Ensure writes go through. */
|
||||
__dsb_ish();
|
||||
@@ -323,7 +323,7 @@ void se_aes_crypt_insecure_internal(unsigned int keyslot, uint32_t out_ll_paddr,
|
||||
|
||||
void se_aes_ctr_crypt_insecure(unsigned int keyslot, uint32_t out_ll_paddr, uint32_t in_ll_paddr, size_t size, const void *ctr, unsigned int (*callback)(void)) {
|
||||
/* Unknown what this write does, but official code writes it for CTR mode. */
|
||||
se_get_regs()->SPARE_0 = 1;
|
||||
se_get_regs()->SE_SPARE = 1;
|
||||
set_se_ctr(ctr);
|
||||
se_aes_crypt_insecure_internal(keyslot, out_ll_paddr, in_ll_paddr, size, 0x81E, true, callback);
|
||||
}
|
||||
@@ -351,20 +351,20 @@ void se_exp_mod(unsigned int keyslot, void *buf, size_t size, unsigned int (*cal
|
||||
stack_buf[i] = *((uint8_t *)buf + size - i - 1);
|
||||
}
|
||||
|
||||
se->CONFIG_REG = (ALG_RSA | DST_RSAREG);
|
||||
se->RSA_CONFIG = keyslot << 24;
|
||||
se->RSA_KEY_SIZE_REG = (g_se_modulus_sizes[keyslot] >> 6) - 1;
|
||||
se->RSA_EXP_SIZE_REG = g_se_exp_sizes[keyslot] >> 2;
|
||||
se->SE_CONFIG = (ALG_RSA | DST_RSAREG);
|
||||
se->SE_RSA_CONFIG = keyslot << 24;
|
||||
se->SE_RSA_KEY_SIZE = (g_se_modulus_sizes[keyslot] >> 6) - 1;
|
||||
se->SE_RSA_EXP_SIZE = g_se_exp_sizes[keyslot] >> 2;
|
||||
|
||||
set_security_engine_callback(callback);
|
||||
|
||||
/* Enable SE Interrupt firing for async op. */
|
||||
se->INT_ENABLE_REG = 0x10;
|
||||
/* Enable SE interrupt firing for async op. */
|
||||
se->SE_INT_ENABLE = 0x10;
|
||||
|
||||
flush_dcache_range(stack_buf, stack_buf + KEYSIZE_RSA_MAX);
|
||||
trigger_se_rsa_op(stack_buf, size);
|
||||
|
||||
while (!(se->INT_STATUS_REG & 2)) { /* Wait a while */ }
|
||||
while (!(se->SE_INT_STATUS & 2)) { /* Wait a while */ }
|
||||
}
|
||||
|
||||
void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
@@ -380,10 +380,10 @@ void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, co
|
||||
stack_buf[i] = *((uint8_t *)src + src_size - i - 1);
|
||||
}
|
||||
|
||||
se->CONFIG_REG = (ALG_RSA | DST_RSAREG);
|
||||
se->RSA_CONFIG = keyslot << 24;
|
||||
se->RSA_KEY_SIZE_REG = (g_se_modulus_sizes[keyslot] >> 6) - 1;
|
||||
se->RSA_EXP_SIZE_REG = g_se_exp_sizes[keyslot] >> 2;
|
||||
se->SE_CONFIG = (ALG_RSA | DST_RSAREG);
|
||||
se->SE_RSA_CONFIG = keyslot << 24;
|
||||
se->SE_RSA_KEY_SIZE = (g_se_modulus_sizes[keyslot] >> 6) - 1;
|
||||
se->SE_RSA_EXP_SIZE = g_se_exp_sizes[keyslot] >> 2;
|
||||
|
||||
flush_dcache_range(stack_buf, stack_buf + KEYSIZE_RSA_MAX);
|
||||
trigger_se_blocking_op(OP_START, NULL, 0, stack_buf, src_size);
|
||||
@@ -401,7 +401,7 @@ void se_get_exp_mod_output(void *buf, size_t size) {
|
||||
|
||||
/* Copy endian swapped output. */
|
||||
while (num_dwords) {
|
||||
*p_out = read32be(se_get_regs()->RSA_OUTPUT, offset);
|
||||
*p_out = read32be(se_get_regs()->SE_RSA_OUTPUT, offset);
|
||||
offset += 4;
|
||||
p_out--;
|
||||
num_dwords--;
|
||||
@@ -472,13 +472,13 @@ void trigger_se_rsa_op(void *buf, size_t size) {
|
||||
ll_init(&in_ll, (void *)buf, size);
|
||||
|
||||
/* Set the input LL. */
|
||||
se->IN_LL_ADDR_REG = (uint32_t) get_physical_address(&in_ll);
|
||||
se->SE_IN_LL_ADDR = (uint32_t) get_physical_address(&in_ll);
|
||||
|
||||
/* Set registers for operation. */
|
||||
se->ERR_STATUS_REG = se->ERR_STATUS_REG;
|
||||
se->INT_STATUS_REG = se->INT_STATUS_REG;
|
||||
se->OPERATION_REG = 1;
|
||||
(void)(se->OPERATION_REG);
|
||||
se->SE_ERR_STATUS = se->SE_ERR_STATUS;
|
||||
se->SE_INT_STATUS = se->SE_INT_STATUS;
|
||||
se->SE_OPERATION = 1;
|
||||
(void)(se->SE_OPERATION);
|
||||
|
||||
/* Ensure writes go through. */
|
||||
__dsb_ish();
|
||||
@@ -495,18 +495,18 @@ void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const v
|
||||
__dsb_sy();
|
||||
|
||||
/* Set the LLs. */
|
||||
se->IN_LL_ADDR_REG = (uint32_t) get_physical_address(&in_ll);
|
||||
se->OUT_LL_ADDR_REG = (uint32_t) get_physical_address(&out_ll);
|
||||
se->SE_IN_LL_ADDR = (uint32_t) get_physical_address(&in_ll);
|
||||
se->SE_OUT_LL_ADDR = (uint32_t) get_physical_address(&out_ll);
|
||||
|
||||
/* Set registers for operation. */
|
||||
se->ERR_STATUS_REG = se->ERR_STATUS_REG;
|
||||
se->INT_STATUS_REG = se->INT_STATUS_REG;
|
||||
se->OPERATION_REG = op;
|
||||
(void)(se->OPERATION_REG);
|
||||
se->SE_ERR_STATUS = se->SE_ERR_STATUS;
|
||||
se->SE_INT_STATUS = se->SE_INT_STATUS;
|
||||
se->SE_OPERATION = op;
|
||||
(void)(se->SE_OPERATION);
|
||||
|
||||
__dsb_ish();
|
||||
|
||||
while (!(se->INT_STATUS_REG & 0x10)) { /* Wait a while */ }
|
||||
while (!(se->SE_INT_STATUS & 0x10)) { /* Wait a while */ }
|
||||
|
||||
se_check_for_error();
|
||||
}
|
||||
@@ -526,7 +526,7 @@ void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src,
|
||||
flush_dcache_range(block, block + sizeof(block));
|
||||
|
||||
/* Trigger AES operation. */
|
||||
se_get_regs()->BLOCK_COUNT_REG = 0;
|
||||
se_get_regs()->SE_CRYPTO_LAST_BLOCK = 0;
|
||||
trigger_se_blocking_op(OP_START, block, sizeof(block), block, sizeof(block));
|
||||
|
||||
/* Copy output data into dst. */
|
||||
@@ -553,15 +553,15 @@ void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const vo
|
||||
unsigned int num_blocks = src_size >> 4;
|
||||
|
||||
/* Unknown what this write does, but official code writes it for CTR mode. */
|
||||
se->SPARE_0 = 1;
|
||||
se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY);
|
||||
se->CRYPTO_REG = (keyslot << 24) | 0x91E;
|
||||
se->SE_SPARE = 1;
|
||||
se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY);
|
||||
se->SE_CRYPTO_CONFIG = (keyslot << 24) | 0x91E;
|
||||
set_se_ctr(ctr);
|
||||
|
||||
/* Handle any aligned blocks. */
|
||||
size_t aligned_size = (size_t)num_blocks << 4;
|
||||
if (aligned_size) {
|
||||
se->BLOCK_COUNT_REG = num_blocks - 1;
|
||||
se->SE_CRYPTO_LAST_BLOCK = num_blocks - 1;
|
||||
trigger_se_blocking_op(OP_START, dst, dst_size, src, aligned_size);
|
||||
}
|
||||
|
||||
@@ -587,8 +587,8 @@ void se_aes_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size,
|
||||
}
|
||||
|
||||
/* Set configuration high (256-bit vs 128-bit) based on parameter. */
|
||||
se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY) | (config_high << 16);
|
||||
se->CRYPTO_REG = keyslot << 24 | 0x100;
|
||||
se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY) | (config_high << 16);
|
||||
se->SE_CRYPTO_CONFIG = keyslot << 24 | 0x100;
|
||||
flush_dcache_range((uint8_t *)src, (uint8_t *)src + 0x10);
|
||||
se_perform_aes_block_operation(dst, 0x10, src, 0x10);
|
||||
flush_dcache_range((uint8_t *)dst, (uint8_t *)dst + 0x10);
|
||||
@@ -611,8 +611,8 @@ void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size,
|
||||
generic_panic();
|
||||
}
|
||||
|
||||
se->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY);
|
||||
se->CRYPTO_REG = keyslot << 24;
|
||||
se->SE_CONFIG = (ALG_AES_DEC | DST_MEMORY);
|
||||
se->SE_CRYPTO_CONFIG = keyslot << 24;
|
||||
flush_dcache_range((uint8_t *)src, (uint8_t *)src + 0x10);
|
||||
se_perform_aes_block_operation(dst, 0x10, src, 0x10);
|
||||
flush_dcache_range((uint8_t *)dst, (uint8_t *)dst + 0x10);
|
||||
@@ -649,16 +649,16 @@ void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, con
|
||||
shift_left_xor_rb(derived_key);
|
||||
}
|
||||
|
||||
se->CONFIG_REG = (ALG_AES_ENC | DST_HASHREG) | (config_high << 16);
|
||||
se->CRYPTO_REG = (keyslot << 24) | (0x145);
|
||||
se->SE_CONFIG = (ALG_AES_ENC | DST_HASHREG) | (config_high << 16);
|
||||
se->SE_CRYPTO_CONFIG = (keyslot << 24) | (0x145);
|
||||
clear_aes_keyslot_iv(keyslot);
|
||||
|
||||
unsigned int num_blocks = (data_size + 0xF) >> 4;
|
||||
/* Handle aligned blocks. */
|
||||
if (num_blocks > 1) {
|
||||
se->BLOCK_COUNT_REG = num_blocks - 2;
|
||||
se->SE_CRYPTO_LAST_BLOCK = num_blocks - 2;
|
||||
trigger_se_blocking_op(OP_START, NULL, 0, data, data_size);
|
||||
se->CRYPTO_REG |= 0x80;
|
||||
se->SE_CRYPTO_CONFIG |= 0x80;
|
||||
}
|
||||
|
||||
/* Create final block. */
|
||||
@@ -675,13 +675,13 @@ void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, con
|
||||
}
|
||||
|
||||
/* Perform last operation. */
|
||||
se->BLOCK_COUNT_REG = 0;
|
||||
se->SE_CRYPTO_LAST_BLOCK = 0;
|
||||
flush_dcache_range(last_block, last_block + sizeof(last_block));
|
||||
trigger_se_blocking_op(OP_START, NULL, 0, last_block, sizeof(last_block));
|
||||
|
||||
/* Copy output CMAC. */
|
||||
for (unsigned int i = 0; i < (cmac_size >> 2); i++) {
|
||||
((uint32_t *)cmac)[i] = read32le(se->HASH_RESULT_REG, i << 2);
|
||||
((uint32_t *)cmac)[i] = read32le(se->SE_HASH_RESULT, i << 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -699,10 +699,10 @@ void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, co
|
||||
generic_panic();
|
||||
}
|
||||
|
||||
se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY) | (0x202 << 16);
|
||||
se->CRYPTO_REG = (keyslot << 24) | 0x144;
|
||||
se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY) | (0x202 << 16);
|
||||
se->SE_CRYPTO_CONFIG = (keyslot << 24) | 0x144;
|
||||
set_aes_keyslot_iv(keyslot, iv, 0x10);
|
||||
se->BLOCK_COUNT_REG = (src_size >> 4) - 1;
|
||||
se->SE_CRYPTO_LAST_BLOCK = (src_size >> 4) - 1;
|
||||
trigger_se_blocking_op(OP_START, dst, dst_size, src, src_size);
|
||||
}
|
||||
|
||||
@@ -711,23 +711,23 @@ void se_calculate_sha256(void *dst, const void *src, size_t src_size) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
|
||||
/* Setup config for SHA256, size = BITS(src_size) */
|
||||
se->CONFIG_REG = (ENCMODE_SHA256 | ALG_SHA | DST_HASHREG);
|
||||
se->SHA_CONFIG_REG = 1;
|
||||
se->SHA_MSG_LENGTH_REG = (uint32_t)(src_size << 3);
|
||||
se->_0x208 = 0;
|
||||
se->_0x20C = 0;
|
||||
se->_0x210 = 0;
|
||||
se->SHA_MSG_LEFT_REG = (uint32_t)(src_size << 3);
|
||||
se->_0x218 = 0;
|
||||
se->_0x21C = 0;
|
||||
se->_0x220 = 0;
|
||||
se->SE_CONFIG = (ENCMODE_SHA256 | ALG_SHA | DST_HASHREG);
|
||||
se->SE_SHA_CONFIG = 1;
|
||||
se->SE_SHA_MSG_LENGTH[0] = (uint32_t)(src_size << 3);
|
||||
se->SE_SHA_MSG_LENGTH[1] = 0;
|
||||
se->SE_SHA_MSG_LENGTH[2] = 0;
|
||||
se->SE_SHA_MSG_LENGTH[3] = 0;
|
||||
se->SE_SHA_MSG_LEFT[0] = (uint32_t)(src_size << 3);
|
||||
se->SE_SHA_MSG_LEFT[1] = 0;
|
||||
se->SE_SHA_MSG_LEFT[2] = 0;
|
||||
se->SE_SHA_MSG_LEFT[3] = 0;
|
||||
|
||||
/* Trigger the operation. */
|
||||
trigger_se_blocking_op(OP_START, NULL, 0, src, src_size);
|
||||
|
||||
/* Copy output hash. */
|
||||
for (unsigned int i = 0; i < (0x20 >> 2); i++) {
|
||||
((uint32_t *)dst)[i] = read32be(se->HASH_RESULT_REG, i << 2);
|
||||
((uint32_t *)dst)[i] = read32be(se->SE_HASH_RESULT, i << 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -743,12 +743,12 @@ void se_initialize_rng(unsigned int keyslot) {
|
||||
/* This will be discarded, when done. */
|
||||
uint8_t output_buf[0x10];
|
||||
|
||||
se->RNG_SRC_CONFIG_REG = 3; /* Entropy enable + Entropy lock enable */
|
||||
se->RNG_RESEED_INTERVAL_REG = 70001;
|
||||
se->CONFIG_REG = (ALG_RNG | DST_MEMORY);
|
||||
se->CRYPTO_REG = (keyslot << 24) | 0x108;
|
||||
se->RNG_CONFIG_REG = 5;
|
||||
se->BLOCK_COUNT_REG = 0;
|
||||
se->SE_RNG_SRC_CONFIG = 3; /* Entropy enable + Entropy lock enable */
|
||||
se->SE_RNG_RESEED_INTERVAL = 70001;
|
||||
se->SE_CONFIG = (ALG_RNG | DST_MEMORY);
|
||||
se->SE_CRYPTO_CONFIG = (keyslot << 24) | 0x108;
|
||||
se->SE_RNG_CONFIG = 5;
|
||||
se->SE_CRYPTO_LAST_BLOCK = 0;
|
||||
trigger_se_blocking_op(OP_START, output_buf, 0x10, NULL, 0);
|
||||
}
|
||||
|
||||
@@ -761,12 +761,12 @@ void se_generate_random(unsigned int keyslot, void *dst, size_t size) {
|
||||
|
||||
uint32_t num_blocks = size >> 4;
|
||||
size_t aligned_size = num_blocks << 4;
|
||||
se->CONFIG_REG = (ALG_RNG | DST_MEMORY);
|
||||
se->CRYPTO_REG = (keyslot << 24) | 0x108;
|
||||
se->RNG_CONFIG_REG = 4;
|
||||
se->SE_CONFIG = (ALG_RNG | DST_MEMORY);
|
||||
se->SE_CRYPTO_CONFIG = (keyslot << 24) | 0x108;
|
||||
se->SE_RNG_CONFIG = 4;
|
||||
|
||||
if (num_blocks >= 1) {
|
||||
se->BLOCK_COUNT_REG = num_blocks - 1;
|
||||
se->SE_CRYPTO_LAST_BLOCK = num_blocks - 1;
|
||||
trigger_se_blocking_op(OP_START, dst, aligned_size, NULL, 0);
|
||||
}
|
||||
if (size > aligned_size) {
|
||||
@@ -778,15 +778,15 @@ void se_generate_random(unsigned int keyslot, void *dst, size_t size) {
|
||||
void se_set_in_context_save_mode(bool is_context_save_mode) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
|
||||
uint32_t val = se->_0x0;
|
||||
uint32_t val = se->SE_SE_SECURITY;
|
||||
if (is_context_save_mode) {
|
||||
val |= 0x10000;
|
||||
} else {
|
||||
val &= 0xFFFEFFFF;
|
||||
}
|
||||
se->_0x0 = val;
|
||||
se->SE_SE_SECURITY = val;
|
||||
/* Perform a useless read from flags reg. */
|
||||
(void)(se->FLAGS_REG);
|
||||
(void)(se->SE_STATUS);
|
||||
}
|
||||
|
||||
void se_generate_random_key(unsigned int dst_keyslot, unsigned int rng_keyslot) {
|
||||
@@ -797,26 +797,26 @@ void se_generate_random_key(unsigned int dst_keyslot, unsigned int rng_keyslot)
|
||||
}
|
||||
|
||||
/* Setup Config. */
|
||||
se->CONFIG_REG = (ALG_RNG | DST_KEYTAB);
|
||||
se->CRYPTO_REG = (rng_keyslot << 24) | 0x108;
|
||||
se->RNG_CONFIG_REG = 4;
|
||||
se->BLOCK_COUNT_REG = 0;
|
||||
se->SE_CONFIG = (ALG_RNG | DST_KEYTAB);
|
||||
se->SE_CRYPTO_CONFIG = (rng_keyslot << 24) | 0x108;
|
||||
se->SE_RNG_CONFIG = 4;
|
||||
se->SE_CRYPTO_LAST_BLOCK = 0;
|
||||
|
||||
/* Generate low part of key. */
|
||||
se->CRYPTO_KEYTABLE_DST_REG = (dst_keyslot << 8);
|
||||
se->SE_CRYPTO_KEYTABLE_DST = (dst_keyslot << 8);
|
||||
trigger_se_blocking_op(OP_START, NULL, 0, NULL, 0);
|
||||
/* Generate high part of key. */
|
||||
se->CRYPTO_KEYTABLE_DST_REG = (dst_keyslot << 8) | 1;
|
||||
se->SE_CRYPTO_KEYTABLE_DST = (dst_keyslot << 8) | 1;
|
||||
trigger_se_blocking_op(OP_START, NULL, 0, NULL, 0);
|
||||
}
|
||||
|
||||
void se_generate_srk(unsigned int srkgen_keyslot) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
|
||||
se->CONFIG_REG = (ALG_RNG | DST_SRK);
|
||||
se->CRYPTO_REG = (srkgen_keyslot << 24) | 0x108;
|
||||
se->RNG_CONFIG_REG = 6;
|
||||
se->BLOCK_COUNT_REG = 0;
|
||||
se->SE_CONFIG = (ALG_RNG | DST_SRK);
|
||||
se->SE_CRYPTO_CONFIG = (srkgen_keyslot << 24) | 0x108;
|
||||
se->SE_RNG_CONFIG = 6;
|
||||
se->SE_CRYPTO_LAST_BLOCK = 0;
|
||||
trigger_se_blocking_op(OP_START, NULL, 0, NULL, 0);
|
||||
}
|
||||
|
||||
@@ -853,39 +853,39 @@ void se_save_context(unsigned int srkgen_keyslot, unsigned int rng_keyslot, void
|
||||
flush_dcache_range(work_buf, work_buf + 0x10);
|
||||
|
||||
/* Save random initial block. */
|
||||
se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY);
|
||||
se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_MEM);
|
||||
se->BLOCK_COUNT_REG = 0;
|
||||
se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY);
|
||||
se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_MEM);
|
||||
se->SE_CRYPTO_LAST_BLOCK = 0;
|
||||
se_encrypt_with_srk(dst, 0x10, work_buf, 0x10);
|
||||
|
||||
/* Save Sticky Bits. */
|
||||
for (unsigned int i = 0; i < 0x2; i++) {
|
||||
se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_STICKY_BITS) | (i << CTX_SAVE_STICKY_BIT_INDEX_SHIFT);
|
||||
se->BLOCK_COUNT_REG = 0;
|
||||
se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_STICKY_BITS) | (i << CTX_SAVE_STICKY_BIT_INDEX_SHIFT);
|
||||
se->SE_CRYPTO_LAST_BLOCK = 0;
|
||||
se_encrypt_with_srk(dst + 0x10 + (i * 0x10), 0x10, NULL, 0);
|
||||
}
|
||||
|
||||
/* Save AES Key Table. */
|
||||
for (unsigned int i = 0; i < KEYSLOT_AES_MAX; i++) {
|
||||
se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_LOW_BITS);
|
||||
se->BLOCK_COUNT_REG = 0;
|
||||
se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_LOW_BITS);
|
||||
se->SE_CRYPTO_LAST_BLOCK = 0;
|
||||
se_encrypt_with_srk(dst + 0x30 + (i * 0x20), 0x10, NULL, 0);
|
||||
se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_HIGH_BITS);
|
||||
se->BLOCK_COUNT_REG = 0;
|
||||
se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_HIGH_BITS);
|
||||
se->SE_CRYPTO_LAST_BLOCK = 0;
|
||||
se_encrypt_with_srk(dst + 0x40 + (i * 0x20), 0x10, NULL, 0);
|
||||
}
|
||||
|
||||
/* Save AES Original IVs. */
|
||||
for (unsigned int i = 0; i < KEYSLOT_AES_MAX; i++) {
|
||||
se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_ORIGINAL_IV);
|
||||
se->BLOCK_COUNT_REG = 0;
|
||||
se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_ORIGINAL_IV);
|
||||
se->SE_CRYPTO_LAST_BLOCK = 0;
|
||||
se_encrypt_with_srk(dst + 0x230 + (i * 0x10), 0x10, NULL, 0);
|
||||
}
|
||||
|
||||
/* Save AES Updated IVs */
|
||||
for (unsigned int i = 0; i < KEYSLOT_AES_MAX; i++) {
|
||||
se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_UPDATED_IV);
|
||||
se->BLOCK_COUNT_REG = 0;
|
||||
se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_UPDATED_IV);
|
||||
se->SE_CRYPTO_LAST_BLOCK = 0;
|
||||
se_encrypt_with_srk(dst + 0x330 + (i * 0x10), 0x10, NULL, 0);
|
||||
}
|
||||
|
||||
@@ -894,8 +894,8 @@ void se_save_context(unsigned int srkgen_keyslot, unsigned int rng_keyslot, void
|
||||
for (unsigned int rsa_key = 0; rsa_key < KEYSLOT_RSA_MAX; rsa_key++) {
|
||||
for (unsigned int mod_exp = 0; mod_exp < 2; mod_exp++) {
|
||||
for (unsigned int sub_block = 0; sub_block < 0x10; sub_block++) {
|
||||
se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_KEYTABLE_RSA) | ((2 * rsa_key + (1 - mod_exp)) << CTX_SAVE_RSA_KEY_INDEX_SHIFT) | (sub_block << CTX_SAVE_RSA_KEY_BLOCK_INDEX_SHIFT);
|
||||
se->BLOCK_COUNT_REG = 0;
|
||||
se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_KEYTABLE_RSA) | ((2 * rsa_key + (1 - mod_exp)) << CTX_SAVE_RSA_KEY_INDEX_SHIFT) | (sub_block << CTX_SAVE_RSA_KEY_BLOCK_INDEX_SHIFT);
|
||||
se->SE_CRYPTO_LAST_BLOCK = 0;
|
||||
se_encrypt_with_srk(rsa_ctx_out, 0x10, NULL, 0);
|
||||
rsa_ctx_out += 0x10;
|
||||
}
|
||||
@@ -904,14 +904,14 @@ void se_save_context(unsigned int srkgen_keyslot, unsigned int rng_keyslot, void
|
||||
|
||||
/* Save "Known Pattern. " */
|
||||
static const uint8_t context_save_known_pattern[0x10] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
|
||||
se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_MEM);
|
||||
se->BLOCK_COUNT_REG = 0;
|
||||
se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_MEM);
|
||||
se->SE_CRYPTO_LAST_BLOCK = 0;
|
||||
se_encrypt_with_srk(dst + 0x830, 0x10, context_save_known_pattern, 0x10);
|
||||
|
||||
/* Save SRK into PMC registers. */
|
||||
se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_SRK);
|
||||
se->BLOCK_COUNT_REG = 0;
|
||||
se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_SRK);
|
||||
se->SE_CRYPTO_LAST_BLOCK = 0;
|
||||
se_encrypt_with_srk(work_buf, 0, NULL, 0);
|
||||
se->CONFIG_REG = 0;
|
||||
se->SE_CONFIG = 0;
|
||||
se_encrypt_with_srk(work_buf, 0, NULL, 0);
|
||||
}
|
||||
|
||||
@@ -103,71 +103,59 @@
|
||||
#define RSA_2048_BYTES 0x100
|
||||
|
||||
typedef struct {
|
||||
uint32_t _0x0;
|
||||
uint32_t _0x4;
|
||||
uint32_t OPERATION_REG;
|
||||
uint32_t INT_ENABLE_REG;
|
||||
uint32_t INT_STATUS_REG;
|
||||
uint32_t CONFIG_REG;
|
||||
uint32_t IN_LL_ADDR_REG;
|
||||
uint32_t _0x1C;
|
||||
uint32_t _0x20;
|
||||
uint32_t OUT_LL_ADDR_REG;
|
||||
uint32_t _0x28;
|
||||
uint32_t _0x2C;
|
||||
uint8_t HASH_RESULT_REG[0x20];
|
||||
uint8_t _0x50[0x20];
|
||||
uint32_t CONTEXT_SAVE_CONFIG_REG;
|
||||
uint8_t _0x74[0x18C];
|
||||
uint32_t SHA_CONFIG_REG;
|
||||
uint32_t SHA_MSG_LENGTH_REG;
|
||||
uint32_t _0x208;
|
||||
uint32_t _0x20C;
|
||||
uint32_t _0x210;
|
||||
uint32_t SHA_MSG_LEFT_REG;
|
||||
uint32_t _0x218;
|
||||
uint32_t _0x21C;
|
||||
uint32_t _0x220;
|
||||
uint32_t _0x224;
|
||||
uint8_t _0x228[0x58];
|
||||
uint32_t AES_KEY_READ_DISABLE_REG;
|
||||
uint32_t AES_KEYSLOT_FLAGS[0x10];
|
||||
uint8_t _0x2C4[0x3C];
|
||||
uint32_t _0x300;
|
||||
uint32_t CRYPTO_REG;
|
||||
uint32_t CRYPTO_CTR_REG[4];
|
||||
uint32_t BLOCK_COUNT_REG;
|
||||
uint32_t AES_KEYTABLE_ADDR;
|
||||
uint32_t AES_KEYTABLE_DATA;
|
||||
uint32_t _0x324;
|
||||
uint32_t _0x328;
|
||||
uint32_t _0x32C;
|
||||
uint32_t CRYPTO_KEYTABLE_DST_REG;
|
||||
uint8_t _0x334[0xC];
|
||||
uint32_t RNG_CONFIG_REG;
|
||||
uint32_t RNG_SRC_CONFIG_REG;
|
||||
uint32_t RNG_RESEED_INTERVAL_REG;
|
||||
uint8_t _0x34C[0xB4];
|
||||
uint32_t RSA_CONFIG;
|
||||
uint32_t RSA_KEY_SIZE_REG;
|
||||
uint32_t RSA_EXP_SIZE_REG;
|
||||
uint32_t RSA_KEY_READ_DISABLE_REG;
|
||||
uint32_t RSA_KEYSLOT_FLAGS[2];
|
||||
uint32_t _0x418;
|
||||
uint32_t _0x41C;
|
||||
uint32_t RSA_KEYTABLE_ADDR;
|
||||
uint32_t RSA_KEYTABLE_DATA;
|
||||
uint8_t RSA_OUTPUT[0x100];
|
||||
uint8_t _0x528[0x2D8];
|
||||
uint32_t FLAGS_REG;
|
||||
uint32_t ERR_STATUS_REG;
|
||||
uint32_t _0x808;
|
||||
uint32_t SPARE_0;
|
||||
uint32_t _0x810;
|
||||
uint32_t SE_SE_SECURITY;
|
||||
uint32_t SE_TZRAM_SECURITY;
|
||||
uint32_t SE_OPERATION;
|
||||
uint32_t SE_INT_ENABLE;
|
||||
uint32_t SE_INT_STATUS;
|
||||
uint32_t SE_CONFIG;
|
||||
uint32_t SE_IN_LL_ADDR;
|
||||
uint32_t SE_IN_CUR_BYTE_ADDR;
|
||||
uint32_t SE_IN_CUR_LL_ID;
|
||||
uint32_t SE_OUT_LL_ADDR;
|
||||
uint32_t SE_OUT_CUR_BYTE_ADDR;
|
||||
uint32_t SE_OUT_CUR_LL_ID;
|
||||
uint32_t SE_HASH_RESULT[0x10];
|
||||
uint32_t SE_CTX_SAVE_CONFIG;
|
||||
uint32_t _0x74[0x63];
|
||||
uint32_t SE_SHA_CONFIG;
|
||||
uint32_t SE_SHA_MSG_LENGTH[0x4];
|
||||
uint32_t SE_SHA_MSG_LEFT[0x4];
|
||||
uint32_t _0x224[0x17];
|
||||
uint32_t SE_CRYPTO_SECURITY_PERKEY;
|
||||
uint32_t SE_CRYPTO_KEYTABLE_ACCESS[0x10];
|
||||
uint32_t _0x2C4[0x10];
|
||||
uint32_t SE_CRYPTO_CONFIG;
|
||||
uint32_t SE_CRYPTO_LINEAR_CTR[0x4];
|
||||
uint32_t SE_CRYPTO_LAST_BLOCK;
|
||||
uint32_t SE_CRYPTO_KEYTABLE_ADDR;
|
||||
uint32_t SE_CRYPTO_KEYTABLE_DATA;
|
||||
uint32_t _0x324[0x3];
|
||||
uint32_t SE_CRYPTO_KEYTABLE_DST;
|
||||
uint32_t _0x334[0x3];
|
||||
uint32_t SE_RNG_CONFIG;
|
||||
uint32_t SE_RNG_SRC_CONFIG;
|
||||
uint32_t SE_RNG_RESEED_INTERVAL;
|
||||
uint32_t _0x34C[0x2D];
|
||||
uint32_t SE_RSA_CONFIG;
|
||||
uint32_t SE_RSA_KEY_SIZE;
|
||||
uint32_t SE_RSA_EXP_SIZE;
|
||||
uint32_t SE_RSA_SECURITY_PERKEY;
|
||||
uint32_t SE_RSA_KEYTABLE_ACCESS[0x2];
|
||||
uint32_t _0x418[0x2];
|
||||
uint32_t SE_RSA_KEYTABLE_ADDR;
|
||||
uint32_t SE_RSA_KEYTABLE_DATA;
|
||||
uint32_t SE_RSA_OUTPUT[0x40];
|
||||
uint32_t _0x528[0xB6];
|
||||
uint32_t SE_STATUS;
|
||||
uint32_t SE_ERR_STATUS;
|
||||
uint32_t SE_MISC;
|
||||
uint32_t SE_SPARE;
|
||||
uint32_t SE_ENTROPY_DEBUG_COUNTER;
|
||||
uint32_t _0x814;
|
||||
uint32_t _0x818;
|
||||
uint32_t _0x81C;
|
||||
uint8_t _0x820[0x17E0];
|
||||
uint32_t _0x820[0x5F8];
|
||||
} tegra_se_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -26,13 +26,25 @@ static inline uintptr_t get_timers_base(void) {
|
||||
return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_TMRs_WDTs);
|
||||
}
|
||||
|
||||
static inline uintptr_t get_rtc_base(void) {
|
||||
return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC);
|
||||
}
|
||||
|
||||
#define TIMERS_BASE (get_timers_base())
|
||||
#define MAKE_TIMERS_REG(n) MAKE_REG32(TIMERS_BASE + n)
|
||||
|
||||
#define TIMERUS_CNTR_1US_0 MAKE_TIMERS_REG(0x10)
|
||||
#define TIMERUS_USEC_CFG_0 MAKE_TIMERS_REG(0x14)
|
||||
#define SHARED_INTR_STATUS_0 MAKE_TIMERS_REG(0x1A0)
|
||||
#define SHARED_TIMER_SECURE_CFG_0 MAKE_TIMERS_REG(0x1A4)
|
||||
|
||||
#define RTC_BASE (get_rtc_base())
|
||||
#define MAKE_RTC_REG(n) MAKE_REG32(RTC_BASE + n)
|
||||
|
||||
#define RTC_SECONDS MAKE_RTC_REG(0x08)
|
||||
#define RTC_SHADOW_SECONDS MAKE_RTC_REG(0x0C)
|
||||
#define RTC_MILLI_SECONDS MAKE_RTC_REG(0x10)
|
||||
|
||||
typedef struct {
|
||||
uint32_t CONFIG;
|
||||
uint32_t STATUS;
|
||||
@@ -46,10 +58,54 @@ typedef struct {
|
||||
|
||||
void wait(uint32_t microseconds);
|
||||
|
||||
static inline uint32_t get_time(void) {
|
||||
static inline uint32_t get_time_s(void) {
|
||||
return RTC_SECONDS;
|
||||
}
|
||||
|
||||
static inline uint32_t get_time_ms(void) {
|
||||
return (RTC_MILLI_SECONDS | (RTC_SHADOW_SECONDS << 10));
|
||||
}
|
||||
|
||||
static inline uint32_t get_time_us(void) {
|
||||
return TIMERUS_CNTR_1US_0;
|
||||
}
|
||||
|
||||
__attribute__ ((noreturn)) void watchdog_reboot(void);
|
||||
/**
|
||||
* Returns the time in microseconds.
|
||||
*/
|
||||
static inline uint32_t get_time(void) {
|
||||
return get_time_us();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of microseconds that have passed since a given get_time().
|
||||
*/
|
||||
static inline uint32_t get_time_since(uint32_t base) {
|
||||
return get_time_us() - base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delays for a given number of microseconds.
|
||||
*/
|
||||
static inline void udelay(uint32_t usecs) {
|
||||
uint32_t start = get_time_us();
|
||||
while (get_time_us() - start < usecs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delays until a number of usecs have passed since an absolute start time.
|
||||
*/
|
||||
static inline void udelay_absolute(uint32_t start, uint32_t usecs) {
|
||||
while (get_time_us() - start < usecs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delays for a given number of milliseconds.
|
||||
*/
|
||||
static inline void mdelay(uint32_t msecs) {
|
||||
uint32_t start = get_time_ms();
|
||||
while (get_time_ms() - start < msecs);
|
||||
}
|
||||
|
||||
__attribute__ ((noreturn)) void watchdog_reboot(void);
|
||||
#endif
|
||||
|
||||
@@ -29,7 +29,7 @@ TARGET := $(notdir $(CURDIR))
|
||||
BUILD := build
|
||||
SOURCES := src src/lib src/display
|
||||
DATA := data
|
||||
INCLUDES := include
|
||||
INCLUDES := include ../../libraries/libvapours/include
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
|
||||
@@ -13,171 +13,178 @@
|
||||
* 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 <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <vapours/ams_version.h>
|
||||
|
||||
#include "car.h"
|
||||
#include "fuse.h"
|
||||
#include "pmc.h"
|
||||
#include "timers.h"
|
||||
|
||||
/* Prototypes for internal commands. */
|
||||
void fuse_make_regs_visible(void);
|
||||
|
||||
void fuse_enable_power(void);
|
||||
void fuse_disable_power(void);
|
||||
void fuse_wait_idle(void);
|
||||
|
||||
/* Initialize the fuse driver */
|
||||
void fuse_init(void) {
|
||||
fuse_make_regs_visible();
|
||||
fuse_secondary_private_key_disable();
|
||||
fuse_disable_programming();
|
||||
|
||||
/* TODO: Overrides (iROM patches) and various reads happen here */
|
||||
}
|
||||
|
||||
/* Make all fuse registers visible */
|
||||
void fuse_make_regs_visible(void) {
|
||||
/* Make all fuse registers visible, disable the private key and disable programming. */
|
||||
clkrst_enable_fuse_regs(true);
|
||||
fuse_disable_private_key();
|
||||
fuse_disable_programming();
|
||||
}
|
||||
|
||||
/* Enable power to the fuse hardware array */
|
||||
/* Disable access to the private key and set the TZ sticky bit. */
|
||||
void fuse_disable_private_key(void) {
|
||||
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||
fuse->FUSE_PRIVATEKEYDISABLE = 0x10;
|
||||
}
|
||||
|
||||
/* Disables all fuse programming. */
|
||||
void fuse_disable_programming(void) {
|
||||
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||
fuse->FUSE_DISABLEREGPROGRAM = 1;
|
||||
}
|
||||
|
||||
/* Enable power to the fuse hardware array. */
|
||||
void fuse_enable_power(void) {
|
||||
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||
fuse->FUSE_PWR_GOOD_SW = 1;
|
||||
udelay(1);
|
||||
volatile tegra_pmc_t *pmc = pmc_get_regs();
|
||||
pmc->fuse_control &= ~(0x200); /* Clear PMC_FUSE_CTRL_PS18_LATCH_CLEAR. */
|
||||
mdelay(1);
|
||||
pmc->fuse_control |= 0x100; /* Set PMC_FUSE_CTRL_PS18_LATCH_SET. */
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
/* Disable power to the fuse hardware array */
|
||||
/* Disable power to the fuse hardware array. */
|
||||
void fuse_disable_power(void) {
|
||||
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||
fuse->FUSE_PWR_GOOD_SW = 0;
|
||||
udelay(1);
|
||||
volatile tegra_pmc_t *pmc = pmc_get_regs();
|
||||
pmc->fuse_control &= ~(0x100); /* Clear PMC_FUSE_CTRL_PS18_LATCH_SET. */
|
||||
mdelay(1);
|
||||
pmc->fuse_control |= 0x200; /* Set PMC_FUSE_CTRL_PS18_LATCH_CLEAR. */
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
/* Wait for the fuse driver to go idle */
|
||||
/* Wait for the fuse driver to go idle. */
|
||||
void fuse_wait_idle(void) {
|
||||
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||
uint32_t ctrl_val = 0;
|
||||
|
||||
/* Wait for STATE_IDLE */
|
||||
while ((ctrl_val & (0xF0000)) != 0x40000)
|
||||
{
|
||||
udelay(1);
|
||||
ctrl_val = fuse->FUSE_CTRL;
|
||||
}
|
||||
ctrl_val = fuse->FUSE_FUSECTRL;
|
||||
}
|
||||
|
||||
/* Read a fuse from the hardware array */
|
||||
/* Read a fuse from the hardware array. */
|
||||
uint32_t fuse_hw_read(uint32_t addr) {
|
||||
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||
|
||||
/* Wait for idle state. */
|
||||
fuse_wait_idle();
|
||||
|
||||
/* Program the target address */
|
||||
fuse->FUSE_REG_ADDR = addr;
|
||||
/* Program the target address. */
|
||||
fuse->FUSE_FUSEADDR = addr;
|
||||
|
||||
/* Enable read operation in control register */
|
||||
uint32_t ctrl_val = fuse->FUSE_CTRL;
|
||||
/* Enable read operation in control register. */
|
||||
uint32_t ctrl_val = fuse->FUSE_FUSECTRL;
|
||||
ctrl_val &= ~0x3;
|
||||
ctrl_val |= 0x1; /* Set FUSE_READ command */
|
||||
fuse->FUSE_CTRL = ctrl_val;
|
||||
ctrl_val |= 0x1; /* Set READ command. */
|
||||
fuse->FUSE_FUSECTRL = ctrl_val;
|
||||
|
||||
/* Wait for idle state. */
|
||||
fuse_wait_idle();
|
||||
|
||||
return fuse->FUSE_REG_READ;
|
||||
return fuse->FUSE_FUSERDATA;
|
||||
}
|
||||
|
||||
/* Write a fuse in the hardware array */
|
||||
/* Write a fuse in the hardware array. */
|
||||
void fuse_hw_write(uint32_t value, uint32_t addr) {
|
||||
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||
|
||||
/* Wait for idle state. */
|
||||
fuse_wait_idle();
|
||||
|
||||
/* Program the target address and value */
|
||||
fuse->FUSE_REG_ADDR = addr;
|
||||
fuse->FUSE_REG_WRITE = value;
|
||||
/* Program the target address and value. */
|
||||
fuse->FUSE_FUSEADDR = addr;
|
||||
fuse->FUSE_FUSEWDATA = value;
|
||||
|
||||
/* Enable write operation in control register */
|
||||
uint32_t ctrl_val = fuse->FUSE_CTRL;
|
||||
/* Enable write operation in control register. */
|
||||
uint32_t ctrl_val = fuse->FUSE_FUSECTRL;
|
||||
ctrl_val &= ~0x3;
|
||||
ctrl_val |= 0x2; /* Set FUSE_WRITE command */
|
||||
fuse->FUSE_CTRL = ctrl_val;
|
||||
ctrl_val |= 0x2; /* Set WRITE command. */
|
||||
fuse->FUSE_FUSECTRL = ctrl_val;
|
||||
|
||||
/* Wait for idle state. */
|
||||
fuse_wait_idle();
|
||||
}
|
||||
|
||||
/* Sense the fuse hardware array into the shadow cache */
|
||||
/* Sense the fuse hardware array into the shadow cache. */
|
||||
void fuse_hw_sense(void) {
|
||||
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||
|
||||
/* Wait for idle state. */
|
||||
fuse_wait_idle();
|
||||
|
||||
/* Enable sense operation in control register */
|
||||
uint32_t ctrl_val = fuse->FUSE_CTRL;
|
||||
uint32_t ctrl_val = fuse->FUSE_FUSECTRL;
|
||||
ctrl_val &= ~0x3;
|
||||
ctrl_val |= 0x3; /* Set FUSE_SENSE command */
|
||||
fuse->FUSE_CTRL = ctrl_val;
|
||||
ctrl_val |= 0x3; /* Set SENSE_CTRL command */
|
||||
fuse->FUSE_FUSECTRL = ctrl_val;
|
||||
|
||||
/* Wait for idle state. */
|
||||
fuse_wait_idle();
|
||||
}
|
||||
|
||||
/* Disables all fuse programming. */
|
||||
void fuse_disable_programming(void) {
|
||||
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||
fuse->FUSE_DIS_PGM = 1;
|
||||
}
|
||||
|
||||
/* Unknown exactly what this does, but it alters the contents read from the fuse cache. */
|
||||
void fuse_secondary_private_key_disable(void) {
|
||||
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||
fuse->FUSE_PRIVATEKEYDISABLE = 0x10;
|
||||
}
|
||||
|
||||
|
||||
/* Read the SKU info register from the shadow cache */
|
||||
/* Read the SKU info register from the shadow cache. */
|
||||
uint32_t fuse_get_sku_info(void) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
return fuse_chip->FUSE_SKU_INFO;
|
||||
}
|
||||
|
||||
/* Read the bootrom patch version from a register in the shadow cache */
|
||||
/* Read the bootrom patch version from a register in the shadow cache. */
|
||||
uint32_t fuse_get_bootrom_patch_version(void) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
return fuse_chip->FUSE_SOC_SPEEDO_1;
|
||||
return fuse_chip->FUSE_SOC_SPEEDO_1_CALIB;
|
||||
}
|
||||
|
||||
/* Read a spare bit register from the shadow cache */
|
||||
uint32_t fuse_get_spare_bit(uint32_t idx) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
|
||||
if (idx >= 32) {
|
||||
if (idx < 32) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
return fuse_chip->FUSE_SPARE_BIT[idx];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return fuse_chip->FUSE_SPARE_BIT[idx];
|
||||
}
|
||||
|
||||
/* Read a reserved ODM register from the shadow cache */
|
||||
/* Read a reserved ODM register from the shadow cache. */
|
||||
uint32_t fuse_get_reserved_odm(uint32_t idx) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
|
||||
if (idx >= 8) {
|
||||
if (idx < 8) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
return fuse_chip->FUSE_RESERVED_ODM[idx];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return fuse_chip->FUSE_RESERVED_ODM[idx];
|
||||
}
|
||||
|
||||
/* Derive the Device ID using values in the shadow cache */
|
||||
/* Get the DRAM ID using values in the shadow cache. */
|
||||
uint32_t fuse_get_dram_id(void) {
|
||||
return ((fuse_get_reserved_odm(4) >> 3) & 0x7);
|
||||
}
|
||||
|
||||
/* Derive the Device ID using values in the shadow cache. */
|
||||
uint64_t fuse_get_device_id(void) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
|
||||
|
||||
uint64_t device_id = 0;
|
||||
uint64_t y_coord = fuse_chip->FUSE_Y_COORDINATE & 0x1FF;
|
||||
uint64_t x_coord = fuse_chip->FUSE_X_COORDINATE & 0x1FF;
|
||||
uint64_t wafer_id = fuse_chip->FUSE_WAFER_ID & 0x3F;
|
||||
uint32_t lot_code = fuse_chip->FUSE_LOT_CODE_0;
|
||||
uint64_t fab_code = fuse_chip->FUSE_FAB_CODE & 0x3F;
|
||||
uint64_t y_coord = fuse_chip->FUSE_OPT_Y_COORDINATE & 0x1FF;
|
||||
uint64_t x_coord = fuse_chip->FUSE_OPT_X_COORDINATE & 0x1FF;
|
||||
uint64_t wafer_id = fuse_chip->FUSE_OPT_WAFER_ID & 0x3F;
|
||||
uint32_t lot_code = fuse_chip->FUSE_OPT_LOT_CODE_0;
|
||||
uint64_t fab_code = fuse_chip->FUSE_OPT_FAB_CODE & 0x3F;
|
||||
|
||||
uint64_t derived_lot_code = 0;
|
||||
for (unsigned int i = 0; i < 5; i++) {
|
||||
derived_lot_code = (derived_lot_code * 0x24) + ((lot_code >> (24 - 6*i)) & 0x3F);
|
||||
@@ -189,45 +196,41 @@ uint64_t fuse_get_device_id(void) {
|
||||
device_id |= wafer_id << 18;
|
||||
device_id |= derived_lot_code << 24;
|
||||
device_id |= fab_code << 50;
|
||||
|
||||
return device_id;
|
||||
}
|
||||
|
||||
/* Get the DRAM ID using values in the shadow cache */
|
||||
uint32_t fuse_get_dram_id(void) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
return (fuse_chip->FUSE_RESERVED_ODM[4] >> 3) & 0x7;
|
||||
}
|
||||
/* Derive the Hardware Type using values in the shadow cache. */
|
||||
uint32_t fuse_get_hardware_type(uint32_t target_firmware) {
|
||||
uint32_t fuse_reserved_odm4 = fuse_get_reserved_odm(4);
|
||||
uint32_t hardware_type = (((fuse_reserved_odm4 >> 7) & 2) | ((fuse_reserved_odm4 >> 2) & 1));
|
||||
|
||||
/* Derive the Hardware Type using values in the shadow cache */
|
||||
uint32_t fuse_get_hardware_type(void) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
|
||||
/* This function is very different between 4.x and < 4.x */
|
||||
uint32_t hardware_type = ((fuse_chip->FUSE_RESERVED_ODM[4] >> 7) & 2) | ((fuse_chip->FUSE_RESERVED_ODM[4] >> 2) & 1);
|
||||
|
||||
/* TODO: choose; if (mkey_get_revision() >= MASTERKEY_REVISION_400_CURRENT) {
|
||||
static const uint32_t types[] = {0,1,4,3};
|
||||
|
||||
hardware_type |= (fuse_chip->FUSE_RESERVED_ODM[4] >> 14) & 0x3C;
|
||||
hardware_type--;
|
||||
return hardware_type > 3 ? 4 : types[hardware_type];
|
||||
} else {*/
|
||||
/* Firmware from versions 1.0.0 to 3.0.2. */
|
||||
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
if (hardware_type >= 1) {
|
||||
return hardware_type > 2 ? 3 : hardware_type - 1;
|
||||
return (hardware_type > 2) ? 3 : hardware_type - 1;
|
||||
} else if ((fuse_chip->FUSE_SPARE_BIT[9] & 1) == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return 3;
|
||||
}
|
||||
// }
|
||||
} else if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_700) { /* Firmware versions from 4.0.0 to 6.2.0. */
|
||||
static const uint32_t types[] = {0,1,4,3};
|
||||
hardware_type |= ((fuse_reserved_odm4 >> 14) & 0x3C);
|
||||
hardware_type--;
|
||||
return (hardware_type > 3) ? 4 : types[hardware_type];
|
||||
} else { /* Firmware versions from 7.0.0 onwards. */
|
||||
/* Always return 0 in retail. */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Derive the Retail Type using values in the shadow cache */
|
||||
/* Derive the Retail Type using values in the shadow cache. */
|
||||
uint32_t fuse_get_retail_type(void) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
|
||||
/* Retail type = IS_RETAIL | UNIT_TYPE */
|
||||
uint32_t retail_type = ((fuse_chip->FUSE_RESERVED_ODM[4] >> 7) & 4) | (fuse_chip->FUSE_RESERVED_ODM[4] & 3);
|
||||
/* Retail Type = IS_RETAIL | UNIT_TYPE. */
|
||||
uint32_t fuse_reserved_odm4 = fuse_get_reserved_odm(4);
|
||||
uint32_t retail_type = (((fuse_reserved_odm4 >> 7) & 4) | (fuse_reserved_odm4 & 3));
|
||||
if (retail_type == 4) { /* Standard retail unit, IS_RETAIL | 0. */
|
||||
return 1;
|
||||
} else if (retail_type == 3) { /* Standard dev unit, 0 | DEV_UNIT. */
|
||||
@@ -241,17 +244,17 @@ void fuse_get_hardware_info(void *dst) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
uint32_t hw_info[0x4];
|
||||
|
||||
uint32_t unk_hw_fuse = fuse_chip->_0x120 & 0x3F;
|
||||
uint32_t y_coord = fuse_chip->FUSE_Y_COORDINATE & 0x1FF;
|
||||
uint32_t x_coord = fuse_chip->FUSE_X_COORDINATE & 0x1FF;
|
||||
uint32_t wafer_id = fuse_chip->FUSE_WAFER_ID & 0x3F;
|
||||
uint32_t lot_code_0 = fuse_chip->FUSE_LOT_CODE_0;
|
||||
uint32_t lot_code_1 = fuse_chip->FUSE_LOT_CODE_1 & 0x0FFFFFFF;
|
||||
uint32_t fab_code = fuse_chip->FUSE_FAB_CODE & 0x3F;
|
||||
uint32_t vendor_code = fuse_chip->FUSE_VENDOR_CODE & 0xF;
|
||||
uint32_t ops_reserved = fuse_chip->FUSE_OPT_OPS_RESERVED & 0x3F;
|
||||
uint32_t y_coord = fuse_chip->FUSE_OPT_Y_COORDINATE & 0x1FF;
|
||||
uint32_t x_coord = fuse_chip->FUSE_OPT_X_COORDINATE & 0x1FF;
|
||||
uint32_t wafer_id = fuse_chip->FUSE_OPT_WAFER_ID & 0x3F;
|
||||
uint32_t lot_code_0 = fuse_chip->FUSE_OPT_LOT_CODE_0;
|
||||
uint32_t lot_code_1 = fuse_chip->FUSE_OPT_LOT_CODE_1 & 0x0FFFFFFF;
|
||||
uint32_t fab_code = fuse_chip->FUSE_OPT_FAB_CODE & 0x3F;
|
||||
uint32_t vendor_code = fuse_chip->FUSE_OPT_VENDOR_CODE & 0xF;
|
||||
|
||||
/* Hardware Info = unk_hw_fuse || Y_COORD || X_COORD || WAFER_ID || LOT_CODE || FAB_CODE || VENDOR_ID */
|
||||
hw_info[0] = (uint32_t)((lot_code_1 << 30) | (wafer_id << 24) | (x_coord << 15) | (y_coord << 6) | (unk_hw_fuse));
|
||||
/* Hardware Info = OPS_RESERVED || Y_COORD || X_COORD || WAFER_ID || LOT_CODE || FAB_CODE || VENDOR_ID */
|
||||
hw_info[0] = (uint32_t)((lot_code_1 << 30) | (wafer_id << 24) | (x_coord << 15) | (y_coord << 6) | (ops_reserved));
|
||||
hw_info[1] = (uint32_t)((lot_code_0 << 26) | (lot_code_1 >> 2));
|
||||
hw_info[2] = (uint32_t)((fab_code << 26) | (lot_code_0 >> 6));
|
||||
hw_info[3] = (uint32_t)(vendor_code);
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* 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 FUSEE_FUSE_H
|
||||
#define FUSEE_FUSE_H
|
||||
|
||||
@@ -23,154 +23,167 @@
|
||||
#define MAKE_FUSE_CHIP_REG(n) MAKE_REG32(FUSE_CHIP_BASE + n)
|
||||
|
||||
typedef struct {
|
||||
uint32_t FUSE_CTRL;
|
||||
uint32_t FUSE_REG_ADDR;
|
||||
uint32_t FUSE_REG_READ;
|
||||
uint32_t FUSE_REG_WRITE;
|
||||
uint32_t FUSE_TIME_RD1;
|
||||
uint32_t FUSE_TIME_RD2;
|
||||
uint32_t FUSE_TIME_PGM1;
|
||||
uint32_t FUSE_TIME_PGM2;
|
||||
uint32_t FUSE_PRIV2INTFC;
|
||||
uint32_t FUSE_FUSECTRL;
|
||||
uint32_t FUSE_FUSEADDR;
|
||||
uint32_t FUSE_FUSERDATA;
|
||||
uint32_t FUSE_FUSEWDATA;
|
||||
uint32_t FUSE_FUSETIME_RD1;
|
||||
uint32_t FUSE_FUSETIME_RD2;
|
||||
uint32_t FUSE_FUSETIME_PGM1;
|
||||
uint32_t FUSE_FUSETIME_PGM2;
|
||||
uint32_t FUSE_PRIV2INTFC_START;
|
||||
uint32_t FUSE_FUSEBYPASS;
|
||||
uint32_t FUSE_PRIVATEKEYDISABLE;
|
||||
uint32_t FUSE_DIS_PGM;
|
||||
uint32_t FUSE_WRITE_ACCESS;
|
||||
uint32_t FUSE_DISABLEREGPROGRAM;
|
||||
uint32_t FUSE_WRITE_ACCESS_SW;
|
||||
uint32_t FUSE_PWR_GOOD_SW;
|
||||
uint32_t _0x38[0x32];
|
||||
uint32_t _0x38;
|
||||
uint32_t FUSE_PRIV2RESHIFT;
|
||||
uint32_t _0x40[0x3];
|
||||
uint32_t FUSE_FUSETIME_RD3;
|
||||
uint32_t _0x50[0xC];
|
||||
uint32_t FUSE_PRIVATE_KEY0_NONZERO;
|
||||
uint32_t FUSE_PRIVATE_KEY1_NONZERO;
|
||||
uint32_t FUSE_PRIVATE_KEY2_NONZERO;
|
||||
uint32_t FUSE_PRIVATE_KEY3_NONZERO;
|
||||
uint32_t FUSE_PRIVATE_KEY4_NONZERO;
|
||||
uint32_t _0x90[0x1C];
|
||||
} tegra_fuse_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t FUSE_PRODUCTION_MODE;
|
||||
uint32_t _0x4;
|
||||
uint32_t _0x8;
|
||||
uint32_t _0xC;
|
||||
uint32_t FUSE_JTAG_SECUREID_VALID;
|
||||
uint32_t FUSE_ODM_LOCK;
|
||||
uint32_t FUSE_OPT_OPENGL_EN;
|
||||
uint32_t FUSE_SKU_INFO;
|
||||
uint32_t FUSE_CPU_SPEEDO_0;
|
||||
uint32_t FUSE_CPU_IDDQ;
|
||||
uint32_t _0x1C;
|
||||
uint32_t _0x20;
|
||||
uint32_t _0x24;
|
||||
uint32_t FUSE_FT_REV;
|
||||
uint32_t FUSE_CPU_SPEEDO_1;
|
||||
uint32_t FUSE_CPU_SPEEDO_2;
|
||||
uint32_t FUSE_SOC_SPEEDO_0;
|
||||
uint32_t FUSE_SOC_SPEEDO_1;
|
||||
uint32_t FUSE_SOC_SPEEDO_2;
|
||||
uint32_t FUSE_SOC_IDDQ;
|
||||
uint32_t _0x44;
|
||||
uint32_t FUSE_CPU_SPEEDO_0_CALIB;
|
||||
uint32_t FUSE_CPU_IDDQ_CALIB;
|
||||
uint32_t FUSE_DAC_CRT_CALIB;
|
||||
uint32_t FUSE_DAC_HDTV_CALIB;
|
||||
uint32_t FUSE_DAC_SDTV_CALIB;
|
||||
uint32_t FUSE_OPT_FT_REV;
|
||||
uint32_t FUSE_CPU_SPEEDO_1_CALIB;
|
||||
uint32_t FUSE_CPU_SPEEDO_2_CALIB;
|
||||
uint32_t FUSE_SOC_SPEEDO_0_CALIB;
|
||||
uint32_t FUSE_SOC_SPEEDO_1_CALIB;
|
||||
uint32_t FUSE_SOC_SPEEDO_2_CALIB;
|
||||
uint32_t FUSE_SOC_IDDQ_CALIB;
|
||||
uint32_t FUSE_RESERVED_PRODUCTION_WP;
|
||||
uint32_t FUSE_FA;
|
||||
uint32_t _0x4C;
|
||||
uint32_t _0x50;
|
||||
uint32_t _0x54;
|
||||
uint32_t _0x58;
|
||||
uint32_t _0x5C;
|
||||
uint32_t _0x60;
|
||||
uint32_t FUSE_RESERVED_PRODUCTION;
|
||||
uint32_t FUSE_HDMI_LANE0_CALIB;
|
||||
uint32_t FUSE_HDMI_LANE1_CALIB;
|
||||
uint32_t FUSE_HDMI_LANE2_CALIB;
|
||||
uint32_t FUSE_HDMI_LANE3_CALIB;
|
||||
uint32_t FUSE_ENCRYPTION_RATE;
|
||||
uint32_t FUSE_PUBLIC_KEY[0x8];
|
||||
uint32_t FUSE_TSENSOR_1;
|
||||
uint32_t FUSE_TSENSOR_2;
|
||||
uint32_t _0x8C;
|
||||
uint32_t FUSE_CP_REV;
|
||||
uint32_t _0x94;
|
||||
uint32_t FUSE_TSENSOR_0;
|
||||
uint32_t FUSE_FIRST_BOOTROM_PATCH_SIZE_REG;
|
||||
uint32_t FUSE_TSENSOR1_CALIB;
|
||||
uint32_t FUSE_TSENSOR2_CALIB;
|
||||
uint32_t FUSE_VSENSOR_CALIB;
|
||||
uint32_t FUSE_OPT_CP_REV;
|
||||
uint32_t FUSE_OPT_PFG;
|
||||
uint32_t FUSE_TSENSOR0_CALIB;
|
||||
uint32_t FUSE_FIRST_BOOTROM_PATCH_SIZE;
|
||||
uint32_t FUSE_SECURITY_MODE;
|
||||
uint32_t FUSE_PRIVATE_KEY[0x4];
|
||||
uint32_t FUSE_DEVICE_KEY;
|
||||
uint32_t _0xB8;
|
||||
uint32_t _0xBC;
|
||||
uint32_t FUSE_PRIVATE_KEY[0x5];
|
||||
uint32_t FUSE_ARM_JTAG_DIS;
|
||||
uint32_t FUSE_BOOT_DEVICE_INFO;
|
||||
uint32_t FUSE_RESERVED_SW;
|
||||
uint32_t FUSE_VP8_ENABLE;
|
||||
uint32_t FUSE_OPT_VP9_DISABLE;
|
||||
uint32_t FUSE_RESERVED_ODM[0x8];
|
||||
uint32_t _0xE8;
|
||||
uint32_t _0xEC;
|
||||
uint32_t FUSE_SKU_USB_CALIB;
|
||||
uint32_t FUSE_OBS_DIS;
|
||||
uint32_t FUSE_NOR_INFO;
|
||||
uint32_t FUSE_USB_CALIB;
|
||||
uint32_t FUSE_SKU_DIRECT_CONFIG;
|
||||
uint32_t _0xF8;
|
||||
uint32_t _0xFC;
|
||||
uint32_t FUSE_VENDOR_CODE;
|
||||
uint32_t FUSE_FAB_CODE;
|
||||
uint32_t FUSE_LOT_CODE_0;
|
||||
uint32_t FUSE_LOT_CODE_1;
|
||||
uint32_t FUSE_WAFER_ID;
|
||||
uint32_t FUSE_X_COORDINATE;
|
||||
uint32_t FUSE_Y_COORDINATE;
|
||||
uint32_t _0x11C;
|
||||
uint32_t _0x120;
|
||||
uint32_t FUSE_KFUSE_PRIVKEY_CTRL;
|
||||
uint32_t FUSE_PACKAGE_INFO;
|
||||
uint32_t FUSE_OPT_VENDOR_CODE;
|
||||
uint32_t FUSE_OPT_FAB_CODE;
|
||||
uint32_t FUSE_OPT_LOT_CODE_0;
|
||||
uint32_t FUSE_OPT_LOT_CODE_1;
|
||||
uint32_t FUSE_OPT_WAFER_ID;
|
||||
uint32_t FUSE_OPT_X_COORDINATE;
|
||||
uint32_t FUSE_OPT_Y_COORDINATE;
|
||||
uint32_t FUSE_OPT_SEC_DEBUG_EN;
|
||||
uint32_t FUSE_OPT_OPS_RESERVED;
|
||||
uint32_t FUSE_SATA_CALIB;
|
||||
uint32_t FUSE_GPU_IDDQ;
|
||||
uint32_t FUSE_TSENSOR_3;
|
||||
uint32_t _0x130;
|
||||
uint32_t _0x134;
|
||||
uint32_t _0x138;
|
||||
uint32_t _0x13C;
|
||||
uint32_t _0x140;
|
||||
uint32_t _0x144;
|
||||
uint32_t FUSE_GPU_IDDQ_CALIB;
|
||||
uint32_t FUSE_TSENSOR3_CALIB;
|
||||
uint32_t FUSE_SKU_BOND_OUT_L;
|
||||
uint32_t FUSE_SKU_BOND_OUT_H;
|
||||
uint32_t FUSE_SKU_BOND_OUT_U;
|
||||
uint32_t FUSE_SKU_BOND_OUT_V;
|
||||
uint32_t FUSE_SKU_BOND_OUT_W;
|
||||
uint32_t FUSE_OPT_SAMPLE_TYPE;
|
||||
uint32_t FUSE_OPT_SUBREVISION;
|
||||
uint32_t _0x14C;
|
||||
uint32_t _0x150;
|
||||
uint32_t FUSE_TSENSOR_4;
|
||||
uint32_t FUSE_TSENSOR_5;
|
||||
uint32_t FUSE_TSENSOR_6;
|
||||
uint32_t FUSE_TSENSOR_7;
|
||||
uint32_t FUSE_OPT_PRIV_SEC_DIS;
|
||||
uint32_t FUSE_OPT_SW_RESERVED_0;
|
||||
uint32_t FUSE_OPT_SW_RESERVED_1;
|
||||
uint32_t FUSE_TSENSOR4_CALIB;
|
||||
uint32_t FUSE_TSENSOR5_CALIB;
|
||||
uint32_t FUSE_TSENSOR6_CALIB;
|
||||
uint32_t FUSE_TSENSOR7_CALIB;
|
||||
uint32_t FUSE_OPT_PRIV_SEC_EN;
|
||||
uint32_t FUSE_PKC_DISABLE;
|
||||
uint32_t _0x16C;
|
||||
uint32_t _0x170;
|
||||
uint32_t _0x174;
|
||||
uint32_t _0x178;
|
||||
uint32_t _0x17C;
|
||||
uint32_t FUSE_FUSE2TSEC_DEBUG_DISABLE;
|
||||
uint32_t FUSE_TSENSOR_COMMON;
|
||||
uint32_t _0x184;
|
||||
uint32_t _0x188;
|
||||
uint32_t _0x18C;
|
||||
uint32_t _0x190;
|
||||
uint32_t FUSE_OPT_CP_BIN;
|
||||
uint32_t FUSE_OPT_GPU_DISABLE;
|
||||
uint32_t FUSE_OPT_FT_BIN;
|
||||
uint32_t FUSE_OPT_DONE_MAP;
|
||||
uint32_t _0x194;
|
||||
uint32_t _0x198;
|
||||
uint32_t FUSE_DEBUG_AUTH_OVERRIDE;
|
||||
uint32_t FUSE_APB2JTAG_DISABLE;
|
||||
uint32_t FUSE_ODM_INFO;
|
||||
uint32_t _0x1A0;
|
||||
uint32_t _0x1A4;
|
||||
uint32_t _0x1A8;
|
||||
uint32_t FUSE_ARM_CRYPT_DE_FEATURE;
|
||||
uint32_t _0x1AC;
|
||||
uint32_t _0x1B0;
|
||||
uint32_t _0x1B4;
|
||||
uint32_t _0x1B8;
|
||||
uint32_t _0x1BC;
|
||||
uint32_t _0x1D0;
|
||||
uint32_t FUSE_TSENSOR_8;
|
||||
uint32_t FUSE_WOA_SKU_FLAG;
|
||||
uint32_t FUSE_ECO_RESERVE_1;
|
||||
uint32_t FUSE_GCPLEX_CONFIG_FUSE;
|
||||
uint32_t FUSE_PRODUCTION_MONTH;
|
||||
uint32_t FUSE_RAM_REPAIR_INDICATOR;
|
||||
uint32_t FUSE_TSENSOR9_CALIB;
|
||||
uint32_t _0x1D8;
|
||||
uint32_t _0x1DC;
|
||||
uint32_t _0x1E0;
|
||||
uint32_t _0x1E4;
|
||||
uint32_t _0x1E8;
|
||||
uint32_t _0x1EC;
|
||||
uint32_t _0x1F0;
|
||||
uint32_t _0x1F4;
|
||||
uint32_t _0x1F8;
|
||||
uint32_t FUSE_VMIN_CALIBRATION;
|
||||
uint32_t FUSE_AGING_SENSOR_CALIBRATION;
|
||||
uint32_t FUSE_DEBUG_AUTHENTICATION;
|
||||
uint32_t FUSE_SECURE_PROVISION_INDEX;
|
||||
uint32_t FUSE_SECURE_PROVISION_INFO;
|
||||
uint32_t FUSE_OPT_GPU_DISABLE_CP1;
|
||||
uint32_t FUSE_SPARE_ENDIS;
|
||||
uint32_t FUSE_ECO_RESERVE_0;
|
||||
uint32_t _0x1FC;
|
||||
uint32_t _0x200;
|
||||
uint32_t FUSE_RESERVED_CALIB;
|
||||
uint32_t _0x208;
|
||||
uint32_t _0x20C;
|
||||
uint32_t _0x210;
|
||||
uint32_t _0x214;
|
||||
uint32_t _0x218;
|
||||
uint32_t FUSE_TSENSOR_9;
|
||||
uint32_t _0x220;
|
||||
uint32_t _0x224;
|
||||
uint32_t _0x228;
|
||||
uint32_t _0x22C;
|
||||
uint32_t _0x230;
|
||||
uint32_t _0x234;
|
||||
uint32_t _0x238;
|
||||
uint32_t _0x23C;
|
||||
uint32_t _0x240;
|
||||
uint32_t _0x244;
|
||||
uint32_t _0x248;
|
||||
uint32_t _0x24C;
|
||||
uint32_t FUSE_RESERVED_CALIB0;
|
||||
uint32_t FUSE_RESERVED_CALIB1;
|
||||
uint32_t FUSE_OPT_GPU_TPC0_DISABLE;
|
||||
uint32_t FUSE_OPT_GPU_TPC0_DISABLE_CP1;
|
||||
uint32_t FUSE_OPT_CPU_DISABLE;
|
||||
uint32_t FUSE_OPT_CPU_DISABLE_CP1;
|
||||
uint32_t FUSE_TSENSOR10_CALIB;
|
||||
uint32_t FUSE_TSENSOR10_CALIB_AUX;
|
||||
uint32_t FUSE_OPT_RAM_SVOP_DP;
|
||||
uint32_t FUSE_OPT_RAM_SVOP_PDP;
|
||||
uint32_t FUSE_OPT_RAM_SVOP_REG;
|
||||
uint32_t FUSE_OPT_RAM_SVOP_SP;
|
||||
uint32_t FUSE_OPT_RAM_SVOP_SMPDP;
|
||||
uint32_t FUSE_OPT_GPU_TPC0_DISABLE_CP2;
|
||||
uint32_t FUSE_OPT_GPU_TPC1_DISABLE;
|
||||
uint32_t FUSE_OPT_GPU_TPC1_DISABLE_CP1;
|
||||
uint32_t FUSE_OPT_GPU_TPC1_DISABLE_CP2;
|
||||
uint32_t FUSE_OPT_CPU_DISABLE_CP2;
|
||||
uint32_t FUSE_OPT_GPU_DISABLE_CP2;
|
||||
uint32_t FUSE_USB_CALIB_EXT;
|
||||
uint32_t _0x254;
|
||||
uint32_t _0x258;
|
||||
uint32_t FUSE_RESERVED_FIELD;
|
||||
uint32_t FUSE_OPT_ECC_EN;
|
||||
uint32_t _0x25C;
|
||||
uint32_t _0x260;
|
||||
uint32_t _0x264;
|
||||
@@ -179,35 +192,36 @@ typedef struct {
|
||||
uint32_t _0x270;
|
||||
uint32_t _0x274;
|
||||
uint32_t _0x278;
|
||||
uint32_t _0x27C;
|
||||
uint32_t FUSE_SPARE_REALIGNMENT_REG;
|
||||
uint32_t FUSE_SPARE_BIT[0x20];
|
||||
} tegra_fuse_chip_t;
|
||||
|
||||
static inline volatile tegra_fuse_t *fuse_get_regs(void) {
|
||||
static inline volatile tegra_fuse_t *fuse_get_regs(void)
|
||||
{
|
||||
return (volatile tegra_fuse_t *)FUSE_BASE;
|
||||
}
|
||||
|
||||
static inline volatile tegra_fuse_chip_t *fuse_chip_get_regs(void) {
|
||||
static inline volatile tegra_fuse_chip_t *fuse_chip_get_regs(void)
|
||||
{
|
||||
return (volatile tegra_fuse_chip_t *)FUSE_CHIP_BASE;
|
||||
}
|
||||
|
||||
void fuse_init(void);
|
||||
|
||||
uint32_t fuse_hw_read(uint32_t addr);
|
||||
void fuse_hw_write(uint32_t value, uint32_t addr);
|
||||
void fuse_hw_sense(void);
|
||||
void fuse_disable_programming(void);
|
||||
void fuse_secondary_private_key_disable(void);
|
||||
void fuse_disable_private_key(void);
|
||||
|
||||
uint32_t fuse_get_sku_info(void);
|
||||
uint32_t fuse_get_spare_bit(uint32_t idx);
|
||||
uint32_t fuse_get_reserved_odm(uint32_t idx);
|
||||
|
||||
uint32_t fuse_get_bootrom_patch_version(void);
|
||||
uint64_t fuse_get_device_id(void);
|
||||
uint32_t fuse_get_dram_id(void);
|
||||
uint32_t fuse_get_hardware_type(void);
|
||||
uint32_t fuse_get_hardware_type(uint32_t target_firmware);
|
||||
uint32_t fuse_get_retail_type(void);
|
||||
void fuse_get_hardware_info(void *dst);
|
||||
|
||||
uint32_t fuse_hw_read(uint32_t addr);
|
||||
void fuse_hw_write(uint32_t value, uint32_t addr);
|
||||
void fuse_hw_sense(void);
|
||||
|
||||
#endif
|
||||
|
||||
626
fusee/fusee-mtc/src/pmc.h
Normal file
626
fusee/fusee-mtc/src/pmc.h
Normal file
@@ -0,0 +1,626 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||
*
|
||||
* 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 FUSEE_PMC_H
|
||||
#define FUSEE_PMC_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define PMC_BASE 0x7000E400
|
||||
#define MAKE_PMC_REG(n) MAKE_REG32(PMC_BASE + n)
|
||||
|
||||
#define PMC_CONTROL_SDMMC1 (1 << 12)
|
||||
#define PMC_CONTROL_SDMMC3 (1 << 13)
|
||||
#define PMC_CONTROL_SDMMC4 (1 << 14)
|
||||
|
||||
#define APBDEV_PMC_CONTROL MAKE_PMC_REG(0x00)
|
||||
#define APBDEV_PM_0 MAKE_PMC_REG(0x14)
|
||||
#define APBDEV_PMC_DPD_ENABLE_0 MAKE_PMC_REG(0x24)
|
||||
#define APBDEV_PMC_PWRGATE_TOGGLE_0 MAKE_PMC_REG(0x30)
|
||||
#define APBDEV_PMC_PWRGATE_STATUS_0 MAKE_PMC_REG(0x38)
|
||||
#define APBDEV_PMC_NO_IOPOWER_0 MAKE_PMC_REG(0x44)
|
||||
#define APBDEV_PMC_SCRATCH0_0 MAKE_PMC_REG(0x50)
|
||||
#define APBDEV_PMC_SCRATCH1_0 MAKE_PMC_REG(0x54)
|
||||
#define APBDEV_PMC_SCRATCH20_0 MAKE_PMC_REG(0xA0)
|
||||
#define APBDEV_PMC_PWR_DET_VAL_0 MAKE_PMC_REG(0xE4)
|
||||
#define APBDEV_PMC_DDR_PWR_0 MAKE_PMC_REG(0xE8)
|
||||
#define APBDEV_PMC_CRYPTO_OP_0 MAKE_PMC_REG(0xF4)
|
||||
#define APBDEV_PMC_WAKE2_STATUS_0 MAKE_PMC_REG(0x168)
|
||||
#define APBDEV_PMC_OSC_EDPD_OVER_0 MAKE_PMC_REG(0x1A4)
|
||||
#define APBDEV_PMC_RST_STATUS_0 MAKE_PMC_REG(0x1B4)
|
||||
#define APBDEV_PMC_IO_DPD_REQ_0 MAKE_PMC_REG(0x1B8)
|
||||
#define APBDEV_PMC_IO_DPD2_REQ_0 MAKE_PMC_REG(0x1C0)
|
||||
#define APBDEV_PMC_VDDP_SEL_0 MAKE_PMC_REG(0x1CC)
|
||||
#define APBDEV_PMC_SCRATCH49_0 MAKE_PMC_REG(0x244)
|
||||
#define APBDEV_PMC_TSC_MULT_0 MAKE_PMC_REG(0x2B4)
|
||||
#define APBDEV_PMC_REG_SHORT_0 MAKE_PMC_REG(0x2CC)
|
||||
#define APBDEV_PMC_WEAK_BIAS_0 MAKE_PMC_REG(0x2C8)
|
||||
#define APBDEV_PMC_SECURE_SCRATCH21_0 MAKE_PMC_REG(0x334)
|
||||
#define APBDEV_PMC_SECURE_SCRATCH32_0 MAKE_PMC_REG(0x360)
|
||||
#define APBDEV_PMC_SECURE_SCRATCH49_0 MAKE_PMC_REG(0x3A4)
|
||||
#define APBDEV_PMC_CNTRL2_0 MAKE_PMC_REG(0x440)
|
||||
#define APBDEV_PMC_IO_DPD4_REQ_0 MAKE_PMC_REG(0x464)
|
||||
#define APBDEV_PMC_UTMIP_PAD_CFG1_0 MAKE_PMC_REG(0x4C4)
|
||||
#define APBDEV_PMC_UTMIP_PAD_CFG3_0 MAKE_PMC_REG(0x4CC)
|
||||
#define APBDEV_PMC_DDR_CNTRL_0 MAKE_PMC_REG(0x4E4)
|
||||
#define APBDEV_PMC_SCRATCH43_0 MAKE_PMC_REG(0x22C)
|
||||
#define APBDEV_PMC_SCRATCH188_0 MAKE_PMC_REG(0x810)
|
||||
#define APBDEV_PMC_SCRATCH190_0 MAKE_PMC_REG(0x818)
|
||||
#define APBDEV_PMC_SCRATCH200_0 MAKE_PMC_REG(0x840)
|
||||
|
||||
#define APBDEV_PMC_SCRATCH45_0 MAKE_PMC_REG(0x234)
|
||||
#define APBDEV_PMC_SCRATCH46_0 MAKE_PMC_REG(0x238)
|
||||
#define APBDEV_PMC_SCRATCH33_0 MAKE_PMC_REG(0x120)
|
||||
#define APBDEV_PMC_SCRATCH40_0 MAKE_PMC_REG(0x13C)
|
||||
|
||||
typedef struct {
|
||||
uint32_t cntrl;
|
||||
uint32_t sec_disable;
|
||||
uint32_t pmc_swrst;
|
||||
uint32_t wake_mask;
|
||||
uint32_t wake_lvl;
|
||||
uint32_t wake_status;
|
||||
uint32_t sw_wake_status;
|
||||
uint32_t dpd_pads_oride;
|
||||
uint32_t dpd_sample;
|
||||
uint32_t dpd_enable;
|
||||
uint32_t pwrgate_timer_off;
|
||||
uint32_t clamp_status;
|
||||
uint32_t pwrgate_toggle;
|
||||
uint32_t remove_clamping;
|
||||
uint32_t pwrgate_status;
|
||||
uint32_t pwrgood_timer;
|
||||
uint32_t blink_timer;
|
||||
uint32_t no_iopower;
|
||||
uint32_t pwr_det;
|
||||
uint32_t pwr_det_latch;
|
||||
uint32_t scratch0;
|
||||
uint32_t scratch1;
|
||||
uint32_t scratch2;
|
||||
uint32_t scratch3;
|
||||
uint32_t scratch4;
|
||||
uint32_t scratch5;
|
||||
uint32_t scratch6;
|
||||
uint32_t scratch7;
|
||||
uint32_t scratch8;
|
||||
uint32_t scratch9;
|
||||
uint32_t scratch10;
|
||||
uint32_t scratch11;
|
||||
uint32_t scratch12;
|
||||
uint32_t scratch13;
|
||||
uint32_t scratch14;
|
||||
uint32_t scratch15;
|
||||
uint32_t scratch16;
|
||||
uint32_t scratch17;
|
||||
uint32_t scratch18;
|
||||
uint32_t scratch19;
|
||||
uint32_t scratch20;
|
||||
uint32_t scratch21;
|
||||
uint32_t scratch22;
|
||||
uint32_t scratch23;
|
||||
uint32_t secure_scratch0;
|
||||
uint32_t secure_scratch1;
|
||||
uint32_t secure_scratch2;
|
||||
uint32_t secure_scratch3;
|
||||
uint32_t secure_scratch4;
|
||||
uint32_t secure_scratch5;
|
||||
uint32_t cpupwrgood_timer;
|
||||
uint32_t cpupwroff_timer;
|
||||
uint32_t pg_mask;
|
||||
uint32_t pg_mask_1;
|
||||
uint32_t auto_wake_lvl;
|
||||
uint32_t auto_wake_lvl_mask;
|
||||
uint32_t wake_delay;
|
||||
uint32_t pwr_det_val;
|
||||
uint32_t ddr_pwr;
|
||||
uint32_t usb_debounce_del;
|
||||
uint32_t usb_ao;
|
||||
uint32_t crypto_op;
|
||||
uint32_t pllp_wb0_override;
|
||||
uint32_t scratch24;
|
||||
uint32_t scratch25;
|
||||
uint32_t scratch26;
|
||||
uint32_t scratch27;
|
||||
uint32_t scratch28;
|
||||
uint32_t scratch29;
|
||||
uint32_t scratch30;
|
||||
uint32_t scratch31;
|
||||
uint32_t scratch32;
|
||||
uint32_t scratch33;
|
||||
uint32_t scratch34;
|
||||
uint32_t scratch35;
|
||||
uint32_t scratch36;
|
||||
uint32_t scratch37;
|
||||
uint32_t scratch38;
|
||||
uint32_t scratch39;
|
||||
uint32_t scratch40;
|
||||
uint32_t scratch41;
|
||||
uint32_t scratch42;
|
||||
uint32_t bo_mirror0;
|
||||
uint32_t bo_mirror1;
|
||||
uint32_t bo_mirror2;
|
||||
uint32_t sys_33v_en;
|
||||
uint32_t bo_mirror_access;
|
||||
uint32_t gate;
|
||||
uint32_t wake2_mask;
|
||||
uint32_t wake2_lvl;
|
||||
uint32_t wake2_stat;
|
||||
uint32_t sw_wake2_stat;
|
||||
uint32_t auto_wake2_lvl_mask;
|
||||
uint32_t pg_mask2;
|
||||
uint32_t pg_mask_ce1;
|
||||
uint32_t pg_mask_ce2;
|
||||
uint32_t pg_mask_ce3;
|
||||
uint32_t pwrgate_timer_ce0;
|
||||
uint32_t pwrgate_timer_ce1;
|
||||
uint32_t pwrgate_timer_ce2;
|
||||
uint32_t pwrgate_timer_ce3;
|
||||
uint32_t pwrgate_timer_ce4;
|
||||
uint32_t pwrgate_timer_ce5;
|
||||
uint32_t pwrgate_timer_ce6;
|
||||
uint32_t pcx_edpd_cntrl;
|
||||
uint32_t osc_edpd_over;
|
||||
uint32_t clk_out_cntrl;
|
||||
uint32_t sata_pwrgate;
|
||||
uint32_t sensor_ctrl;
|
||||
uint32_t reset_status;
|
||||
uint32_t io_dpd_req;
|
||||
uint32_t io_dpd_stat;
|
||||
uint32_t io_dpd2_req;
|
||||
uint32_t io_dpd2_stat;
|
||||
uint32_t sel_dpd_tim;
|
||||
uint32_t vddp_sel;
|
||||
uint32_t ddr_cfg;
|
||||
uint32_t e_no_vttgen;
|
||||
uint32_t _reserved0;
|
||||
uint32_t pllm_wb0_ovrride_frq;
|
||||
uint32_t test_pwrgate;
|
||||
uint32_t pwrgate_timer_mult;
|
||||
uint32_t dsi_sel_dpd;
|
||||
uint32_t utmip_uhsic_triggers;
|
||||
uint32_t utmip_uhsic_saved_st;
|
||||
uint32_t utmip_pad_cfg;
|
||||
uint32_t utmip_term_pad_cfg;
|
||||
uint32_t utmip_uhsic_sleep_cfg;
|
||||
uint32_t utmip_uhsic_sleepwalk_cfg;
|
||||
uint32_t utmip_sleepwalk_p[3];
|
||||
uint32_t uhsic_sleepwalk_p0;
|
||||
uint32_t utmip_uhsic_status;
|
||||
uint32_t utmip_uhsic_fake;
|
||||
uint32_t bo_mirror3[2];
|
||||
uint32_t secure_scratch6;
|
||||
uint32_t secure_scratch7;
|
||||
uint32_t scratch43;
|
||||
uint32_t scratch44;
|
||||
uint32_t scratch45;
|
||||
uint32_t scratch46;
|
||||
uint32_t scratch47;
|
||||
uint32_t scratch48;
|
||||
uint32_t scratch49;
|
||||
uint32_t scratch50;
|
||||
uint32_t scratch51;
|
||||
uint32_t scratch52;
|
||||
uint32_t scratch53;
|
||||
uint32_t scratch54;
|
||||
uint32_t scratch55;
|
||||
uint32_t scratch0_eco;
|
||||
uint32_t por_dpd_ctrl;
|
||||
uint32_t scratch2_eco;
|
||||
uint32_t utmip_uhsic_line_wakeup;
|
||||
uint32_t utmip_bias_master_cntrl;
|
||||
uint32_t utmip_master_config;
|
||||
uint32_t td_pwrgate_inter_part_timer;
|
||||
uint32_t utmip_uhsic2_triggers;
|
||||
uint32_t utmip_uhsic2_saved_state;
|
||||
uint32_t utmip_uhsic2_sleep_cfg;
|
||||
uint32_t utmip_uhsic2_sleepwalk_cfg;
|
||||
uint32_t uhsic2_sleepwalk_p1;
|
||||
uint32_t utmip_uhsic2_status;
|
||||
uint32_t utmip_uhsic2_fake;
|
||||
uint32_t utmip_uhsic2_line_wakeup;
|
||||
uint32_t utmip_master2_config;
|
||||
uint32_t utmip_uhsic_rpd_cfg;
|
||||
uint32_t pg_mask_ce0;
|
||||
uint32_t pg_mask3[2];
|
||||
uint32_t pllm_wb0_override2;
|
||||
uint32_t tsc_mult;
|
||||
uint32_t cpu_vsense_override;
|
||||
uint32_t glb_amap_cfg;
|
||||
uint32_t sticky_bits;
|
||||
uint32_t sec_disable2;
|
||||
uint32_t weak_bias;
|
||||
uint32_t reg_short;
|
||||
uint32_t pg_mask_andor;
|
||||
uint32_t _reserved1[11];
|
||||
uint32_t secure_scratch8;
|
||||
uint32_t secure_scratch9;
|
||||
uint32_t secure_scratch10;
|
||||
uint32_t secure_scratch11;
|
||||
uint32_t secure_scratch12;
|
||||
uint32_t secure_scratch13;
|
||||
uint32_t secure_scratch14;
|
||||
uint32_t secure_scratch15;
|
||||
uint32_t secure_scratch16;
|
||||
uint32_t secure_scratch17;
|
||||
uint32_t secure_scratch18;
|
||||
uint32_t secure_scratch19;
|
||||
uint32_t secure_scratch20;
|
||||
uint32_t secure_scratch21;
|
||||
uint32_t secure_scratch22;
|
||||
uint32_t secure_scratch23;
|
||||
uint32_t secure_scratch24;
|
||||
uint32_t secure_scratch25;
|
||||
uint32_t secure_scratch26;
|
||||
uint32_t secure_scratch27;
|
||||
uint32_t secure_scratch28;
|
||||
uint32_t secure_scratch29;
|
||||
uint32_t secure_scratch30;
|
||||
uint32_t secure_scratch31;
|
||||
uint32_t secure_scratch32;
|
||||
uint32_t secure_scratch33;
|
||||
uint32_t secure_scratch34;
|
||||
uint32_t secure_scratch35;
|
||||
uint32_t secure_scratch36;
|
||||
uint32_t secure_scratch37;
|
||||
uint32_t secure_scratch38;
|
||||
uint32_t secure_scratch39;
|
||||
uint32_t secure_scratch40;
|
||||
uint32_t secure_scratch41;
|
||||
uint32_t secure_scratch42;
|
||||
uint32_t secure_scratch43;
|
||||
uint32_t secure_scratch44;
|
||||
uint32_t secure_scratch45;
|
||||
uint32_t secure_scratch46;
|
||||
uint32_t secure_scratch47;
|
||||
uint32_t secure_scratch48;
|
||||
uint32_t secure_scratch49;
|
||||
uint32_t secure_scratch50;
|
||||
uint32_t secure_scratch51;
|
||||
uint32_t secure_scratch52;
|
||||
uint32_t secure_scratch53;
|
||||
uint32_t secure_scratch54;
|
||||
uint32_t secure_scratch55;
|
||||
uint32_t secure_scratch56;
|
||||
uint32_t secure_scratch57;
|
||||
uint32_t secure_scratch58;
|
||||
uint32_t secure_scratch59;
|
||||
uint32_t secure_scratch60;
|
||||
uint32_t secure_scratch61;
|
||||
uint32_t secure_scratch62;
|
||||
uint32_t secure_scratch63;
|
||||
uint32_t secure_scratch64;
|
||||
uint32_t secure_scratch65;
|
||||
uint32_t secure_scratch66;
|
||||
uint32_t secure_scratch67;
|
||||
uint32_t secure_scratch68;
|
||||
uint32_t secure_scratch69;
|
||||
uint32_t secure_scratch70;
|
||||
uint32_t secure_scratch71;
|
||||
uint32_t secure_scratch72;
|
||||
uint32_t secure_scratch73;
|
||||
uint32_t secure_scratch74;
|
||||
uint32_t secure_scratch75;
|
||||
uint32_t secure_scratch76;
|
||||
uint32_t secure_scratch77;
|
||||
uint32_t secure_scratch78;
|
||||
uint32_t secure_scratch79;
|
||||
uint32_t _reserved2[8];
|
||||
uint32_t cntrl2;
|
||||
uint32_t _reserved3[2];
|
||||
uint32_t event_counter;
|
||||
uint32_t fuse_control;
|
||||
uint32_t scratch1_eco;
|
||||
uint32_t _reserved4;
|
||||
uint32_t io_dpd3_req;
|
||||
uint32_t io_dpd3_status;
|
||||
uint32_t io_dpd4_req;
|
||||
uint32_t io_dpd4_status;
|
||||
uint32_t _reserved5[30];
|
||||
uint32_t ddr_cntrl;
|
||||
uint32_t _reserved6[70];
|
||||
uint32_t scratch56;
|
||||
uint32_t scratch57;
|
||||
uint32_t scratch58;
|
||||
uint32_t scratch59;
|
||||
uint32_t scratch60;
|
||||
uint32_t scratch61;
|
||||
uint32_t scratch62;
|
||||
uint32_t scratch63;
|
||||
uint32_t scratch64;
|
||||
uint32_t scratch65;
|
||||
uint32_t scratch66;
|
||||
uint32_t scratch67;
|
||||
uint32_t scratch68;
|
||||
uint32_t scratch69;
|
||||
uint32_t scratch70;
|
||||
uint32_t scratch71;
|
||||
uint32_t scratch72;
|
||||
uint32_t scratch73;
|
||||
uint32_t scratch74;
|
||||
uint32_t scratch75;
|
||||
uint32_t scratch76;
|
||||
uint32_t scratch77;
|
||||
uint32_t scratch78;
|
||||
uint32_t scratch79;
|
||||
uint32_t scratch80;
|
||||
uint32_t scratch81;
|
||||
uint32_t scratch82;
|
||||
uint32_t scratch83;
|
||||
uint32_t scratch84;
|
||||
uint32_t scratch85;
|
||||
uint32_t scratch86;
|
||||
uint32_t scratch87;
|
||||
uint32_t scratch88;
|
||||
uint32_t scratch89;
|
||||
uint32_t scratch90;
|
||||
uint32_t scratch91;
|
||||
uint32_t scratch92;
|
||||
uint32_t scratch93;
|
||||
uint32_t scratch94;
|
||||
uint32_t scratch95;
|
||||
uint32_t scratch96;
|
||||
uint32_t scratch97;
|
||||
uint32_t scratch98;
|
||||
uint32_t scratch99;
|
||||
uint32_t scratch100;
|
||||
uint32_t scratch101;
|
||||
uint32_t scratch102;
|
||||
uint32_t scratch103;
|
||||
uint32_t scratch104;
|
||||
uint32_t scratch105;
|
||||
uint32_t scratch106;
|
||||
uint32_t scratch107;
|
||||
uint32_t scratch108;
|
||||
uint32_t scratch109;
|
||||
uint32_t scratch110;
|
||||
uint32_t scratch111;
|
||||
uint32_t scratch112;
|
||||
uint32_t scratch113;
|
||||
uint32_t scratch114;
|
||||
uint32_t scratch115;
|
||||
uint32_t scratch116;
|
||||
uint32_t scratch117;
|
||||
uint32_t scratch118;
|
||||
uint32_t scratch119;
|
||||
uint32_t scratch120;
|
||||
uint32_t scratch121;
|
||||
uint32_t scratch122;
|
||||
uint32_t scratch123;
|
||||
uint32_t scratch124;
|
||||
uint32_t scratch125;
|
||||
uint32_t scratch126;
|
||||
uint32_t scratch127;
|
||||
uint32_t scratch128;
|
||||
uint32_t scratch129;
|
||||
uint32_t scratch130;
|
||||
uint32_t scratch131;
|
||||
uint32_t scratch132;
|
||||
uint32_t scratch133;
|
||||
uint32_t scratch134;
|
||||
uint32_t scratch135;
|
||||
uint32_t scratch136;
|
||||
uint32_t scratch137;
|
||||
uint32_t scratch138;
|
||||
uint32_t scratch139;
|
||||
uint32_t scratch140;
|
||||
uint32_t scratch141;
|
||||
uint32_t scratch142;
|
||||
uint32_t scratch143;
|
||||
uint32_t scratch144;
|
||||
uint32_t scratch145;
|
||||
uint32_t scratch146;
|
||||
uint32_t scratch147;
|
||||
uint32_t scratch148;
|
||||
uint32_t scratch149;
|
||||
uint32_t scratch150;
|
||||
uint32_t scratch151;
|
||||
uint32_t scratch152;
|
||||
uint32_t scratch153;
|
||||
uint32_t scratch154;
|
||||
uint32_t scratch155;
|
||||
uint32_t scratch156;
|
||||
uint32_t scratch157;
|
||||
uint32_t scratch158;
|
||||
uint32_t scratch159;
|
||||
uint32_t scratch160;
|
||||
uint32_t scratch161;
|
||||
uint32_t scratch162;
|
||||
uint32_t scratch163;
|
||||
uint32_t scratch164;
|
||||
uint32_t scratch165;
|
||||
uint32_t scratch166;
|
||||
uint32_t scratch167;
|
||||
uint32_t scratch168;
|
||||
uint32_t scratch169;
|
||||
uint32_t scratch170;
|
||||
uint32_t scratch171;
|
||||
uint32_t scratch172;
|
||||
uint32_t scratch173;
|
||||
uint32_t scratch174;
|
||||
uint32_t scratch175;
|
||||
uint32_t scratch176;
|
||||
uint32_t scratch177;
|
||||
uint32_t scratch178;
|
||||
uint32_t scratch179;
|
||||
uint32_t scratch180;
|
||||
uint32_t scratch181;
|
||||
uint32_t scratch182;
|
||||
uint32_t scratch183;
|
||||
uint32_t scratch184;
|
||||
uint32_t scratch185;
|
||||
uint32_t scratch186;
|
||||
uint32_t scratch187;
|
||||
uint32_t scratch188;
|
||||
uint32_t scratch189;
|
||||
uint32_t scratch190;
|
||||
uint32_t scratch191;
|
||||
uint32_t scratch192;
|
||||
uint32_t scratch193;
|
||||
uint32_t scratch194;
|
||||
uint32_t scratch195;
|
||||
uint32_t scratch196;
|
||||
uint32_t scratch197;
|
||||
uint32_t scratch198;
|
||||
uint32_t scratch199;
|
||||
uint32_t scratch200;
|
||||
uint32_t scratch201;
|
||||
uint32_t scratch202;
|
||||
uint32_t scratch203;
|
||||
uint32_t scratch204;
|
||||
uint32_t scratch205;
|
||||
uint32_t scratch206;
|
||||
uint32_t scratch207;
|
||||
uint32_t scratch208;
|
||||
uint32_t scratch209;
|
||||
uint32_t scratch210;
|
||||
uint32_t scratch211;
|
||||
uint32_t scratch212;
|
||||
uint32_t scratch213;
|
||||
uint32_t scratch214;
|
||||
uint32_t scratch215;
|
||||
uint32_t scratch216;
|
||||
uint32_t scratch217;
|
||||
uint32_t scratch218;
|
||||
uint32_t scratch219;
|
||||
uint32_t scratch220;
|
||||
uint32_t scratch221;
|
||||
uint32_t scratch222;
|
||||
uint32_t scratch223;
|
||||
uint32_t scratch224;
|
||||
uint32_t scratch225;
|
||||
uint32_t scratch226;
|
||||
uint32_t scratch227;
|
||||
uint32_t scratch228;
|
||||
uint32_t scratch229;
|
||||
uint32_t scratch230;
|
||||
uint32_t scratch231;
|
||||
uint32_t scratch232;
|
||||
uint32_t scratch233;
|
||||
uint32_t scratch234;
|
||||
uint32_t scratch235;
|
||||
uint32_t scratch236;
|
||||
uint32_t scratch237;
|
||||
uint32_t scratch238;
|
||||
uint32_t scratch239;
|
||||
uint32_t scratch240;
|
||||
uint32_t scratch241;
|
||||
uint32_t scratch242;
|
||||
uint32_t scratch243;
|
||||
uint32_t scratch244;
|
||||
uint32_t scratch245;
|
||||
uint32_t scratch246;
|
||||
uint32_t scratch247;
|
||||
uint32_t scratch248;
|
||||
uint32_t scratch249;
|
||||
uint32_t scratch250;
|
||||
uint32_t scratch251;
|
||||
uint32_t scratch252;
|
||||
uint32_t scratch253;
|
||||
uint32_t scratch254;
|
||||
uint32_t scratch255;
|
||||
uint32_t scratch256;
|
||||
uint32_t scratch257;
|
||||
uint32_t scratch258;
|
||||
uint32_t scratch259;
|
||||
uint32_t scratch260;
|
||||
uint32_t scratch261;
|
||||
uint32_t scratch262;
|
||||
uint32_t scratch263;
|
||||
uint32_t scratch264;
|
||||
uint32_t scratch265;
|
||||
uint32_t scratch266;
|
||||
uint32_t scratch267;
|
||||
uint32_t scratch268;
|
||||
uint32_t scratch269;
|
||||
uint32_t scratch270;
|
||||
uint32_t scratch271;
|
||||
uint32_t scratch272;
|
||||
uint32_t scratch273;
|
||||
uint32_t scratch274;
|
||||
uint32_t scratch275;
|
||||
uint32_t scratch276;
|
||||
uint32_t scratch277;
|
||||
uint32_t scratch278;
|
||||
uint32_t scratch279;
|
||||
uint32_t scratch280;
|
||||
uint32_t scratch281;
|
||||
uint32_t scratch282;
|
||||
uint32_t scratch283;
|
||||
uint32_t scratch284;
|
||||
uint32_t scratch285;
|
||||
uint32_t scratch286;
|
||||
uint32_t scratch287;
|
||||
uint32_t scratch288;
|
||||
uint32_t scratch289;
|
||||
uint32_t scratch290;
|
||||
uint32_t scratch291;
|
||||
uint32_t scratch292;
|
||||
uint32_t scratch293;
|
||||
uint32_t scratch294;
|
||||
uint32_t scratch295;
|
||||
uint32_t scratch296;
|
||||
uint32_t scratch297;
|
||||
uint32_t scratch298;
|
||||
uint32_t scratch299;
|
||||
uint32_t _reserved7[50];
|
||||
uint32_t secure_scratch80;
|
||||
uint32_t secure_scratch81;
|
||||
uint32_t secure_scratch82;
|
||||
uint32_t secure_scratch83;
|
||||
uint32_t secure_scratch84;
|
||||
uint32_t secure_scratch85;
|
||||
uint32_t secure_scratch86;
|
||||
uint32_t secure_scratch87;
|
||||
uint32_t secure_scratch88;
|
||||
uint32_t secure_scratch89;
|
||||
uint32_t secure_scratch90;
|
||||
uint32_t secure_scratch91;
|
||||
uint32_t secure_scratch92;
|
||||
uint32_t secure_scratch93;
|
||||
uint32_t secure_scratch94;
|
||||
uint32_t secure_scratch95;
|
||||
uint32_t secure_scratch96;
|
||||
uint32_t secure_scratch97;
|
||||
uint32_t secure_scratch98;
|
||||
uint32_t secure_scratch99;
|
||||
uint32_t secure_scratch100;
|
||||
uint32_t secure_scratch101;
|
||||
uint32_t secure_scratch102;
|
||||
uint32_t secure_scratch103;
|
||||
uint32_t secure_scratch104;
|
||||
uint32_t secure_scratch105;
|
||||
uint32_t secure_scratch106;
|
||||
uint32_t secure_scratch107;
|
||||
uint32_t secure_scratch108;
|
||||
uint32_t secure_scratch109;
|
||||
uint32_t secure_scratch110;
|
||||
uint32_t secure_scratch111;
|
||||
uint32_t secure_scratch112;
|
||||
uint32_t secure_scratch113;
|
||||
uint32_t secure_scratch114;
|
||||
uint32_t secure_scratch115;
|
||||
uint32_t secure_scratch116;
|
||||
uint32_t secure_scratch117;
|
||||
uint32_t secure_scratch118;
|
||||
uint32_t secure_scratch119;
|
||||
} tegra_pmc_t;
|
||||
|
||||
static inline volatile tegra_pmc_t *pmc_get_regs(void)
|
||||
{
|
||||
return (volatile tegra_pmc_t *)PMC_BASE;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -29,7 +29,7 @@ TARGET := $(notdir $(CURDIR))
|
||||
BUILD := build
|
||||
SOURCES := src src/sdmmc src/lib src/lib/fatfs src/display
|
||||
DATA := data
|
||||
INCLUDES := include ../../common/include
|
||||
INCLUDES := include ../../libraries/libvapours/include
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
|
||||
@@ -13,171 +13,178 @@
|
||||
* 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 <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <vapours/ams_version.h>
|
||||
|
||||
#include "car.h"
|
||||
#include "fuse.h"
|
||||
#include "pmc.h"
|
||||
#include "timers.h"
|
||||
|
||||
/* Prototypes for internal commands. */
|
||||
void fuse_make_regs_visible(void);
|
||||
|
||||
void fuse_enable_power(void);
|
||||
void fuse_disable_power(void);
|
||||
void fuse_wait_idle(void);
|
||||
|
||||
/* Initialize the fuse driver */
|
||||
void fuse_init(void) {
|
||||
fuse_make_regs_visible();
|
||||
fuse_secondary_private_key_disable();
|
||||
fuse_disable_programming();
|
||||
|
||||
/* TODO: Overrides (iROM patches) and various reads happen here */
|
||||
}
|
||||
|
||||
/* Make all fuse registers visible */
|
||||
void fuse_make_regs_visible(void) {
|
||||
/* Make all fuse registers visible, disable the private key and disable programming. */
|
||||
clkrst_enable_fuse_regs(true);
|
||||
fuse_disable_private_key();
|
||||
fuse_disable_programming();
|
||||
}
|
||||
|
||||
/* Enable power to the fuse hardware array */
|
||||
/* Disable access to the private key and set the TZ sticky bit. */
|
||||
void fuse_disable_private_key(void) {
|
||||
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||
fuse->FUSE_PRIVATEKEYDISABLE = 0x10;
|
||||
}
|
||||
|
||||
/* Disables all fuse programming. */
|
||||
void fuse_disable_programming(void) {
|
||||
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||
fuse->FUSE_DISABLEREGPROGRAM = 1;
|
||||
}
|
||||
|
||||
/* Enable power to the fuse hardware array. */
|
||||
void fuse_enable_power(void) {
|
||||
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||
fuse->FUSE_PWR_GOOD_SW = 1;
|
||||
udelay(1);
|
||||
volatile tegra_pmc_t *pmc = pmc_get_regs();
|
||||
pmc->fuse_control &= ~(0x200); /* Clear PMC_FUSE_CTRL_PS18_LATCH_CLEAR. */
|
||||
mdelay(1);
|
||||
pmc->fuse_control |= 0x100; /* Set PMC_FUSE_CTRL_PS18_LATCH_SET. */
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
/* Disable power to the fuse hardware array */
|
||||
/* Disable power to the fuse hardware array. */
|
||||
void fuse_disable_power(void) {
|
||||
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||
fuse->FUSE_PWR_GOOD_SW = 0;
|
||||
udelay(1);
|
||||
volatile tegra_pmc_t *pmc = pmc_get_regs();
|
||||
pmc->fuse_control &= ~(0x100); /* Clear PMC_FUSE_CTRL_PS18_LATCH_SET. */
|
||||
mdelay(1);
|
||||
pmc->fuse_control |= 0x200; /* Set PMC_FUSE_CTRL_PS18_LATCH_CLEAR. */
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
/* Wait for the fuse driver to go idle */
|
||||
/* Wait for the fuse driver to go idle. */
|
||||
void fuse_wait_idle(void) {
|
||||
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||
uint32_t ctrl_val = 0;
|
||||
|
||||
/* Wait for STATE_IDLE */
|
||||
while ((ctrl_val & (0xF0000)) != 0x40000)
|
||||
{
|
||||
udelay(1);
|
||||
ctrl_val = fuse->FUSE_CTRL;
|
||||
}
|
||||
ctrl_val = fuse->FUSE_FUSECTRL;
|
||||
}
|
||||
|
||||
/* Read a fuse from the hardware array */
|
||||
/* Read a fuse from the hardware array. */
|
||||
uint32_t fuse_hw_read(uint32_t addr) {
|
||||
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||
|
||||
/* Wait for idle state. */
|
||||
fuse_wait_idle();
|
||||
|
||||
/* Program the target address */
|
||||
fuse->FUSE_REG_ADDR = addr;
|
||||
/* Program the target address. */
|
||||
fuse->FUSE_FUSEADDR = addr;
|
||||
|
||||
/* Enable read operation in control register */
|
||||
uint32_t ctrl_val = fuse->FUSE_CTRL;
|
||||
/* Enable read operation in control register. */
|
||||
uint32_t ctrl_val = fuse->FUSE_FUSECTRL;
|
||||
ctrl_val &= ~0x3;
|
||||
ctrl_val |= 0x1; /* Set FUSE_READ command */
|
||||
fuse->FUSE_CTRL = ctrl_val;
|
||||
ctrl_val |= 0x1; /* Set READ command. */
|
||||
fuse->FUSE_FUSECTRL = ctrl_val;
|
||||
|
||||
/* Wait for idle state. */
|
||||
fuse_wait_idle();
|
||||
|
||||
return fuse->FUSE_REG_READ;
|
||||
return fuse->FUSE_FUSERDATA;
|
||||
}
|
||||
|
||||
/* Write a fuse in the hardware array */
|
||||
/* Write a fuse in the hardware array. */
|
||||
void fuse_hw_write(uint32_t value, uint32_t addr) {
|
||||
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||
|
||||
/* Wait for idle state. */
|
||||
fuse_wait_idle();
|
||||
|
||||
/* Program the target address and value */
|
||||
fuse->FUSE_REG_ADDR = addr;
|
||||
fuse->FUSE_REG_WRITE = value;
|
||||
/* Program the target address and value. */
|
||||
fuse->FUSE_FUSEADDR = addr;
|
||||
fuse->FUSE_FUSEWDATA = value;
|
||||
|
||||
/* Enable write operation in control register */
|
||||
uint32_t ctrl_val = fuse->FUSE_CTRL;
|
||||
/* Enable write operation in control register. */
|
||||
uint32_t ctrl_val = fuse->FUSE_FUSECTRL;
|
||||
ctrl_val &= ~0x3;
|
||||
ctrl_val |= 0x2; /* Set FUSE_WRITE command */
|
||||
fuse->FUSE_CTRL = ctrl_val;
|
||||
ctrl_val |= 0x2; /* Set WRITE command. */
|
||||
fuse->FUSE_FUSECTRL = ctrl_val;
|
||||
|
||||
/* Wait for idle state. */
|
||||
fuse_wait_idle();
|
||||
}
|
||||
|
||||
/* Sense the fuse hardware array into the shadow cache */
|
||||
/* Sense the fuse hardware array into the shadow cache. */
|
||||
void fuse_hw_sense(void) {
|
||||
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||
|
||||
/* Wait for idle state. */
|
||||
fuse_wait_idle();
|
||||
|
||||
/* Enable sense operation in control register */
|
||||
uint32_t ctrl_val = fuse->FUSE_CTRL;
|
||||
uint32_t ctrl_val = fuse->FUSE_FUSECTRL;
|
||||
ctrl_val &= ~0x3;
|
||||
ctrl_val |= 0x3; /* Set FUSE_SENSE command */
|
||||
fuse->FUSE_CTRL = ctrl_val;
|
||||
ctrl_val |= 0x3; /* Set SENSE_CTRL command */
|
||||
fuse->FUSE_FUSECTRL = ctrl_val;
|
||||
|
||||
/* Wait for idle state. */
|
||||
fuse_wait_idle();
|
||||
}
|
||||
|
||||
/* Disables all fuse programming. */
|
||||
void fuse_disable_programming(void) {
|
||||
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||
fuse->FUSE_DIS_PGM = 1;
|
||||
}
|
||||
|
||||
/* Unknown exactly what this does, but it alters the contents read from the fuse cache. */
|
||||
void fuse_secondary_private_key_disable(void) {
|
||||
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||
fuse->FUSE_PRIVATEKEYDISABLE = 0x10;
|
||||
}
|
||||
|
||||
|
||||
/* Read the SKU info register from the shadow cache */
|
||||
/* Read the SKU info register from the shadow cache. */
|
||||
uint32_t fuse_get_sku_info(void) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
return fuse_chip->FUSE_SKU_INFO;
|
||||
}
|
||||
|
||||
/* Read the bootrom patch version from a register in the shadow cache */
|
||||
/* Read the bootrom patch version from a register in the shadow cache. */
|
||||
uint32_t fuse_get_bootrom_patch_version(void) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
return fuse_chip->FUSE_SOC_SPEEDO_1;
|
||||
return fuse_chip->FUSE_SOC_SPEEDO_1_CALIB;
|
||||
}
|
||||
|
||||
/* Read a spare bit register from the shadow cache */
|
||||
uint32_t fuse_get_spare_bit(uint32_t idx) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
|
||||
if (idx >= 32) {
|
||||
if (idx < 32) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
return fuse_chip->FUSE_SPARE_BIT[idx];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return fuse_chip->FUSE_SPARE_BIT[idx];
|
||||
}
|
||||
|
||||
/* Read a reserved ODM register from the shadow cache */
|
||||
/* Read a reserved ODM register from the shadow cache. */
|
||||
uint32_t fuse_get_reserved_odm(uint32_t idx) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
|
||||
if (idx >= 8) {
|
||||
if (idx < 8) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
return fuse_chip->FUSE_RESERVED_ODM[idx];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return fuse_chip->FUSE_RESERVED_ODM[idx];
|
||||
}
|
||||
|
||||
/* Derive the Device ID using values in the shadow cache */
|
||||
/* Get the DRAM ID using values in the shadow cache. */
|
||||
uint32_t fuse_get_dram_id(void) {
|
||||
return ((fuse_get_reserved_odm(4) >> 3) & 0x7);
|
||||
}
|
||||
|
||||
/* Derive the Device ID using values in the shadow cache. */
|
||||
uint64_t fuse_get_device_id(void) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
|
||||
|
||||
uint64_t device_id = 0;
|
||||
uint64_t y_coord = fuse_chip->FUSE_Y_COORDINATE & 0x1FF;
|
||||
uint64_t x_coord = fuse_chip->FUSE_X_COORDINATE & 0x1FF;
|
||||
uint64_t wafer_id = fuse_chip->FUSE_WAFER_ID & 0x3F;
|
||||
uint32_t lot_code = fuse_chip->FUSE_LOT_CODE_0;
|
||||
uint64_t fab_code = fuse_chip->FUSE_FAB_CODE & 0x3F;
|
||||
uint64_t y_coord = fuse_chip->FUSE_OPT_Y_COORDINATE & 0x1FF;
|
||||
uint64_t x_coord = fuse_chip->FUSE_OPT_X_COORDINATE & 0x1FF;
|
||||
uint64_t wafer_id = fuse_chip->FUSE_OPT_WAFER_ID & 0x3F;
|
||||
uint32_t lot_code = fuse_chip->FUSE_OPT_LOT_CODE_0;
|
||||
uint64_t fab_code = fuse_chip->FUSE_OPT_FAB_CODE & 0x3F;
|
||||
|
||||
uint64_t derived_lot_code = 0;
|
||||
for (unsigned int i = 0; i < 5; i++) {
|
||||
derived_lot_code = (derived_lot_code * 0x24) + ((lot_code >> (24 - 6*i)) & 0x3F);
|
||||
@@ -189,45 +196,41 @@ uint64_t fuse_get_device_id(void) {
|
||||
device_id |= wafer_id << 18;
|
||||
device_id |= derived_lot_code << 24;
|
||||
device_id |= fab_code << 50;
|
||||
|
||||
return device_id;
|
||||
}
|
||||
|
||||
/* Get the DRAM ID using values in the shadow cache */
|
||||
uint32_t fuse_get_dram_id(void) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
return (fuse_chip->FUSE_RESERVED_ODM[4] >> 3) & 0x7;
|
||||
}
|
||||
/* Derive the Hardware Type using values in the shadow cache. */
|
||||
uint32_t fuse_get_hardware_type(uint32_t target_firmware) {
|
||||
uint32_t fuse_reserved_odm4 = fuse_get_reserved_odm(4);
|
||||
uint32_t hardware_type = (((fuse_reserved_odm4 >> 7) & 2) | ((fuse_reserved_odm4 >> 2) & 1));
|
||||
|
||||
/* Derive the Hardware Type using values in the shadow cache */
|
||||
uint32_t fuse_get_hardware_type(void) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
|
||||
/* This function is very different between 4.x and < 4.x */
|
||||
uint32_t hardware_type = ((fuse_chip->FUSE_RESERVED_ODM[4] >> 7) & 2) | ((fuse_chip->FUSE_RESERVED_ODM[4] >> 2) & 1);
|
||||
|
||||
/* TODO: choose; if (mkey_get_revision() >= MASTERKEY_REVISION_400_CURRENT) {
|
||||
static const uint32_t types[] = {0,1,4,3};
|
||||
|
||||
hardware_type |= (fuse_chip->FUSE_RESERVED_ODM[4] >> 14) & 0x3C;
|
||||
hardware_type--;
|
||||
return hardware_type > 3 ? 4 : types[hardware_type];
|
||||
} else {*/
|
||||
/* Firmware from versions 1.0.0 to 3.0.2. */
|
||||
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
if (hardware_type >= 1) {
|
||||
return hardware_type > 2 ? 3 : hardware_type - 1;
|
||||
return (hardware_type > 2) ? 3 : hardware_type - 1;
|
||||
} else if ((fuse_chip->FUSE_SPARE_BIT[9] & 1) == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return 3;
|
||||
}
|
||||
// }
|
||||
} else if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_700) { /* Firmware versions from 4.0.0 to 6.2.0. */
|
||||
static const uint32_t types[] = {0,1,4,3};
|
||||
hardware_type |= ((fuse_reserved_odm4 >> 14) & 0x3C);
|
||||
hardware_type--;
|
||||
return (hardware_type > 3) ? 4 : types[hardware_type];
|
||||
} else { /* Firmware versions from 7.0.0 onwards. */
|
||||
/* Always return 0 in retail. */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Derive the Retail Type using values in the shadow cache */
|
||||
/* Derive the Retail Type using values in the shadow cache. */
|
||||
uint32_t fuse_get_retail_type(void) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
|
||||
/* Retail type = IS_RETAIL | UNIT_TYPE */
|
||||
uint32_t retail_type = ((fuse_chip->FUSE_RESERVED_ODM[4] >> 7) & 4) | (fuse_chip->FUSE_RESERVED_ODM[4] & 3);
|
||||
/* Retail Type = IS_RETAIL | UNIT_TYPE. */
|
||||
uint32_t fuse_reserved_odm4 = fuse_get_reserved_odm(4);
|
||||
uint32_t retail_type = (((fuse_reserved_odm4 >> 7) & 4) | (fuse_reserved_odm4 & 3));
|
||||
if (retail_type == 4) { /* Standard retail unit, IS_RETAIL | 0. */
|
||||
return 1;
|
||||
} else if (retail_type == 3) { /* Standard dev unit, 0 | DEV_UNIT. */
|
||||
@@ -241,17 +244,17 @@ void fuse_get_hardware_info(void *dst) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
uint32_t hw_info[0x4];
|
||||
|
||||
uint32_t unk_hw_fuse = fuse_chip->_0x120 & 0x3F;
|
||||
uint32_t y_coord = fuse_chip->FUSE_Y_COORDINATE & 0x1FF;
|
||||
uint32_t x_coord = fuse_chip->FUSE_X_COORDINATE & 0x1FF;
|
||||
uint32_t wafer_id = fuse_chip->FUSE_WAFER_ID & 0x3F;
|
||||
uint32_t lot_code_0 = fuse_chip->FUSE_LOT_CODE_0;
|
||||
uint32_t lot_code_1 = fuse_chip->FUSE_LOT_CODE_1 & 0x0FFFFFFF;
|
||||
uint32_t fab_code = fuse_chip->FUSE_FAB_CODE & 0x3F;
|
||||
uint32_t vendor_code = fuse_chip->FUSE_VENDOR_CODE & 0xF;
|
||||
uint32_t ops_reserved = fuse_chip->FUSE_OPT_OPS_RESERVED & 0x3F;
|
||||
uint32_t y_coord = fuse_chip->FUSE_OPT_Y_COORDINATE & 0x1FF;
|
||||
uint32_t x_coord = fuse_chip->FUSE_OPT_X_COORDINATE & 0x1FF;
|
||||
uint32_t wafer_id = fuse_chip->FUSE_OPT_WAFER_ID & 0x3F;
|
||||
uint32_t lot_code_0 = fuse_chip->FUSE_OPT_LOT_CODE_0;
|
||||
uint32_t lot_code_1 = fuse_chip->FUSE_OPT_LOT_CODE_1 & 0x0FFFFFFF;
|
||||
uint32_t fab_code = fuse_chip->FUSE_OPT_FAB_CODE & 0x3F;
|
||||
uint32_t vendor_code = fuse_chip->FUSE_OPT_VENDOR_CODE & 0xF;
|
||||
|
||||
/* Hardware Info = unk_hw_fuse || Y_COORD || X_COORD || WAFER_ID || LOT_CODE || FAB_CODE || VENDOR_ID */
|
||||
hw_info[0] = (uint32_t)((lot_code_1 << 30) | (wafer_id << 24) | (x_coord << 15) | (y_coord << 6) | (unk_hw_fuse));
|
||||
/* Hardware Info = OPS_RESERVED || Y_COORD || X_COORD || WAFER_ID || LOT_CODE || FAB_CODE || VENDOR_ID */
|
||||
hw_info[0] = (uint32_t)((lot_code_1 << 30) | (wafer_id << 24) | (x_coord << 15) | (y_coord << 6) | (ops_reserved));
|
||||
hw_info[1] = (uint32_t)((lot_code_0 << 26) | (lot_code_1 >> 2));
|
||||
hw_info[2] = (uint32_t)((fab_code << 26) | (lot_code_0 >> 6));
|
||||
hw_info[3] = (uint32_t)(vendor_code);
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* 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 FUSEE_FUSE_H
|
||||
#define FUSEE_FUSE_H
|
||||
|
||||
@@ -23,154 +23,167 @@
|
||||
#define MAKE_FUSE_CHIP_REG(n) MAKE_REG32(FUSE_CHIP_BASE + n)
|
||||
|
||||
typedef struct {
|
||||
uint32_t FUSE_CTRL;
|
||||
uint32_t FUSE_REG_ADDR;
|
||||
uint32_t FUSE_REG_READ;
|
||||
uint32_t FUSE_REG_WRITE;
|
||||
uint32_t FUSE_TIME_RD1;
|
||||
uint32_t FUSE_TIME_RD2;
|
||||
uint32_t FUSE_TIME_PGM1;
|
||||
uint32_t FUSE_TIME_PGM2;
|
||||
uint32_t FUSE_PRIV2INTFC;
|
||||
uint32_t FUSE_FUSECTRL;
|
||||
uint32_t FUSE_FUSEADDR;
|
||||
uint32_t FUSE_FUSERDATA;
|
||||
uint32_t FUSE_FUSEWDATA;
|
||||
uint32_t FUSE_FUSETIME_RD1;
|
||||
uint32_t FUSE_FUSETIME_RD2;
|
||||
uint32_t FUSE_FUSETIME_PGM1;
|
||||
uint32_t FUSE_FUSETIME_PGM2;
|
||||
uint32_t FUSE_PRIV2INTFC_START;
|
||||
uint32_t FUSE_FUSEBYPASS;
|
||||
uint32_t FUSE_PRIVATEKEYDISABLE;
|
||||
uint32_t FUSE_DIS_PGM;
|
||||
uint32_t FUSE_WRITE_ACCESS;
|
||||
uint32_t FUSE_DISABLEREGPROGRAM;
|
||||
uint32_t FUSE_WRITE_ACCESS_SW;
|
||||
uint32_t FUSE_PWR_GOOD_SW;
|
||||
uint32_t _0x38[0x32];
|
||||
uint32_t _0x38;
|
||||
uint32_t FUSE_PRIV2RESHIFT;
|
||||
uint32_t _0x40[0x3];
|
||||
uint32_t FUSE_FUSETIME_RD3;
|
||||
uint32_t _0x50[0xC];
|
||||
uint32_t FUSE_PRIVATE_KEY0_NONZERO;
|
||||
uint32_t FUSE_PRIVATE_KEY1_NONZERO;
|
||||
uint32_t FUSE_PRIVATE_KEY2_NONZERO;
|
||||
uint32_t FUSE_PRIVATE_KEY3_NONZERO;
|
||||
uint32_t FUSE_PRIVATE_KEY4_NONZERO;
|
||||
uint32_t _0x90[0x1C];
|
||||
} tegra_fuse_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t FUSE_PRODUCTION_MODE;
|
||||
uint32_t _0x4;
|
||||
uint32_t _0x8;
|
||||
uint32_t _0xC;
|
||||
uint32_t FUSE_JTAG_SECUREID_VALID;
|
||||
uint32_t FUSE_ODM_LOCK;
|
||||
uint32_t FUSE_OPT_OPENGL_EN;
|
||||
uint32_t FUSE_SKU_INFO;
|
||||
uint32_t FUSE_CPU_SPEEDO_0;
|
||||
uint32_t FUSE_CPU_IDDQ;
|
||||
uint32_t _0x1C;
|
||||
uint32_t _0x20;
|
||||
uint32_t _0x24;
|
||||
uint32_t FUSE_FT_REV;
|
||||
uint32_t FUSE_CPU_SPEEDO_1;
|
||||
uint32_t FUSE_CPU_SPEEDO_2;
|
||||
uint32_t FUSE_SOC_SPEEDO_0;
|
||||
uint32_t FUSE_SOC_SPEEDO_1;
|
||||
uint32_t FUSE_SOC_SPEEDO_2;
|
||||
uint32_t FUSE_SOC_IDDQ;
|
||||
uint32_t _0x44;
|
||||
uint32_t FUSE_CPU_SPEEDO_0_CALIB;
|
||||
uint32_t FUSE_CPU_IDDQ_CALIB;
|
||||
uint32_t FUSE_DAC_CRT_CALIB;
|
||||
uint32_t FUSE_DAC_HDTV_CALIB;
|
||||
uint32_t FUSE_DAC_SDTV_CALIB;
|
||||
uint32_t FUSE_OPT_FT_REV;
|
||||
uint32_t FUSE_CPU_SPEEDO_1_CALIB;
|
||||
uint32_t FUSE_CPU_SPEEDO_2_CALIB;
|
||||
uint32_t FUSE_SOC_SPEEDO_0_CALIB;
|
||||
uint32_t FUSE_SOC_SPEEDO_1_CALIB;
|
||||
uint32_t FUSE_SOC_SPEEDO_2_CALIB;
|
||||
uint32_t FUSE_SOC_IDDQ_CALIB;
|
||||
uint32_t FUSE_RESERVED_PRODUCTION_WP;
|
||||
uint32_t FUSE_FA;
|
||||
uint32_t _0x4C;
|
||||
uint32_t _0x50;
|
||||
uint32_t _0x54;
|
||||
uint32_t _0x58;
|
||||
uint32_t _0x5C;
|
||||
uint32_t _0x60;
|
||||
uint32_t FUSE_RESERVED_PRODUCTION;
|
||||
uint32_t FUSE_HDMI_LANE0_CALIB;
|
||||
uint32_t FUSE_HDMI_LANE1_CALIB;
|
||||
uint32_t FUSE_HDMI_LANE2_CALIB;
|
||||
uint32_t FUSE_HDMI_LANE3_CALIB;
|
||||
uint32_t FUSE_ENCRYPTION_RATE;
|
||||
uint32_t FUSE_PUBLIC_KEY[0x8];
|
||||
uint32_t FUSE_TSENSOR_1;
|
||||
uint32_t FUSE_TSENSOR_2;
|
||||
uint32_t _0x8C;
|
||||
uint32_t FUSE_CP_REV;
|
||||
uint32_t _0x94;
|
||||
uint32_t FUSE_TSENSOR_0;
|
||||
uint32_t FUSE_FIRST_BOOTROM_PATCH_SIZE_REG;
|
||||
uint32_t FUSE_TSENSOR1_CALIB;
|
||||
uint32_t FUSE_TSENSOR2_CALIB;
|
||||
uint32_t FUSE_VSENSOR_CALIB;
|
||||
uint32_t FUSE_OPT_CP_REV;
|
||||
uint32_t FUSE_OPT_PFG;
|
||||
uint32_t FUSE_TSENSOR0_CALIB;
|
||||
uint32_t FUSE_FIRST_BOOTROM_PATCH_SIZE;
|
||||
uint32_t FUSE_SECURITY_MODE;
|
||||
uint32_t FUSE_PRIVATE_KEY[0x4];
|
||||
uint32_t FUSE_DEVICE_KEY;
|
||||
uint32_t _0xB8;
|
||||
uint32_t _0xBC;
|
||||
uint32_t FUSE_PRIVATE_KEY[0x5];
|
||||
uint32_t FUSE_ARM_JTAG_DIS;
|
||||
uint32_t FUSE_BOOT_DEVICE_INFO;
|
||||
uint32_t FUSE_RESERVED_SW;
|
||||
uint32_t FUSE_VP8_ENABLE;
|
||||
uint32_t FUSE_OPT_VP9_DISABLE;
|
||||
uint32_t FUSE_RESERVED_ODM[0x8];
|
||||
uint32_t _0xE8;
|
||||
uint32_t _0xEC;
|
||||
uint32_t FUSE_SKU_USB_CALIB;
|
||||
uint32_t FUSE_OBS_DIS;
|
||||
uint32_t FUSE_NOR_INFO;
|
||||
uint32_t FUSE_USB_CALIB;
|
||||
uint32_t FUSE_SKU_DIRECT_CONFIG;
|
||||
uint32_t _0xF8;
|
||||
uint32_t _0xFC;
|
||||
uint32_t FUSE_VENDOR_CODE;
|
||||
uint32_t FUSE_FAB_CODE;
|
||||
uint32_t FUSE_LOT_CODE_0;
|
||||
uint32_t FUSE_LOT_CODE_1;
|
||||
uint32_t FUSE_WAFER_ID;
|
||||
uint32_t FUSE_X_COORDINATE;
|
||||
uint32_t FUSE_Y_COORDINATE;
|
||||
uint32_t _0x11C;
|
||||
uint32_t _0x120;
|
||||
uint32_t FUSE_KFUSE_PRIVKEY_CTRL;
|
||||
uint32_t FUSE_PACKAGE_INFO;
|
||||
uint32_t FUSE_OPT_VENDOR_CODE;
|
||||
uint32_t FUSE_OPT_FAB_CODE;
|
||||
uint32_t FUSE_OPT_LOT_CODE_0;
|
||||
uint32_t FUSE_OPT_LOT_CODE_1;
|
||||
uint32_t FUSE_OPT_WAFER_ID;
|
||||
uint32_t FUSE_OPT_X_COORDINATE;
|
||||
uint32_t FUSE_OPT_Y_COORDINATE;
|
||||
uint32_t FUSE_OPT_SEC_DEBUG_EN;
|
||||
uint32_t FUSE_OPT_OPS_RESERVED;
|
||||
uint32_t FUSE_SATA_CALIB;
|
||||
uint32_t FUSE_GPU_IDDQ;
|
||||
uint32_t FUSE_TSENSOR_3;
|
||||
uint32_t _0x130;
|
||||
uint32_t _0x134;
|
||||
uint32_t _0x138;
|
||||
uint32_t _0x13C;
|
||||
uint32_t _0x140;
|
||||
uint32_t _0x144;
|
||||
uint32_t FUSE_GPU_IDDQ_CALIB;
|
||||
uint32_t FUSE_TSENSOR3_CALIB;
|
||||
uint32_t FUSE_SKU_BOND_OUT_L;
|
||||
uint32_t FUSE_SKU_BOND_OUT_H;
|
||||
uint32_t FUSE_SKU_BOND_OUT_U;
|
||||
uint32_t FUSE_SKU_BOND_OUT_V;
|
||||
uint32_t FUSE_SKU_BOND_OUT_W;
|
||||
uint32_t FUSE_OPT_SAMPLE_TYPE;
|
||||
uint32_t FUSE_OPT_SUBREVISION;
|
||||
uint32_t _0x14C;
|
||||
uint32_t _0x150;
|
||||
uint32_t FUSE_TSENSOR_4;
|
||||
uint32_t FUSE_TSENSOR_5;
|
||||
uint32_t FUSE_TSENSOR_6;
|
||||
uint32_t FUSE_TSENSOR_7;
|
||||
uint32_t FUSE_OPT_PRIV_SEC_DIS;
|
||||
uint32_t FUSE_OPT_SW_RESERVED_0;
|
||||
uint32_t FUSE_OPT_SW_RESERVED_1;
|
||||
uint32_t FUSE_TSENSOR4_CALIB;
|
||||
uint32_t FUSE_TSENSOR5_CALIB;
|
||||
uint32_t FUSE_TSENSOR6_CALIB;
|
||||
uint32_t FUSE_TSENSOR7_CALIB;
|
||||
uint32_t FUSE_OPT_PRIV_SEC_EN;
|
||||
uint32_t FUSE_PKC_DISABLE;
|
||||
uint32_t _0x16C;
|
||||
uint32_t _0x170;
|
||||
uint32_t _0x174;
|
||||
uint32_t _0x178;
|
||||
uint32_t _0x17C;
|
||||
uint32_t FUSE_FUSE2TSEC_DEBUG_DISABLE;
|
||||
uint32_t FUSE_TSENSOR_COMMON;
|
||||
uint32_t _0x184;
|
||||
uint32_t _0x188;
|
||||
uint32_t _0x18C;
|
||||
uint32_t _0x190;
|
||||
uint32_t FUSE_OPT_CP_BIN;
|
||||
uint32_t FUSE_OPT_GPU_DISABLE;
|
||||
uint32_t FUSE_OPT_FT_BIN;
|
||||
uint32_t FUSE_OPT_DONE_MAP;
|
||||
uint32_t _0x194;
|
||||
uint32_t _0x198;
|
||||
uint32_t FUSE_DEBUG_AUTH_OVERRIDE;
|
||||
uint32_t FUSE_APB2JTAG_DISABLE;
|
||||
uint32_t FUSE_ODM_INFO;
|
||||
uint32_t _0x1A0;
|
||||
uint32_t _0x1A4;
|
||||
uint32_t _0x1A8;
|
||||
uint32_t FUSE_ARM_CRYPT_DE_FEATURE;
|
||||
uint32_t _0x1AC;
|
||||
uint32_t _0x1B0;
|
||||
uint32_t _0x1B4;
|
||||
uint32_t _0x1B8;
|
||||
uint32_t _0x1BC;
|
||||
uint32_t _0x1D0;
|
||||
uint32_t FUSE_TSENSOR_8;
|
||||
uint32_t FUSE_WOA_SKU_FLAG;
|
||||
uint32_t FUSE_ECO_RESERVE_1;
|
||||
uint32_t FUSE_GCPLEX_CONFIG_FUSE;
|
||||
uint32_t FUSE_PRODUCTION_MONTH;
|
||||
uint32_t FUSE_RAM_REPAIR_INDICATOR;
|
||||
uint32_t FUSE_TSENSOR9_CALIB;
|
||||
uint32_t _0x1D8;
|
||||
uint32_t _0x1DC;
|
||||
uint32_t _0x1E0;
|
||||
uint32_t _0x1E4;
|
||||
uint32_t _0x1E8;
|
||||
uint32_t _0x1EC;
|
||||
uint32_t _0x1F0;
|
||||
uint32_t _0x1F4;
|
||||
uint32_t _0x1F8;
|
||||
uint32_t FUSE_VMIN_CALIBRATION;
|
||||
uint32_t FUSE_AGING_SENSOR_CALIBRATION;
|
||||
uint32_t FUSE_DEBUG_AUTHENTICATION;
|
||||
uint32_t FUSE_SECURE_PROVISION_INDEX;
|
||||
uint32_t FUSE_SECURE_PROVISION_INFO;
|
||||
uint32_t FUSE_OPT_GPU_DISABLE_CP1;
|
||||
uint32_t FUSE_SPARE_ENDIS;
|
||||
uint32_t FUSE_ECO_RESERVE_0;
|
||||
uint32_t _0x1FC;
|
||||
uint32_t _0x200;
|
||||
uint32_t FUSE_RESERVED_CALIB;
|
||||
uint32_t _0x208;
|
||||
uint32_t _0x20C;
|
||||
uint32_t _0x210;
|
||||
uint32_t _0x214;
|
||||
uint32_t _0x218;
|
||||
uint32_t FUSE_TSENSOR_9;
|
||||
uint32_t _0x220;
|
||||
uint32_t _0x224;
|
||||
uint32_t _0x228;
|
||||
uint32_t _0x22C;
|
||||
uint32_t _0x230;
|
||||
uint32_t _0x234;
|
||||
uint32_t _0x238;
|
||||
uint32_t _0x23C;
|
||||
uint32_t _0x240;
|
||||
uint32_t _0x244;
|
||||
uint32_t _0x248;
|
||||
uint32_t _0x24C;
|
||||
uint32_t FUSE_RESERVED_CALIB0;
|
||||
uint32_t FUSE_RESERVED_CALIB1;
|
||||
uint32_t FUSE_OPT_GPU_TPC0_DISABLE;
|
||||
uint32_t FUSE_OPT_GPU_TPC0_DISABLE_CP1;
|
||||
uint32_t FUSE_OPT_CPU_DISABLE;
|
||||
uint32_t FUSE_OPT_CPU_DISABLE_CP1;
|
||||
uint32_t FUSE_TSENSOR10_CALIB;
|
||||
uint32_t FUSE_TSENSOR10_CALIB_AUX;
|
||||
uint32_t FUSE_OPT_RAM_SVOP_DP;
|
||||
uint32_t FUSE_OPT_RAM_SVOP_PDP;
|
||||
uint32_t FUSE_OPT_RAM_SVOP_REG;
|
||||
uint32_t FUSE_OPT_RAM_SVOP_SP;
|
||||
uint32_t FUSE_OPT_RAM_SVOP_SMPDP;
|
||||
uint32_t FUSE_OPT_GPU_TPC0_DISABLE_CP2;
|
||||
uint32_t FUSE_OPT_GPU_TPC1_DISABLE;
|
||||
uint32_t FUSE_OPT_GPU_TPC1_DISABLE_CP1;
|
||||
uint32_t FUSE_OPT_GPU_TPC1_DISABLE_CP2;
|
||||
uint32_t FUSE_OPT_CPU_DISABLE_CP2;
|
||||
uint32_t FUSE_OPT_GPU_DISABLE_CP2;
|
||||
uint32_t FUSE_USB_CALIB_EXT;
|
||||
uint32_t _0x254;
|
||||
uint32_t _0x258;
|
||||
uint32_t FUSE_RESERVED_FIELD;
|
||||
uint32_t FUSE_OPT_ECC_EN;
|
||||
uint32_t _0x25C;
|
||||
uint32_t _0x260;
|
||||
uint32_t _0x264;
|
||||
@@ -179,35 +192,36 @@ typedef struct {
|
||||
uint32_t _0x270;
|
||||
uint32_t _0x274;
|
||||
uint32_t _0x278;
|
||||
uint32_t _0x27C;
|
||||
uint32_t FUSE_SPARE_REALIGNMENT_REG;
|
||||
uint32_t FUSE_SPARE_BIT[0x20];
|
||||
} tegra_fuse_chip_t;
|
||||
|
||||
static inline volatile tegra_fuse_t *fuse_get_regs(void) {
|
||||
static inline volatile tegra_fuse_t *fuse_get_regs(void)
|
||||
{
|
||||
return (volatile tegra_fuse_t *)FUSE_BASE;
|
||||
}
|
||||
|
||||
static inline volatile tegra_fuse_chip_t *fuse_chip_get_regs(void) {
|
||||
static inline volatile tegra_fuse_chip_t *fuse_chip_get_regs(void)
|
||||
{
|
||||
return (volatile tegra_fuse_chip_t *)FUSE_CHIP_BASE;
|
||||
}
|
||||
|
||||
void fuse_init(void);
|
||||
|
||||
uint32_t fuse_hw_read(uint32_t addr);
|
||||
void fuse_hw_write(uint32_t value, uint32_t addr);
|
||||
void fuse_hw_sense(void);
|
||||
void fuse_disable_programming(void);
|
||||
void fuse_secondary_private_key_disable(void);
|
||||
void fuse_disable_private_key(void);
|
||||
|
||||
uint32_t fuse_get_sku_info(void);
|
||||
uint32_t fuse_get_spare_bit(uint32_t idx);
|
||||
uint32_t fuse_get_reserved_odm(uint32_t idx);
|
||||
|
||||
uint32_t fuse_get_bootrom_patch_version(void);
|
||||
uint64_t fuse_get_device_id(void);
|
||||
uint32_t fuse_get_dram_id(void);
|
||||
uint32_t fuse_get_hardware_type(void);
|
||||
uint32_t fuse_get_hardware_type(uint32_t target_firmware);
|
||||
uint32_t fuse_get_retail_type(void);
|
||||
void fuse_get_hardware_info(void *dst);
|
||||
|
||||
uint32_t fuse_hw_read(uint32_t addr);
|
||||
void fuse_hw_write(uint32_t value, uint32_t addr);
|
||||
void fuse_hw_sense(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -162,16 +162,16 @@ void config_se_brom()
|
||||
set_aes_keyslot(0xE, sbk, 0x10);
|
||||
|
||||
/* Lock SBK from being read. */
|
||||
se->AES_KEYSLOT_FLAGS[0xE] = 0x7E;
|
||||
se->SE_CRYPTO_KEYTABLE_ACCESS[0xE] = 0x7E;
|
||||
|
||||
/* This memset needs to happen here, else TZRAM will behave weirdly later on. */
|
||||
memset((void *)0x7C010000, 0, 0x10000);
|
||||
|
||||
pmc->crypto_op = 0;
|
||||
se->INT_STATUS_REG = 0x1F;
|
||||
se->SE_INT_STATUS = 0x1F;
|
||||
|
||||
/* Lock SSK (although it's not set and unused anyways). */
|
||||
se->AES_KEYSLOT_FLAGS[0xF] = 0x7E;
|
||||
se->SE_CRYPTO_KEYTABLE_ACCESS[0xF] = 0x7E;
|
||||
|
||||
/* Clear the boot reason to avoid problems later */
|
||||
pmc->scratch200 = 0;
|
||||
|
||||
@@ -39,20 +39,20 @@ void NOINLINE ll_init(volatile se_ll_t *ll, void *buffer, size_t size) {
|
||||
}
|
||||
|
||||
void se_check_error_status_reg(void) {
|
||||
if (se_get_regs()->ERR_STATUS_REG) {
|
||||
if (se_get_regs()->SE_ERR_STATUS) {
|
||||
generic_panic();
|
||||
}
|
||||
}
|
||||
|
||||
void se_check_for_error(void) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
if (se->INT_STATUS_REG & 0x10000 || se->FLAGS_REG & 3 || se->ERR_STATUS_REG) {
|
||||
if (se->SE_INT_STATUS & 0x10000 || se->SE_STATUS & 3 || se->SE_ERR_STATUS) {
|
||||
generic_panic();
|
||||
}
|
||||
}
|
||||
|
||||
void se_verify_flags_cleared(void) {
|
||||
if (se_get_regs()->FLAGS_REG & 3) {
|
||||
if (se_get_regs()->SE_STATUS & 3) {
|
||||
generic_panic();
|
||||
}
|
||||
}
|
||||
@@ -67,12 +67,12 @@ void set_aes_keyslot_flags(unsigned int keyslot, unsigned int flags) {
|
||||
|
||||
/* Misc flags. */
|
||||
if (flags & ~0x80) {
|
||||
se->AES_KEYSLOT_FLAGS[keyslot] = ~flags;
|
||||
se->SE_CRYPTO_KEYTABLE_ACCESS[keyslot] = ~flags;
|
||||
}
|
||||
|
||||
/* Disable keyslot reads. */
|
||||
if (flags & 0x80) {
|
||||
se->AES_KEY_READ_DISABLE_REG &= ~(1 << keyslot);
|
||||
se->SE_CRYPTO_SECURITY_PERKEY &= ~(1 << keyslot);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,12 +87,12 @@ void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags) {
|
||||
/* Misc flags. */
|
||||
if (flags & ~0x80) {
|
||||
/* TODO: Why are flags assigned this way? */
|
||||
se->RSA_KEYSLOT_FLAGS[keyslot] = (((flags >> 4) & 4) | (flags & 3)) ^ 7;
|
||||
se->SE_RSA_KEYTABLE_ACCESS[keyslot] = (((flags >> 4) & 4) | (flags & 3)) ^ 7;
|
||||
}
|
||||
|
||||
/* Disable keyslot reads. */
|
||||
if (flags & 0x80) {
|
||||
se->RSA_KEY_READ_DISABLE_REG &= ~(1 << keyslot);
|
||||
se->SE_RSA_SECURITY_PERKEY &= ~(1 << keyslot);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,8 +105,8 @@ void clear_aes_keyslot(unsigned int keyslot) {
|
||||
|
||||
/* Zero out the whole keyslot and IV. */
|
||||
for (unsigned int i = 0; i < 0x10; i++) {
|
||||
se->AES_KEYTABLE_ADDR = (keyslot << 4) | i;
|
||||
se->AES_KEYTABLE_DATA = 0;
|
||||
se->SE_CRYPTO_KEYTABLE_ADDR = (keyslot << 4) | i;
|
||||
se->SE_CRYPTO_KEYTABLE_DATA = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,13 +120,13 @@ void clear_rsa_keyslot(unsigned int keyslot) {
|
||||
/* Zero out the whole keyslot. */
|
||||
for (unsigned int i = 0; i < 0x40; i++) {
|
||||
/* Select Keyslot Modulus[i] */
|
||||
se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i | 0x40;
|
||||
se->RSA_KEYTABLE_DATA = 0;
|
||||
se->SE_RSA_KEYTABLE_ADDR = (keyslot << 7) | i | 0x40;
|
||||
se->SE_RSA_KEYTABLE_DATA = 0;
|
||||
}
|
||||
for (unsigned int i = 0; i < 0x40; i++) {
|
||||
/* Select Keyslot Expontent[i] */
|
||||
se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i;
|
||||
se->RSA_KEYTABLE_DATA = 0;
|
||||
se->SE_RSA_KEYTABLE_ADDR = (keyslot << 7) | i;
|
||||
se->SE_RSA_KEYTABLE_DATA = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,8 +138,8 @@ void set_aes_keyslot(unsigned int keyslot, const void *key, size_t key_size) {
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < (key_size >> 2); i++) {
|
||||
se->AES_KEYTABLE_ADDR = (keyslot << 4) | i;
|
||||
se->AES_KEYTABLE_DATA = read32le(key, 4 * i);
|
||||
se->SE_CRYPTO_KEYTABLE_ADDR = (keyslot << 4) | i;
|
||||
se->SE_CRYPTO_KEYTABLE_DATA = read32le(key, 4 * i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,13 +151,13 @@ void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < (modulus_size >> 2); i++) {
|
||||
se->RSA_KEYTABLE_ADDR = (keyslot << 7) | 0x40 | i;
|
||||
se->RSA_KEYTABLE_DATA = read32be(modulus, (4 * (modulus_size >> 2)) - (4 * i) - 4);
|
||||
se->SE_RSA_KEYTABLE_ADDR = (keyslot << 7) | 0x40 | i;
|
||||
se->SE_RSA_KEYTABLE_DATA = read32be(modulus, (4 * (modulus_size >> 2)) - (4 * i) - 4);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < (exp_size >> 2); i++) {
|
||||
se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i;
|
||||
se->RSA_KEYTABLE_DATA = read32be(exponent, (4 * (exp_size >> 2)) - (4 * i) - 4);
|
||||
se->SE_RSA_KEYTABLE_ADDR = (keyslot << 7) | i;
|
||||
se->SE_RSA_KEYTABLE_DATA = read32be(exponent, (4 * (exp_size >> 2)) - (4 * i) - 4);
|
||||
}
|
||||
|
||||
g_se_modulus_sizes[keyslot] = modulus_size;
|
||||
@@ -172,8 +172,8 @@ void set_aes_keyslot_iv(unsigned int keyslot, const void *iv, size_t iv_size) {
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < (iv_size >> 2); i++) {
|
||||
se->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i;
|
||||
se->AES_KEYTABLE_DATA = read32le(iv, 4 * i);
|
||||
se->SE_CRYPTO_KEYTABLE_ADDR = (keyslot << 4) | 8 | i;
|
||||
se->SE_CRYPTO_KEYTABLE_DATA = read32le(iv, 4 * i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,14 +185,14 @@ void clear_aes_keyslot_iv(unsigned int keyslot) {
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < (0x10 >> 2); i++) {
|
||||
se->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i;
|
||||
se->AES_KEYTABLE_DATA = 0;
|
||||
se->SE_CRYPTO_KEYTABLE_ADDR = (keyslot << 4) | 8 | i;
|
||||
se->SE_CRYPTO_KEYTABLE_DATA = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void set_se_ctr(const void *ctr) {
|
||||
for (unsigned int i = 0; i < 4; i++) {
|
||||
se_get_regs()->CRYPTO_CTR_REG[i] = read32le(ctr, i * 4);
|
||||
se_get_regs()->SE_CRYPTO_LINEAR_CTR[i] = read32le(ctr, i * 4);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,10 +203,10 @@ void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_sr
|
||||
generic_panic();
|
||||
}
|
||||
|
||||
se->CONFIG_REG = (ALG_AES_DEC | DST_KEYTAB);
|
||||
se->CRYPTO_REG = keyslot_src << 24;
|
||||
se->BLOCK_COUNT_REG = 0;
|
||||
se->CRYPTO_KEYTABLE_DST_REG = keyslot_dst << 8;
|
||||
se->SE_CONFIG = (ALG_AES_DEC | DST_KEYTAB);
|
||||
se->SE_CRYPTO_CONFIG = keyslot_src << 24;
|
||||
se->SE_CRYPTO_LAST_BLOCK = 0;
|
||||
se->SE_CRYPTO_KEYTABLE_DST = keyslot_dst << 8;
|
||||
|
||||
trigger_se_blocking_op(OP_START, NULL, 0, wrapped_key, wrapped_key_size);
|
||||
}
|
||||
@@ -224,10 +224,10 @@ void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, co
|
||||
stack_buf[i] = *((uint8_t *)src + src_size - i - 1);
|
||||
}
|
||||
|
||||
se->CONFIG_REG = (ALG_RSA | DST_RSAREG);
|
||||
se->RSA_CONFIG = keyslot << 24;
|
||||
se->RSA_KEY_SIZE_REG = (g_se_modulus_sizes[keyslot] >> 6) - 1;
|
||||
se->RSA_EXP_SIZE_REG = g_se_exp_sizes[keyslot] >> 2;
|
||||
se->SE_CONFIG = (ALG_RSA | DST_RSAREG);
|
||||
se->SE_RSA_CONFIG = keyslot << 24;
|
||||
se->SE_RSA_KEY_SIZE = (g_se_modulus_sizes[keyslot] >> 6) - 1;
|
||||
se->SE_RSA_EXP_SIZE = g_se_exp_sizes[keyslot] >> 2;
|
||||
|
||||
trigger_se_blocking_op(OP_START, NULL, 0, stack_buf, src_size);
|
||||
se_get_exp_mod_output(dst, dst_size);
|
||||
@@ -245,7 +245,7 @@ void se_get_exp_mod_output(void *buf, size_t size) {
|
||||
|
||||
/* Copy endian swapped output. */
|
||||
while (num_dwords) {
|
||||
*p_out = read32be(se_get_regs()->RSA_OUTPUT, offset);
|
||||
*p_out = read32be(se_get_regs()->SE_RSA_OUTPUT, offset);
|
||||
offset += 4;
|
||||
p_out--;
|
||||
num_dwords--;
|
||||
@@ -314,15 +314,15 @@ void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const v
|
||||
ll_init(&out_ll, dst, dst_size);
|
||||
|
||||
/* Set the LLs. */
|
||||
se->IN_LL_ADDR_REG = (uint32_t) get_physical_address(&in_ll);
|
||||
se->OUT_LL_ADDR_REG = (uint32_t) get_physical_address(&out_ll);
|
||||
se->SE_IN_LL_ADDR = (uint32_t) get_physical_address(&in_ll);
|
||||
se->SE_OUT_LL_ADDR = (uint32_t) get_physical_address(&out_ll);
|
||||
|
||||
/* Set registers for operation. */
|
||||
se->ERR_STATUS_REG = se->ERR_STATUS_REG;
|
||||
se->INT_STATUS_REG = se->INT_STATUS_REG;
|
||||
se->OPERATION_REG = op;
|
||||
se->SE_ERR_STATUS = se->SE_ERR_STATUS;
|
||||
se->SE_INT_STATUS = se->SE_INT_STATUS;
|
||||
se->SE_OPERATION = op;
|
||||
|
||||
while (!(se->INT_STATUS_REG & 0x10)) { /* Wait a while */ }
|
||||
while (!(se->SE_INT_STATUS & 0x10)) { /* Wait a while */ }
|
||||
se_check_for_error();
|
||||
}
|
||||
|
||||
@@ -340,7 +340,7 @@ void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src,
|
||||
}
|
||||
|
||||
/* Trigger AES operation. */
|
||||
se_get_regs()->BLOCK_COUNT_REG = 0;
|
||||
se_get_regs()->SE_CRYPTO_LAST_BLOCK = 0;
|
||||
trigger_se_blocking_op(OP_START, block, sizeof(block), block, sizeof(block));
|
||||
|
||||
/* Copy output data into dst. */
|
||||
@@ -358,15 +358,15 @@ void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const vo
|
||||
unsigned int num_blocks = src_size >> 4;
|
||||
|
||||
/* Unknown what this write does, but official code writes it for CTR mode. */
|
||||
se->SPARE_0 = 1;
|
||||
se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY);
|
||||
se->CRYPTO_REG = (keyslot << 24) | 0x91E;
|
||||
se->SE_SPARE = 1;
|
||||
se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY);
|
||||
se->SE_CRYPTO_CONFIG = (keyslot << 24) | 0x91E;
|
||||
set_se_ctr(ctr);
|
||||
|
||||
/* Handle any aligned blocks. */
|
||||
size_t aligned_size = (size_t)num_blocks << 4;
|
||||
if (aligned_size) {
|
||||
se->BLOCK_COUNT_REG = num_blocks - 1;
|
||||
se->SE_CRYPTO_LAST_BLOCK = num_blocks - 1;
|
||||
trigger_se_blocking_op(OP_START, dst, dst_size, src, aligned_size);
|
||||
}
|
||||
|
||||
@@ -388,8 +388,8 @@ void se_aes_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size,
|
||||
}
|
||||
|
||||
/* Set configuration high (256-bit vs 128-bit) based on parameter. */
|
||||
se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY) | (config_high << 16);
|
||||
se->CRYPTO_REG = keyslot << 24 | 0x100;
|
||||
se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY) | (config_high << 16);
|
||||
se->SE_CRYPTO_CONFIG = keyslot << 24 | 0x100;
|
||||
se_perform_aes_block_operation(dst, 0x10, src, 0x10);
|
||||
}
|
||||
|
||||
@@ -408,8 +408,8 @@ void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size,
|
||||
generic_panic();
|
||||
}
|
||||
|
||||
se->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY);
|
||||
se->CRYPTO_REG = keyslot << 24;
|
||||
se->SE_CONFIG = (ALG_AES_DEC | DST_MEMORY);
|
||||
se->SE_CRYPTO_CONFIG = keyslot << 24;
|
||||
se_perform_aes_block_operation(dst, 0x10, src, 0x10);
|
||||
}
|
||||
|
||||
@@ -472,13 +472,13 @@ void aes_128_xts_nintendo_crypt_sector(unsigned int keyslot_1, unsigned int keys
|
||||
|
||||
/* Encrypt/Decrypt. */
|
||||
if (encrypt) {
|
||||
se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY);
|
||||
se->CRYPTO_REG = keyslot_1 << 24 | 0x100;
|
||||
se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY);
|
||||
se->SE_CRYPTO_CONFIG = keyslot_1 << 24 | 0x100;
|
||||
} else {
|
||||
se->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY);
|
||||
se->CRYPTO_REG = keyslot_1 << 24;
|
||||
se->SE_CONFIG = (ALG_AES_DEC | DST_MEMORY);
|
||||
se->SE_CRYPTO_CONFIG = keyslot_1 << 24;
|
||||
}
|
||||
se->BLOCK_COUNT_REG = (size >> 4) - 1;
|
||||
se->SE_CRYPTO_LAST_BLOCK = (size >> 4) - 1;
|
||||
trigger_se_blocking_op(OP_START, dst, size, src, size);
|
||||
|
||||
/* XOR. */
|
||||
@@ -524,16 +524,16 @@ void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, con
|
||||
shift_left_xor_rb(derived_key);
|
||||
}
|
||||
|
||||
se->CONFIG_REG = (ALG_AES_ENC | DST_HASHREG) | (config_high << 16);
|
||||
se->CRYPTO_REG = (keyslot << 24) | (0x145);
|
||||
se->SE_CONFIG = (ALG_AES_ENC | DST_HASHREG) | (config_high << 16);
|
||||
se->SE_CRYPTO_CONFIG = (keyslot << 24) | (0x145);
|
||||
clear_aes_keyslot_iv(keyslot);
|
||||
|
||||
unsigned int num_blocks = (data_size + 0xF) >> 4;
|
||||
/* Handle aligned blocks. */
|
||||
if (num_blocks > 1) {
|
||||
se->BLOCK_COUNT_REG = num_blocks - 2;
|
||||
se->SE_CRYPTO_LAST_BLOCK = num_blocks - 2;
|
||||
trigger_se_blocking_op(OP_START, NULL, 0, data, data_size);
|
||||
se->CRYPTO_REG |= 0x80;
|
||||
se->SE_CRYPTO_CONFIG |= 0x80;
|
||||
}
|
||||
|
||||
/* Create final block. */
|
||||
@@ -550,12 +550,12 @@ void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, con
|
||||
}
|
||||
|
||||
/* Perform last operation. */
|
||||
se->BLOCK_COUNT_REG = 0;
|
||||
se->SE_CRYPTO_LAST_BLOCK = 0;
|
||||
trigger_se_blocking_op(OP_START, NULL, 0, last_block, sizeof(last_block));
|
||||
|
||||
/* Copy output CMAC. */
|
||||
for (unsigned int i = 0; i < (cmac_size >> 2); i++) {
|
||||
((uint32_t *)cmac)[i] = read32le(se->HASH_RESULT_REG, i << 2);
|
||||
((uint32_t *)cmac)[i] = read32le(se->SE_HASH_RESULT, i << 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -573,10 +573,10 @@ void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, co
|
||||
generic_panic();
|
||||
}
|
||||
|
||||
se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY) | (0x202 << 16);
|
||||
se->CRYPTO_REG = (keyslot << 24) | 0x144;
|
||||
se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY) | (0x202 << 16);
|
||||
se->SE_CRYPTO_CONFIG = (keyslot << 24) | 0x144;
|
||||
set_aes_keyslot_iv(keyslot, iv, 0x10);
|
||||
se->BLOCK_COUNT_REG = (src_size >> 4) - 1;
|
||||
se->SE_CRYPTO_LAST_BLOCK = (src_size >> 4) - 1;
|
||||
trigger_se_blocking_op(OP_START, dst, dst_size, src, src_size);
|
||||
}
|
||||
|
||||
@@ -585,23 +585,23 @@ void se_calculate_sha256(void *dst, const void *src, size_t src_size) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
|
||||
/* Setup config for SHA256, size = BITS(src_size) */
|
||||
se->CONFIG_REG = (ENCMODE_SHA256 | ALG_SHA | DST_HASHREG);
|
||||
se->SHA_CONFIG_REG = 1;
|
||||
se->SHA_MSG_LENGTH_REG = (uint32_t)(src_size << 3);
|
||||
se->_0x208 = 0;
|
||||
se->_0x20C = 0;
|
||||
se->_0x210 = 0;
|
||||
se->SHA_MSG_LEFT_REG = (uint32_t)(src_size << 3);
|
||||
se->_0x218 = 0;
|
||||
se->_0x21C = 0;
|
||||
se->_0x220 = 0;
|
||||
se->SE_CONFIG = (ENCMODE_SHA256 | ALG_SHA | DST_HASHREG);
|
||||
se->SE_SHA_CONFIG = 1;
|
||||
se->SE_SHA_MSG_LENGTH[0] = (uint32_t)(src_size << 3);
|
||||
se->SE_SHA_MSG_LENGTH[1] = 0;
|
||||
se->SE_SHA_MSG_LENGTH[2] = 0;
|
||||
se->SE_SHA_MSG_LENGTH[3] = 0;
|
||||
se->SE_SHA_MSG_LEFT[0] = (uint32_t)(src_size << 3);
|
||||
se->SE_SHA_MSG_LEFT[1] = 0;
|
||||
se->SE_SHA_MSG_LEFT[2] = 0;
|
||||
se->SE_SHA_MSG_LEFT[3] = 0;
|
||||
|
||||
/* Trigger the operation. */
|
||||
trigger_se_blocking_op(OP_START, NULL, 0, src, src_size);
|
||||
|
||||
/* Copy output hash. */
|
||||
for (unsigned int i = 0; i < (0x20 >> 2); i++) {
|
||||
((uint32_t *)dst)[i] = read32be(se->HASH_RESULT_REG, i << 2);
|
||||
((uint32_t *)dst)[i] = read32be(se->SE_HASH_RESULT, i << 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -617,12 +617,12 @@ void se_initialize_rng(unsigned int keyslot) {
|
||||
/* This will be discarded, when done. */
|
||||
uint8_t ALIGN(16) output_buf[0x10];
|
||||
|
||||
se->RNG_SRC_CONFIG_REG = 3; /* Entropy enable + Entropy lock enable */
|
||||
se->RNG_RESEED_INTERVAL_REG = 70001;
|
||||
se->CONFIG_REG = (ALG_RNG | DST_MEMORY);
|
||||
se->CRYPTO_REG = (keyslot << 24) | 0x108;
|
||||
se->RNG_CONFIG_REG = 5;
|
||||
se->BLOCK_COUNT_REG = 0;
|
||||
se->SE_RNG_SRC_CONFIG = 3; /* Entropy enable + Entropy lock enable */
|
||||
se->SE_RNG_RESEED_INTERVAL = 70001;
|
||||
se->SE_CONFIG = (ALG_RNG | DST_MEMORY);
|
||||
se->SE_CRYPTO_CONFIG = (keyslot << 24) | 0x108;
|
||||
se->SE_RNG_CONFIG = 5;
|
||||
se->SE_CRYPTO_LAST_BLOCK = 0;
|
||||
trigger_se_blocking_op(OP_START, output_buf, 0x10, NULL, 0);
|
||||
}
|
||||
|
||||
@@ -635,12 +635,12 @@ void se_generate_random(unsigned int keyslot, void *dst, size_t size) {
|
||||
|
||||
uint32_t num_blocks = size >> 4;
|
||||
size_t aligned_size = num_blocks << 4;
|
||||
se->CONFIG_REG = (ALG_RNG | DST_MEMORY);
|
||||
se->CRYPTO_REG = (keyslot << 24) | 0x108;
|
||||
se->RNG_CONFIG_REG = 4;
|
||||
se->SE_CONFIG = (ALG_RNG | DST_MEMORY);
|
||||
se->SE_CRYPTO_CONFIG = (keyslot << 24) | 0x108;
|
||||
se->SE_RNG_CONFIG = 4;
|
||||
|
||||
if (num_blocks >= 1) {
|
||||
se->BLOCK_COUNT_REG = num_blocks - 1;
|
||||
se->SE_CRYPTO_LAST_BLOCK = num_blocks - 1;
|
||||
trigger_se_blocking_op(OP_START, dst, aligned_size, NULL, 0);
|
||||
}
|
||||
if (size > aligned_size) {
|
||||
|
||||
@@ -92,71 +92,59 @@
|
||||
#define RSA_2048_BYTES 0x100
|
||||
|
||||
typedef struct {
|
||||
uint32_t _0x0;
|
||||
uint32_t _0x4;
|
||||
uint32_t OPERATION_REG;
|
||||
uint32_t INT_ENABLE_REG;
|
||||
uint32_t INT_STATUS_REG;
|
||||
uint32_t CONFIG_REG;
|
||||
uint32_t IN_LL_ADDR_REG;
|
||||
uint32_t _0x1C;
|
||||
uint32_t _0x20;
|
||||
uint32_t OUT_LL_ADDR_REG;
|
||||
uint32_t _0x28;
|
||||
uint32_t _0x2C;
|
||||
uint8_t HASH_RESULT_REG[0x20];
|
||||
uint8_t _0x50[0x20];
|
||||
uint32_t CONTEXT_SAVE_CONFIG_REG;
|
||||
uint8_t _0x74[0x18C];
|
||||
uint32_t SHA_CONFIG_REG;
|
||||
uint32_t SHA_MSG_LENGTH_REG;
|
||||
uint32_t _0x208;
|
||||
uint32_t _0x20C;
|
||||
uint32_t _0x210;
|
||||
uint32_t SHA_MSG_LEFT_REG;
|
||||
uint32_t _0x218;
|
||||
uint32_t _0x21C;
|
||||
uint32_t _0x220;
|
||||
uint32_t _0x224;
|
||||
uint8_t _0x228[0x58];
|
||||
uint32_t AES_KEY_READ_DISABLE_REG;
|
||||
uint32_t AES_KEYSLOT_FLAGS[0x10];
|
||||
uint8_t _0x2C4[0x3C];
|
||||
uint32_t _0x300;
|
||||
uint32_t CRYPTO_REG;
|
||||
uint32_t CRYPTO_CTR_REG[4];
|
||||
uint32_t BLOCK_COUNT_REG;
|
||||
uint32_t AES_KEYTABLE_ADDR;
|
||||
uint32_t AES_KEYTABLE_DATA;
|
||||
uint32_t _0x324;
|
||||
uint32_t _0x328;
|
||||
uint32_t _0x32C;
|
||||
uint32_t CRYPTO_KEYTABLE_DST_REG;
|
||||
uint8_t _0x334[0xC];
|
||||
uint32_t RNG_CONFIG_REG;
|
||||
uint32_t RNG_SRC_CONFIG_REG;
|
||||
uint32_t RNG_RESEED_INTERVAL_REG;
|
||||
uint8_t _0x34C[0xB4];
|
||||
uint32_t RSA_CONFIG;
|
||||
uint32_t RSA_KEY_SIZE_REG;
|
||||
uint32_t RSA_EXP_SIZE_REG;
|
||||
uint32_t RSA_KEY_READ_DISABLE_REG;
|
||||
uint32_t RSA_KEYSLOT_FLAGS[2];
|
||||
uint32_t _0x418;
|
||||
uint32_t _0x41C;
|
||||
uint32_t RSA_KEYTABLE_ADDR;
|
||||
uint32_t RSA_KEYTABLE_DATA;
|
||||
uint8_t RSA_OUTPUT[0x100];
|
||||
uint8_t _0x528[0x2D8];
|
||||
uint32_t FLAGS_REG;
|
||||
uint32_t ERR_STATUS_REG;
|
||||
uint32_t _0x808;
|
||||
uint32_t SPARE_0;
|
||||
uint32_t _0x810;
|
||||
uint32_t SE_SE_SECURITY;
|
||||
uint32_t SE_TZRAM_SECURITY;
|
||||
uint32_t SE_OPERATION;
|
||||
uint32_t SE_INT_ENABLE;
|
||||
uint32_t SE_INT_STATUS;
|
||||
uint32_t SE_CONFIG;
|
||||
uint32_t SE_IN_LL_ADDR;
|
||||
uint32_t SE_IN_CUR_BYTE_ADDR;
|
||||
uint32_t SE_IN_CUR_LL_ID;
|
||||
uint32_t SE_OUT_LL_ADDR;
|
||||
uint32_t SE_OUT_CUR_BYTE_ADDR;
|
||||
uint32_t SE_OUT_CUR_LL_ID;
|
||||
uint32_t SE_HASH_RESULT[0x10];
|
||||
uint32_t SE_CTX_SAVE_CONFIG;
|
||||
uint32_t _0x74[0x63];
|
||||
uint32_t SE_SHA_CONFIG;
|
||||
uint32_t SE_SHA_MSG_LENGTH[0x4];
|
||||
uint32_t SE_SHA_MSG_LEFT[0x4];
|
||||
uint32_t _0x224[0x17];
|
||||
uint32_t SE_CRYPTO_SECURITY_PERKEY;
|
||||
uint32_t SE_CRYPTO_KEYTABLE_ACCESS[0x10];
|
||||
uint32_t _0x2C4[0x10];
|
||||
uint32_t SE_CRYPTO_CONFIG;
|
||||
uint32_t SE_CRYPTO_LINEAR_CTR[0x4];
|
||||
uint32_t SE_CRYPTO_LAST_BLOCK;
|
||||
uint32_t SE_CRYPTO_KEYTABLE_ADDR;
|
||||
uint32_t SE_CRYPTO_KEYTABLE_DATA;
|
||||
uint32_t _0x324[0x3];
|
||||
uint32_t SE_CRYPTO_KEYTABLE_DST;
|
||||
uint32_t _0x334[0x3];
|
||||
uint32_t SE_RNG_CONFIG;
|
||||
uint32_t SE_RNG_SRC_CONFIG;
|
||||
uint32_t SE_RNG_RESEED_INTERVAL;
|
||||
uint32_t _0x34C[0x2D];
|
||||
uint32_t SE_RSA_CONFIG;
|
||||
uint32_t SE_RSA_KEY_SIZE;
|
||||
uint32_t SE_RSA_EXP_SIZE;
|
||||
uint32_t SE_RSA_SECURITY_PERKEY;
|
||||
uint32_t SE_RSA_KEYTABLE_ACCESS[0x2];
|
||||
uint32_t _0x418[0x2];
|
||||
uint32_t SE_RSA_KEYTABLE_ADDR;
|
||||
uint32_t SE_RSA_KEYTABLE_DATA;
|
||||
uint32_t SE_RSA_OUTPUT[0x40];
|
||||
uint32_t _0x528[0xB6];
|
||||
uint32_t SE_STATUS;
|
||||
uint32_t SE_ERR_STATUS;
|
||||
uint32_t SE_MISC;
|
||||
uint32_t SE_SPARE;
|
||||
uint32_t SE_ENTROPY_DEBUG_COUNTER;
|
||||
uint32_t _0x814;
|
||||
uint32_t _0x818;
|
||||
uint32_t _0x81C;
|
||||
uint8_t _0x820[0x17E0];
|
||||
uint32_t _0x820[0x5F8];
|
||||
} tegra_se_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -89,7 +89,7 @@ export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
|
||||
$(AMS)/exosphere $(AMS)/exosphere/lp0fw $(AMS)/exosphere/rebootstub \
|
||||
$(AMS)/thermosphere $(AMS)/fusee/fusee-primary $(AMS)/sept/sept-primary \
|
||||
$(AMS)/sept/sept-secondary $(AMS)/emummc $(KIPDIRS)
|
||||
$(AMS)/sept/sept-secondary $(AMS)/emummc $(AMS)/mesosphere/kernel_ldr $(KIPDIRS)
|
||||
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
@@ -100,7 +100,7 @@ KIPFILES := loader.kip pm.kip sm.kip ams_mitm.kip spl.kip boot.kip
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) fusee-primary.bin \
|
||||
exosphere.bin lp0fw.bin rebootstub.bin thermosphere.bin splash_screen.bmp \
|
||||
sept-primary.bin sept-secondary_00.enc sept-secondary_01.enc emummc.kip \
|
||||
$(KIPFILES)
|
||||
kernel_ldr.bin $(KIPFILES)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
@@ -151,11 +151,14 @@ check_thermosphere:
|
||||
check_stratosphere: check_libraries
|
||||
@$(MAKE) -C $(AMS)/stratosphere all
|
||||
|
||||
check_mesosphere: check_libraries
|
||||
@$(MAKE) -C $(AMS)/mesosphere all
|
||||
|
||||
check_libraries:
|
||||
@$(MAKE) -C $(AMS)/libraries all
|
||||
|
||||
|
||||
$(BUILD): check_fusee_primary check_exosphere check_sept check_emummc check_thermosphere check_libraries check_stratosphere
|
||||
$(BUILD): check_fusee_primary check_exosphere check_sept check_emummc check_thermosphere check_libraries check_stratosphere check_mesosphere
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
@@ -166,6 +169,7 @@ clean:
|
||||
@$(MAKE) -C $(AMS)/exosphere clean
|
||||
@$(MAKE) -C $(AMS)/thermosphere clean
|
||||
@$(MAKE) -C $(AMS)/libraries clean
|
||||
@$(MAKE) -C $(AMS)/mesosphere clean
|
||||
@$(MAKE) -C $(AMS)/stratosphere clean
|
||||
@$(MAKE) -C $(AMS)/sept clean
|
||||
@$(MAKE) -C $(AMS)/emummc clean
|
||||
|
||||
@@ -250,4 +250,6 @@ SECTIONS
|
||||
PROVIDE(__thermosphere_bin_size__ = thermosphere_bin_end - thermosphere_bin);
|
||||
PROVIDE(__emummc_kip_start__ = emummc_kip - __start__);
|
||||
PROVIDE(__emummc_kip_size__ = emummc_kip_end - emummc_kip);
|
||||
PROVIDE(__kernel_ldr_bin_start__ = kernel_ldr_bin - __start__);
|
||||
PROVIDE(__kernel_ldr_bin_size__ = kernel_ldr_bin_end - kernel_ldr_bin);
|
||||
}
|
||||
|
||||
@@ -13,171 +13,178 @@
|
||||
* 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 <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <vapours/ams_version.h>
|
||||
|
||||
#include "car.h"
|
||||
#include "fuse.h"
|
||||
#include "pmc.h"
|
||||
#include "timers.h"
|
||||
|
||||
/* Prototypes for internal commands. */
|
||||
void fuse_make_regs_visible(void);
|
||||
|
||||
void fuse_enable_power(void);
|
||||
void fuse_disable_power(void);
|
||||
void fuse_wait_idle(void);
|
||||
|
||||
/* Initialize the fuse driver */
|
||||
void fuse_init(void) {
|
||||
fuse_make_regs_visible();
|
||||
fuse_secondary_private_key_disable();
|
||||
fuse_disable_programming();
|
||||
|
||||
/* TODO: Overrides (iROM patches) and various reads happen here */
|
||||
}
|
||||
|
||||
/* Make all fuse registers visible */
|
||||
void fuse_make_regs_visible(void) {
|
||||
/* Make all fuse registers visible, disable the private key and disable programming. */
|
||||
clkrst_enable_fuse_regs(true);
|
||||
fuse_disable_private_key();
|
||||
fuse_disable_programming();
|
||||
}
|
||||
|
||||
/* Enable power to the fuse hardware array */
|
||||
/* Disable access to the private key and set the TZ sticky bit. */
|
||||
void fuse_disable_private_key(void) {
|
||||
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||
fuse->FUSE_PRIVATEKEYDISABLE = 0x10;
|
||||
}
|
||||
|
||||
/* Disables all fuse programming. */
|
||||
void fuse_disable_programming(void) {
|
||||
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||
fuse->FUSE_DISABLEREGPROGRAM = 1;
|
||||
}
|
||||
|
||||
/* Enable power to the fuse hardware array. */
|
||||
void fuse_enable_power(void) {
|
||||
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||
fuse->FUSE_PWR_GOOD_SW = 1;
|
||||
udelay(1);
|
||||
volatile tegra_pmc_t *pmc = pmc_get_regs();
|
||||
pmc->fuse_control &= ~(0x200); /* Clear PMC_FUSE_CTRL_PS18_LATCH_CLEAR. */
|
||||
mdelay(1);
|
||||
pmc->fuse_control |= 0x100; /* Set PMC_FUSE_CTRL_PS18_LATCH_SET. */
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
/* Disable power to the fuse hardware array */
|
||||
/* Disable power to the fuse hardware array. */
|
||||
void fuse_disable_power(void) {
|
||||
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||
fuse->FUSE_PWR_GOOD_SW = 0;
|
||||
udelay(1);
|
||||
volatile tegra_pmc_t *pmc = pmc_get_regs();
|
||||
pmc->fuse_control &= ~(0x100); /* Clear PMC_FUSE_CTRL_PS18_LATCH_SET. */
|
||||
mdelay(1);
|
||||
pmc->fuse_control |= 0x200; /* Set PMC_FUSE_CTRL_PS18_LATCH_CLEAR. */
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
/* Wait for the fuse driver to go idle */
|
||||
/* Wait for the fuse driver to go idle. */
|
||||
void fuse_wait_idle(void) {
|
||||
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||
uint32_t ctrl_val = 0;
|
||||
|
||||
/* Wait for STATE_IDLE */
|
||||
while ((ctrl_val & (0xF0000)) != 0x40000)
|
||||
{
|
||||
udelay(1);
|
||||
ctrl_val = fuse->FUSE_CTRL;
|
||||
}
|
||||
ctrl_val = fuse->FUSE_FUSECTRL;
|
||||
}
|
||||
|
||||
/* Read a fuse from the hardware array */
|
||||
/* Read a fuse from the hardware array. */
|
||||
uint32_t fuse_hw_read(uint32_t addr) {
|
||||
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||
|
||||
/* Wait for idle state. */
|
||||
fuse_wait_idle();
|
||||
|
||||
/* Program the target address */
|
||||
fuse->FUSE_REG_ADDR = addr;
|
||||
/* Program the target address. */
|
||||
fuse->FUSE_FUSEADDR = addr;
|
||||
|
||||
/* Enable read operation in control register */
|
||||
uint32_t ctrl_val = fuse->FUSE_CTRL;
|
||||
/* Enable read operation in control register. */
|
||||
uint32_t ctrl_val = fuse->FUSE_FUSECTRL;
|
||||
ctrl_val &= ~0x3;
|
||||
ctrl_val |= 0x1; /* Set FUSE_READ command */
|
||||
fuse->FUSE_CTRL = ctrl_val;
|
||||
ctrl_val |= 0x1; /* Set READ command. */
|
||||
fuse->FUSE_FUSECTRL = ctrl_val;
|
||||
|
||||
/* Wait for idle state. */
|
||||
fuse_wait_idle();
|
||||
|
||||
return fuse->FUSE_REG_READ;
|
||||
return fuse->FUSE_FUSERDATA;
|
||||
}
|
||||
|
||||
/* Write a fuse in the hardware array */
|
||||
/* Write a fuse in the hardware array. */
|
||||
void fuse_hw_write(uint32_t value, uint32_t addr) {
|
||||
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||
|
||||
/* Wait for idle state. */
|
||||
fuse_wait_idle();
|
||||
|
||||
/* Program the target address and value */
|
||||
fuse->FUSE_REG_ADDR = addr;
|
||||
fuse->FUSE_REG_WRITE = value;
|
||||
/* Program the target address and value. */
|
||||
fuse->FUSE_FUSEADDR = addr;
|
||||
fuse->FUSE_FUSEWDATA = value;
|
||||
|
||||
/* Enable write operation in control register */
|
||||
uint32_t ctrl_val = fuse->FUSE_CTRL;
|
||||
/* Enable write operation in control register. */
|
||||
uint32_t ctrl_val = fuse->FUSE_FUSECTRL;
|
||||
ctrl_val &= ~0x3;
|
||||
ctrl_val |= 0x2; /* Set FUSE_WRITE command */
|
||||
fuse->FUSE_CTRL = ctrl_val;
|
||||
ctrl_val |= 0x2; /* Set WRITE command. */
|
||||
fuse->FUSE_FUSECTRL = ctrl_val;
|
||||
|
||||
/* Wait for idle state. */
|
||||
fuse_wait_idle();
|
||||
}
|
||||
|
||||
/* Sense the fuse hardware array into the shadow cache */
|
||||
/* Sense the fuse hardware array into the shadow cache. */
|
||||
void fuse_hw_sense(void) {
|
||||
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||
|
||||
/* Wait for idle state. */
|
||||
fuse_wait_idle();
|
||||
|
||||
/* Enable sense operation in control register */
|
||||
uint32_t ctrl_val = fuse->FUSE_CTRL;
|
||||
uint32_t ctrl_val = fuse->FUSE_FUSECTRL;
|
||||
ctrl_val &= ~0x3;
|
||||
ctrl_val |= 0x3; /* Set FUSE_SENSE command */
|
||||
fuse->FUSE_CTRL = ctrl_val;
|
||||
ctrl_val |= 0x3; /* Set SENSE_CTRL command */
|
||||
fuse->FUSE_FUSECTRL = ctrl_val;
|
||||
|
||||
/* Wait for idle state. */
|
||||
fuse_wait_idle();
|
||||
}
|
||||
|
||||
/* Disables all fuse programming. */
|
||||
void fuse_disable_programming(void) {
|
||||
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||
fuse->FUSE_DIS_PGM = 1;
|
||||
}
|
||||
|
||||
/* Unknown exactly what this does, but it alters the contents read from the fuse cache. */
|
||||
void fuse_secondary_private_key_disable(void) {
|
||||
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||
fuse->FUSE_PRIVATEKEYDISABLE = 0x10;
|
||||
}
|
||||
|
||||
|
||||
/* Read the SKU info register from the shadow cache */
|
||||
/* Read the SKU info register from the shadow cache. */
|
||||
uint32_t fuse_get_sku_info(void) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
return fuse_chip->FUSE_SKU_INFO;
|
||||
}
|
||||
|
||||
/* Read the bootrom patch version from a register in the shadow cache */
|
||||
/* Read the bootrom patch version from a register in the shadow cache. */
|
||||
uint32_t fuse_get_bootrom_patch_version(void) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
return fuse_chip->FUSE_SOC_SPEEDO_1;
|
||||
return fuse_chip->FUSE_SOC_SPEEDO_1_CALIB;
|
||||
}
|
||||
|
||||
/* Read a spare bit register from the shadow cache */
|
||||
uint32_t fuse_get_spare_bit(uint32_t idx) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
|
||||
if (idx >= 32) {
|
||||
if (idx < 32) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
return fuse_chip->FUSE_SPARE_BIT[idx];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return fuse_chip->FUSE_SPARE_BIT[idx];
|
||||
}
|
||||
|
||||
/* Read a reserved ODM register from the shadow cache */
|
||||
/* Read a reserved ODM register from the shadow cache. */
|
||||
uint32_t fuse_get_reserved_odm(uint32_t idx) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
|
||||
if (idx >= 8) {
|
||||
if (idx < 8) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
return fuse_chip->FUSE_RESERVED_ODM[idx];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return fuse_chip->FUSE_RESERVED_ODM[idx];
|
||||
}
|
||||
|
||||
/* Derive the Device ID using values in the shadow cache */
|
||||
/* Get the DRAM ID using values in the shadow cache. */
|
||||
uint32_t fuse_get_dram_id(void) {
|
||||
return ((fuse_get_reserved_odm(4) >> 3) & 0x7);
|
||||
}
|
||||
|
||||
/* Derive the Device ID using values in the shadow cache. */
|
||||
uint64_t fuse_get_device_id(void) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
|
||||
|
||||
uint64_t device_id = 0;
|
||||
uint64_t y_coord = fuse_chip->FUSE_Y_COORDINATE & 0x1FF;
|
||||
uint64_t x_coord = fuse_chip->FUSE_X_COORDINATE & 0x1FF;
|
||||
uint64_t wafer_id = fuse_chip->FUSE_WAFER_ID & 0x3F;
|
||||
uint32_t lot_code = fuse_chip->FUSE_LOT_CODE_0;
|
||||
uint64_t fab_code = fuse_chip->FUSE_FAB_CODE & 0x3F;
|
||||
uint64_t y_coord = fuse_chip->FUSE_OPT_Y_COORDINATE & 0x1FF;
|
||||
uint64_t x_coord = fuse_chip->FUSE_OPT_X_COORDINATE & 0x1FF;
|
||||
uint64_t wafer_id = fuse_chip->FUSE_OPT_WAFER_ID & 0x3F;
|
||||
uint32_t lot_code = fuse_chip->FUSE_OPT_LOT_CODE_0;
|
||||
uint64_t fab_code = fuse_chip->FUSE_OPT_FAB_CODE & 0x3F;
|
||||
|
||||
uint64_t derived_lot_code = 0;
|
||||
for (unsigned int i = 0; i < 5; i++) {
|
||||
derived_lot_code = (derived_lot_code * 0x24) + ((lot_code >> (24 - 6*i)) & 0x3F);
|
||||
@@ -189,45 +196,41 @@ uint64_t fuse_get_device_id(void) {
|
||||
device_id |= wafer_id << 18;
|
||||
device_id |= derived_lot_code << 24;
|
||||
device_id |= fab_code << 50;
|
||||
|
||||
return device_id;
|
||||
}
|
||||
|
||||
/* Get the DRAM ID using values in the shadow cache */
|
||||
uint32_t fuse_get_dram_id(void) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
return (fuse_chip->FUSE_RESERVED_ODM[4] >> 3) & 0x7;
|
||||
}
|
||||
/* Derive the Hardware Type using values in the shadow cache. */
|
||||
uint32_t fuse_get_hardware_type(uint32_t target_firmware) {
|
||||
uint32_t fuse_reserved_odm4 = fuse_get_reserved_odm(4);
|
||||
uint32_t hardware_type = (((fuse_reserved_odm4 >> 7) & 2) | ((fuse_reserved_odm4 >> 2) & 1));
|
||||
|
||||
/* Derive the Hardware Type using values in the shadow cache */
|
||||
uint32_t fuse_get_hardware_type(void) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
|
||||
/* This function is very different between 4.x and < 4.x */
|
||||
uint32_t hardware_type = ((fuse_chip->FUSE_RESERVED_ODM[4] >> 7) & 2) | ((fuse_chip->FUSE_RESERVED_ODM[4] >> 2) & 1);
|
||||
|
||||
/* TODO: choose; if (mkey_get_revision() >= MASTERKEY_REVISION_400_CURRENT) {
|
||||
static const uint32_t types[] = {0,1,4,3};
|
||||
|
||||
hardware_type |= (fuse_chip->FUSE_RESERVED_ODM[4] >> 14) & 0x3C;
|
||||
hardware_type--;
|
||||
return hardware_type > 3 ? 4 : types[hardware_type];
|
||||
} else {*/
|
||||
/* Firmware from versions 1.0.0 to 3.0.2. */
|
||||
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
if (hardware_type >= 1) {
|
||||
return hardware_type > 2 ? 3 : hardware_type - 1;
|
||||
return (hardware_type > 2) ? 3 : hardware_type - 1;
|
||||
} else if ((fuse_chip->FUSE_SPARE_BIT[9] & 1) == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return 3;
|
||||
}
|
||||
// }
|
||||
} else if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_700) { /* Firmware versions from 4.0.0 to 6.2.0. */
|
||||
static const uint32_t types[] = {0,1,4,3};
|
||||
hardware_type |= ((fuse_reserved_odm4 >> 14) & 0x3C);
|
||||
hardware_type--;
|
||||
return (hardware_type > 3) ? 4 : types[hardware_type];
|
||||
} else { /* Firmware versions from 7.0.0 onwards. */
|
||||
/* Always return 0 in retail. */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Derive the Retail Type using values in the shadow cache */
|
||||
/* Derive the Retail Type using values in the shadow cache. */
|
||||
uint32_t fuse_get_retail_type(void) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
|
||||
/* Retail type = IS_RETAIL | UNIT_TYPE */
|
||||
uint32_t retail_type = ((fuse_chip->FUSE_RESERVED_ODM[4] >> 7) & 4) | (fuse_chip->FUSE_RESERVED_ODM[4] & 3);
|
||||
/* Retail Type = IS_RETAIL | UNIT_TYPE. */
|
||||
uint32_t fuse_reserved_odm4 = fuse_get_reserved_odm(4);
|
||||
uint32_t retail_type = (((fuse_reserved_odm4 >> 7) & 4) | (fuse_reserved_odm4 & 3));
|
||||
if (retail_type == 4) { /* Standard retail unit, IS_RETAIL | 0. */
|
||||
return 1;
|
||||
} else if (retail_type == 3) { /* Standard dev unit, 0 | DEV_UNIT. */
|
||||
@@ -241,17 +244,17 @@ void fuse_get_hardware_info(void *dst) {
|
||||
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||
uint32_t hw_info[0x4];
|
||||
|
||||
uint32_t unk_hw_fuse = fuse_chip->_0x120 & 0x3F;
|
||||
uint32_t y_coord = fuse_chip->FUSE_Y_COORDINATE & 0x1FF;
|
||||
uint32_t x_coord = fuse_chip->FUSE_X_COORDINATE & 0x1FF;
|
||||
uint32_t wafer_id = fuse_chip->FUSE_WAFER_ID & 0x3F;
|
||||
uint32_t lot_code_0 = fuse_chip->FUSE_LOT_CODE_0;
|
||||
uint32_t lot_code_1 = fuse_chip->FUSE_LOT_CODE_1 & 0x0FFFFFFF;
|
||||
uint32_t fab_code = fuse_chip->FUSE_FAB_CODE & 0x3F;
|
||||
uint32_t vendor_code = fuse_chip->FUSE_VENDOR_CODE & 0xF;
|
||||
uint32_t ops_reserved = fuse_chip->FUSE_OPT_OPS_RESERVED & 0x3F;
|
||||
uint32_t y_coord = fuse_chip->FUSE_OPT_Y_COORDINATE & 0x1FF;
|
||||
uint32_t x_coord = fuse_chip->FUSE_OPT_X_COORDINATE & 0x1FF;
|
||||
uint32_t wafer_id = fuse_chip->FUSE_OPT_WAFER_ID & 0x3F;
|
||||
uint32_t lot_code_0 = fuse_chip->FUSE_OPT_LOT_CODE_0;
|
||||
uint32_t lot_code_1 = fuse_chip->FUSE_OPT_LOT_CODE_1 & 0x0FFFFFFF;
|
||||
uint32_t fab_code = fuse_chip->FUSE_OPT_FAB_CODE & 0x3F;
|
||||
uint32_t vendor_code = fuse_chip->FUSE_OPT_VENDOR_CODE & 0xF;
|
||||
|
||||
/* Hardware Info = unk_hw_fuse || Y_COORD || X_COORD || WAFER_ID || LOT_CODE || FAB_CODE || VENDOR_ID */
|
||||
hw_info[0] = (uint32_t)((lot_code_1 << 30) | (wafer_id << 24) | (x_coord << 15) | (y_coord << 6) | (unk_hw_fuse));
|
||||
/* Hardware Info = OPS_RESERVED || Y_COORD || X_COORD || WAFER_ID || LOT_CODE || FAB_CODE || VENDOR_ID */
|
||||
hw_info[0] = (uint32_t)((lot_code_1 << 30) | (wafer_id << 24) | (x_coord << 15) | (y_coord << 6) | (ops_reserved));
|
||||
hw_info[1] = (uint32_t)((lot_code_0 << 26) | (lot_code_1 >> 2));
|
||||
hw_info[2] = (uint32_t)((fab_code << 26) | (lot_code_0 >> 6));
|
||||
hw_info[3] = (uint32_t)(vendor_code);
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* 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 FUSEE_FUSE_H
|
||||
#define FUSEE_FUSE_H
|
||||
|
||||
@@ -23,154 +23,167 @@
|
||||
#define MAKE_FUSE_CHIP_REG(n) MAKE_REG32(FUSE_CHIP_BASE + n)
|
||||
|
||||
typedef struct {
|
||||
uint32_t FUSE_CTRL;
|
||||
uint32_t FUSE_REG_ADDR;
|
||||
uint32_t FUSE_REG_READ;
|
||||
uint32_t FUSE_REG_WRITE;
|
||||
uint32_t FUSE_TIME_RD1;
|
||||
uint32_t FUSE_TIME_RD2;
|
||||
uint32_t FUSE_TIME_PGM1;
|
||||
uint32_t FUSE_TIME_PGM2;
|
||||
uint32_t FUSE_PRIV2INTFC;
|
||||
uint32_t FUSE_FUSECTRL;
|
||||
uint32_t FUSE_FUSEADDR;
|
||||
uint32_t FUSE_FUSERDATA;
|
||||
uint32_t FUSE_FUSEWDATA;
|
||||
uint32_t FUSE_FUSETIME_RD1;
|
||||
uint32_t FUSE_FUSETIME_RD2;
|
||||
uint32_t FUSE_FUSETIME_PGM1;
|
||||
uint32_t FUSE_FUSETIME_PGM2;
|
||||
uint32_t FUSE_PRIV2INTFC_START;
|
||||
uint32_t FUSE_FUSEBYPASS;
|
||||
uint32_t FUSE_PRIVATEKEYDISABLE;
|
||||
uint32_t FUSE_DIS_PGM;
|
||||
uint32_t FUSE_WRITE_ACCESS;
|
||||
uint32_t FUSE_DISABLEREGPROGRAM;
|
||||
uint32_t FUSE_WRITE_ACCESS_SW;
|
||||
uint32_t FUSE_PWR_GOOD_SW;
|
||||
uint32_t _0x38[0x32];
|
||||
uint32_t _0x38;
|
||||
uint32_t FUSE_PRIV2RESHIFT;
|
||||
uint32_t _0x40[0x3];
|
||||
uint32_t FUSE_FUSETIME_RD3;
|
||||
uint32_t _0x50[0xC];
|
||||
uint32_t FUSE_PRIVATE_KEY0_NONZERO;
|
||||
uint32_t FUSE_PRIVATE_KEY1_NONZERO;
|
||||
uint32_t FUSE_PRIVATE_KEY2_NONZERO;
|
||||
uint32_t FUSE_PRIVATE_KEY3_NONZERO;
|
||||
uint32_t FUSE_PRIVATE_KEY4_NONZERO;
|
||||
uint32_t _0x90[0x1C];
|
||||
} tegra_fuse_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t FUSE_PRODUCTION_MODE;
|
||||
uint32_t _0x4;
|
||||
uint32_t _0x8;
|
||||
uint32_t _0xC;
|
||||
uint32_t FUSE_JTAG_SECUREID_VALID;
|
||||
uint32_t FUSE_ODM_LOCK;
|
||||
uint32_t FUSE_OPT_OPENGL_EN;
|
||||
uint32_t FUSE_SKU_INFO;
|
||||
uint32_t FUSE_CPU_SPEEDO_0;
|
||||
uint32_t FUSE_CPU_IDDQ;
|
||||
uint32_t _0x1C;
|
||||
uint32_t _0x20;
|
||||
uint32_t _0x24;
|
||||
uint32_t FUSE_FT_REV;
|
||||
uint32_t FUSE_CPU_SPEEDO_1;
|
||||
uint32_t FUSE_CPU_SPEEDO_2;
|
||||
uint32_t FUSE_SOC_SPEEDO_0;
|
||||
uint32_t FUSE_SOC_SPEEDO_1;
|
||||
uint32_t FUSE_SOC_SPEEDO_2;
|
||||
uint32_t FUSE_SOC_IDDQ;
|
||||
uint32_t _0x44;
|
||||
uint32_t FUSE_CPU_SPEEDO_0_CALIB;
|
||||
uint32_t FUSE_CPU_IDDQ_CALIB;
|
||||
uint32_t FUSE_DAC_CRT_CALIB;
|
||||
uint32_t FUSE_DAC_HDTV_CALIB;
|
||||
uint32_t FUSE_DAC_SDTV_CALIB;
|
||||
uint32_t FUSE_OPT_FT_REV;
|
||||
uint32_t FUSE_CPU_SPEEDO_1_CALIB;
|
||||
uint32_t FUSE_CPU_SPEEDO_2_CALIB;
|
||||
uint32_t FUSE_SOC_SPEEDO_0_CALIB;
|
||||
uint32_t FUSE_SOC_SPEEDO_1_CALIB;
|
||||
uint32_t FUSE_SOC_SPEEDO_2_CALIB;
|
||||
uint32_t FUSE_SOC_IDDQ_CALIB;
|
||||
uint32_t FUSE_RESERVED_PRODUCTION_WP;
|
||||
uint32_t FUSE_FA;
|
||||
uint32_t _0x4C;
|
||||
uint32_t _0x50;
|
||||
uint32_t _0x54;
|
||||
uint32_t _0x58;
|
||||
uint32_t _0x5C;
|
||||
uint32_t _0x60;
|
||||
uint32_t FUSE_RESERVED_PRODUCTION;
|
||||
uint32_t FUSE_HDMI_LANE0_CALIB;
|
||||
uint32_t FUSE_HDMI_LANE1_CALIB;
|
||||
uint32_t FUSE_HDMI_LANE2_CALIB;
|
||||
uint32_t FUSE_HDMI_LANE3_CALIB;
|
||||
uint32_t FUSE_ENCRYPTION_RATE;
|
||||
uint32_t FUSE_PUBLIC_KEY[0x8];
|
||||
uint32_t FUSE_TSENSOR_1;
|
||||
uint32_t FUSE_TSENSOR_2;
|
||||
uint32_t _0x8C;
|
||||
uint32_t FUSE_CP_REV;
|
||||
uint32_t _0x94;
|
||||
uint32_t FUSE_TSENSOR_0;
|
||||
uint32_t FUSE_FIRST_BOOTROM_PATCH_SIZE_REG;
|
||||
uint32_t FUSE_TSENSOR1_CALIB;
|
||||
uint32_t FUSE_TSENSOR2_CALIB;
|
||||
uint32_t FUSE_VSENSOR_CALIB;
|
||||
uint32_t FUSE_OPT_CP_REV;
|
||||
uint32_t FUSE_OPT_PFG;
|
||||
uint32_t FUSE_TSENSOR0_CALIB;
|
||||
uint32_t FUSE_FIRST_BOOTROM_PATCH_SIZE;
|
||||
uint32_t FUSE_SECURITY_MODE;
|
||||
uint32_t FUSE_PRIVATE_KEY[0x4];
|
||||
uint32_t FUSE_DEVICE_KEY;
|
||||
uint32_t _0xB8;
|
||||
uint32_t _0xBC;
|
||||
uint32_t FUSE_PRIVATE_KEY[0x5];
|
||||
uint32_t FUSE_ARM_JTAG_DIS;
|
||||
uint32_t FUSE_BOOT_DEVICE_INFO;
|
||||
uint32_t FUSE_RESERVED_SW;
|
||||
uint32_t FUSE_VP8_ENABLE;
|
||||
uint32_t FUSE_OPT_VP9_DISABLE;
|
||||
uint32_t FUSE_RESERVED_ODM[0x8];
|
||||
uint32_t _0xE8;
|
||||
uint32_t _0xEC;
|
||||
uint32_t FUSE_SKU_USB_CALIB;
|
||||
uint32_t FUSE_OBS_DIS;
|
||||
uint32_t FUSE_NOR_INFO;
|
||||
uint32_t FUSE_USB_CALIB;
|
||||
uint32_t FUSE_SKU_DIRECT_CONFIG;
|
||||
uint32_t _0xF8;
|
||||
uint32_t _0xFC;
|
||||
uint32_t FUSE_VENDOR_CODE;
|
||||
uint32_t FUSE_FAB_CODE;
|
||||
uint32_t FUSE_LOT_CODE_0;
|
||||
uint32_t FUSE_LOT_CODE_1;
|
||||
uint32_t FUSE_WAFER_ID;
|
||||
uint32_t FUSE_X_COORDINATE;
|
||||
uint32_t FUSE_Y_COORDINATE;
|
||||
uint32_t _0x11C;
|
||||
uint32_t _0x120;
|
||||
uint32_t FUSE_KFUSE_PRIVKEY_CTRL;
|
||||
uint32_t FUSE_PACKAGE_INFO;
|
||||
uint32_t FUSE_OPT_VENDOR_CODE;
|
||||
uint32_t FUSE_OPT_FAB_CODE;
|
||||
uint32_t FUSE_OPT_LOT_CODE_0;
|
||||
uint32_t FUSE_OPT_LOT_CODE_1;
|
||||
uint32_t FUSE_OPT_WAFER_ID;
|
||||
uint32_t FUSE_OPT_X_COORDINATE;
|
||||
uint32_t FUSE_OPT_Y_COORDINATE;
|
||||
uint32_t FUSE_OPT_SEC_DEBUG_EN;
|
||||
uint32_t FUSE_OPT_OPS_RESERVED;
|
||||
uint32_t FUSE_SATA_CALIB;
|
||||
uint32_t FUSE_GPU_IDDQ;
|
||||
uint32_t FUSE_TSENSOR_3;
|
||||
uint32_t _0x130;
|
||||
uint32_t _0x134;
|
||||
uint32_t _0x138;
|
||||
uint32_t _0x13C;
|
||||
uint32_t _0x140;
|
||||
uint32_t _0x144;
|
||||
uint32_t FUSE_GPU_IDDQ_CALIB;
|
||||
uint32_t FUSE_TSENSOR3_CALIB;
|
||||
uint32_t FUSE_SKU_BOND_OUT_L;
|
||||
uint32_t FUSE_SKU_BOND_OUT_H;
|
||||
uint32_t FUSE_SKU_BOND_OUT_U;
|
||||
uint32_t FUSE_SKU_BOND_OUT_V;
|
||||
uint32_t FUSE_SKU_BOND_OUT_W;
|
||||
uint32_t FUSE_OPT_SAMPLE_TYPE;
|
||||
uint32_t FUSE_OPT_SUBREVISION;
|
||||
uint32_t _0x14C;
|
||||
uint32_t _0x150;
|
||||
uint32_t FUSE_TSENSOR_4;
|
||||
uint32_t FUSE_TSENSOR_5;
|
||||
uint32_t FUSE_TSENSOR_6;
|
||||
uint32_t FUSE_TSENSOR_7;
|
||||
uint32_t FUSE_OPT_PRIV_SEC_DIS;
|
||||
uint32_t FUSE_OPT_SW_RESERVED_0;
|
||||
uint32_t FUSE_OPT_SW_RESERVED_1;
|
||||
uint32_t FUSE_TSENSOR4_CALIB;
|
||||
uint32_t FUSE_TSENSOR5_CALIB;
|
||||
uint32_t FUSE_TSENSOR6_CALIB;
|
||||
uint32_t FUSE_TSENSOR7_CALIB;
|
||||
uint32_t FUSE_OPT_PRIV_SEC_EN;
|
||||
uint32_t FUSE_PKC_DISABLE;
|
||||
uint32_t _0x16C;
|
||||
uint32_t _0x170;
|
||||
uint32_t _0x174;
|
||||
uint32_t _0x178;
|
||||
uint32_t _0x17C;
|
||||
uint32_t FUSE_FUSE2TSEC_DEBUG_DISABLE;
|
||||
uint32_t FUSE_TSENSOR_COMMON;
|
||||
uint32_t _0x184;
|
||||
uint32_t _0x188;
|
||||
uint32_t _0x18C;
|
||||
uint32_t _0x190;
|
||||
uint32_t FUSE_OPT_CP_BIN;
|
||||
uint32_t FUSE_OPT_GPU_DISABLE;
|
||||
uint32_t FUSE_OPT_FT_BIN;
|
||||
uint32_t FUSE_OPT_DONE_MAP;
|
||||
uint32_t _0x194;
|
||||
uint32_t _0x198;
|
||||
uint32_t FUSE_DEBUG_AUTH_OVERRIDE;
|
||||
uint32_t FUSE_APB2JTAG_DISABLE;
|
||||
uint32_t FUSE_ODM_INFO;
|
||||
uint32_t _0x1A0;
|
||||
uint32_t _0x1A4;
|
||||
uint32_t _0x1A8;
|
||||
uint32_t FUSE_ARM_CRYPT_DE_FEATURE;
|
||||
uint32_t _0x1AC;
|
||||
uint32_t _0x1B0;
|
||||
uint32_t _0x1B4;
|
||||
uint32_t _0x1B8;
|
||||
uint32_t _0x1BC;
|
||||
uint32_t _0x1D0;
|
||||
uint32_t FUSE_TSENSOR_8;
|
||||
uint32_t FUSE_WOA_SKU_FLAG;
|
||||
uint32_t FUSE_ECO_RESERVE_1;
|
||||
uint32_t FUSE_GCPLEX_CONFIG_FUSE;
|
||||
uint32_t FUSE_PRODUCTION_MONTH;
|
||||
uint32_t FUSE_RAM_REPAIR_INDICATOR;
|
||||
uint32_t FUSE_TSENSOR9_CALIB;
|
||||
uint32_t _0x1D8;
|
||||
uint32_t _0x1DC;
|
||||
uint32_t _0x1E0;
|
||||
uint32_t _0x1E4;
|
||||
uint32_t _0x1E8;
|
||||
uint32_t _0x1EC;
|
||||
uint32_t _0x1F0;
|
||||
uint32_t _0x1F4;
|
||||
uint32_t _0x1F8;
|
||||
uint32_t FUSE_VMIN_CALIBRATION;
|
||||
uint32_t FUSE_AGING_SENSOR_CALIBRATION;
|
||||
uint32_t FUSE_DEBUG_AUTHENTICATION;
|
||||
uint32_t FUSE_SECURE_PROVISION_INDEX;
|
||||
uint32_t FUSE_SECURE_PROVISION_INFO;
|
||||
uint32_t FUSE_OPT_GPU_DISABLE_CP1;
|
||||
uint32_t FUSE_SPARE_ENDIS;
|
||||
uint32_t FUSE_ECO_RESERVE_0;
|
||||
uint32_t _0x1FC;
|
||||
uint32_t _0x200;
|
||||
uint32_t FUSE_RESERVED_CALIB;
|
||||
uint32_t _0x208;
|
||||
uint32_t _0x20C;
|
||||
uint32_t _0x210;
|
||||
uint32_t _0x214;
|
||||
uint32_t _0x218;
|
||||
uint32_t FUSE_TSENSOR_9;
|
||||
uint32_t _0x220;
|
||||
uint32_t _0x224;
|
||||
uint32_t _0x228;
|
||||
uint32_t _0x22C;
|
||||
uint32_t _0x230;
|
||||
uint32_t _0x234;
|
||||
uint32_t _0x238;
|
||||
uint32_t _0x23C;
|
||||
uint32_t _0x240;
|
||||
uint32_t _0x244;
|
||||
uint32_t _0x248;
|
||||
uint32_t _0x24C;
|
||||
uint32_t FUSE_RESERVED_CALIB0;
|
||||
uint32_t FUSE_RESERVED_CALIB1;
|
||||
uint32_t FUSE_OPT_GPU_TPC0_DISABLE;
|
||||
uint32_t FUSE_OPT_GPU_TPC0_DISABLE_CP1;
|
||||
uint32_t FUSE_OPT_CPU_DISABLE;
|
||||
uint32_t FUSE_OPT_CPU_DISABLE_CP1;
|
||||
uint32_t FUSE_TSENSOR10_CALIB;
|
||||
uint32_t FUSE_TSENSOR10_CALIB_AUX;
|
||||
uint32_t FUSE_OPT_RAM_SVOP_DP;
|
||||
uint32_t FUSE_OPT_RAM_SVOP_PDP;
|
||||
uint32_t FUSE_OPT_RAM_SVOP_REG;
|
||||
uint32_t FUSE_OPT_RAM_SVOP_SP;
|
||||
uint32_t FUSE_OPT_RAM_SVOP_SMPDP;
|
||||
uint32_t FUSE_OPT_GPU_TPC0_DISABLE_CP2;
|
||||
uint32_t FUSE_OPT_GPU_TPC1_DISABLE;
|
||||
uint32_t FUSE_OPT_GPU_TPC1_DISABLE_CP1;
|
||||
uint32_t FUSE_OPT_GPU_TPC1_DISABLE_CP2;
|
||||
uint32_t FUSE_OPT_CPU_DISABLE_CP2;
|
||||
uint32_t FUSE_OPT_GPU_DISABLE_CP2;
|
||||
uint32_t FUSE_USB_CALIB_EXT;
|
||||
uint32_t _0x254;
|
||||
uint32_t _0x258;
|
||||
uint32_t FUSE_RESERVED_FIELD;
|
||||
uint32_t FUSE_OPT_ECC_EN;
|
||||
uint32_t _0x25C;
|
||||
uint32_t _0x260;
|
||||
uint32_t _0x264;
|
||||
@@ -179,35 +192,36 @@ typedef struct {
|
||||
uint32_t _0x270;
|
||||
uint32_t _0x274;
|
||||
uint32_t _0x278;
|
||||
uint32_t _0x27C;
|
||||
uint32_t FUSE_SPARE_REALIGNMENT_REG;
|
||||
uint32_t FUSE_SPARE_BIT[0x20];
|
||||
} tegra_fuse_chip_t;
|
||||
|
||||
static inline volatile tegra_fuse_t *fuse_get_regs(void) {
|
||||
static inline volatile tegra_fuse_t *fuse_get_regs(void)
|
||||
{
|
||||
return (volatile tegra_fuse_t *)FUSE_BASE;
|
||||
}
|
||||
|
||||
static inline volatile tegra_fuse_chip_t *fuse_chip_get_regs(void) {
|
||||
static inline volatile tegra_fuse_chip_t *fuse_chip_get_regs(void)
|
||||
{
|
||||
return (volatile tegra_fuse_chip_t *)FUSE_CHIP_BASE;
|
||||
}
|
||||
|
||||
void fuse_init(void);
|
||||
|
||||
uint32_t fuse_hw_read(uint32_t addr);
|
||||
void fuse_hw_write(uint32_t value, uint32_t addr);
|
||||
void fuse_hw_sense(void);
|
||||
void fuse_disable_programming(void);
|
||||
void fuse_secondary_private_key_disable(void);
|
||||
void fuse_disable_private_key(void);
|
||||
|
||||
uint32_t fuse_get_sku_info(void);
|
||||
uint32_t fuse_get_spare_bit(uint32_t idx);
|
||||
uint32_t fuse_get_reserved_odm(uint32_t idx);
|
||||
|
||||
uint32_t fuse_get_bootrom_patch_version(void);
|
||||
uint64_t fuse_get_device_id(void);
|
||||
uint32_t fuse_get_dram_id(void);
|
||||
uint32_t fuse_get_hardware_type(void);
|
||||
uint32_t fuse_get_hardware_type(uint32_t target_firmware);
|
||||
uint32_t fuse_get_retail_type(void);
|
||||
void fuse_get_hardware_info(void *dst);
|
||||
|
||||
uint32_t fuse_hw_read(uint32_t addr);
|
||||
void fuse_hw_write(uint32_t value, uint32_t addr);
|
||||
void fuse_hw_sense(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -21,6 +21,12 @@
|
||||
#include "kernel_patches.h"
|
||||
#include "ips.h"
|
||||
|
||||
#define u8 uint8_t
|
||||
#define u32 uint32_t
|
||||
#include "kernel_ldr_bin.h"
|
||||
#undef u8
|
||||
#undef u32
|
||||
|
||||
#define MAKE_BRANCH(a, o) 0x14000000 | ((((o) - (a)) >> 2) & 0x3FFFFFF)
|
||||
#define MAKE_NOP 0xD503201F
|
||||
|
||||
@@ -839,12 +845,12 @@ const kernel_info_t *get_kernel_info(void *kernel, size_t size) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void package2_patch_kernel(void *_kernel, size_t size, bool is_sd_kernel, void **out_ini1) {
|
||||
const kernel_info_t *kernel_info = get_kernel_info(_kernel, size);
|
||||
void package2_patch_kernel(void *_kernel, size_t *kernel_size, bool is_sd_kernel, void **out_ini1) {
|
||||
const kernel_info_t *kernel_info = get_kernel_info(_kernel, *kernel_size);
|
||||
*out_ini1 = NULL;
|
||||
|
||||
/* Apply IPS patches. */
|
||||
apply_kernel_ips_patches(_kernel, size);
|
||||
apply_kernel_ips_patches(_kernel, *kernel_size);
|
||||
|
||||
if (kernel_info == NULL && !is_sd_kernel) {
|
||||
/* Should this be fatal? */
|
||||
@@ -856,8 +862,16 @@ void package2_patch_kernel(void *_kernel, size_t size, bool is_sd_kernel, void *
|
||||
}
|
||||
|
||||
if (kernel_info->embedded_ini_offset != 0) {
|
||||
/* Copy in our kernel loader. */
|
||||
const uint32_t kernel_ldr_offset = *((volatile uint64_t *)((uintptr_t)_kernel + kernel_info->embedded_ini_ptr + 8));
|
||||
memcpy((void *)((uintptr_t)_kernel + kernel_ldr_offset), kernel_ldr_bin, kernel_ldr_bin_size);
|
||||
|
||||
/* Update size. */
|
||||
*kernel_size = kernel_ldr_offset + kernel_ldr_bin_size;
|
||||
|
||||
/* Set output INI ptr. */
|
||||
*out_ini1 = (void *)((uintptr_t)_kernel + kernel_info->embedded_ini_offset);
|
||||
*((volatile uint64_t *)((uintptr_t)_kernel + kernel_info->embedded_ini_ptr)) = (uint64_t)size;
|
||||
*((volatile uint64_t *)((uintptr_t)_kernel + kernel_info->embedded_ini_ptr)) = (uint64_t)*kernel_size;
|
||||
}
|
||||
|
||||
/* Apply hooks and patches. */
|
||||
@@ -882,7 +896,7 @@ void package2_patch_kernel(void *_kernel, size_t size, bool is_sd_kernel, void *
|
||||
fatal_error("kernel_patcher: insufficient space to apply patches!\n");
|
||||
}
|
||||
|
||||
uint8_t *pattern_loc = search_pattern(kernel, size, kernel_info->patches[i].pattern, kernel_info->patches[i].pattern_size);
|
||||
uint8_t *pattern_loc = search_pattern(kernel, *kernel_size, kernel_info->patches[i].pattern, kernel_info->patches[i].pattern_size);
|
||||
if (pattern_loc == NULL) {
|
||||
/* TODO: Should we print an error/abort here? */
|
||||
continue;
|
||||
|
||||
@@ -13,12 +13,12 @@
|
||||
* 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 FUSEE_KERNEL_PATCHES_H
|
||||
#define FUSEE_KERNEL_PATCHES_H
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
void package2_patch_kernel(void *kernel, size_t kernel_size, bool is_sd_kernel, void **out_ini1);
|
||||
void package2_patch_kernel(void *kernel, size_t *kernel_size, bool is_sd_kernel, void **out_ini1);
|
||||
|
||||
#endif
|
||||
@@ -56,10 +56,10 @@ void nxboot_finish(uint32_t boot_memaddr) {
|
||||
set_rsa_keyslot_flags(i, 1);
|
||||
|
||||
/* Lock the Security Engine. */
|
||||
se->_0x4 = 0;
|
||||
se->AES_KEY_READ_DISABLE_REG = 0;
|
||||
se->RSA_KEY_READ_DISABLE_REG = 0;
|
||||
se->_0x0 &= 0xFFFFFFFB;
|
||||
se->SE_TZRAM_SECURITY = 0;
|
||||
se->SE_CRYPTO_SECURITY_PERKEY = 0;
|
||||
se->SE_RSA_SECURITY_PERKEY = 0;
|
||||
se->SE_SE_SECURITY &= 0xFFFFFFFB;
|
||||
|
||||
/* Boot up Exosphère. */
|
||||
MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE(target_firmware) = 0;
|
||||
|
||||
@@ -87,7 +87,7 @@ void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firm
|
||||
}
|
||||
|
||||
/* Perform any patches we want to the NX kernel. */
|
||||
package2_patch_kernel(kernel, kernel_size, is_sd_kernel, (void *)&orig_ini1);
|
||||
package2_patch_kernel(kernel, &kernel_size, is_sd_kernel, (void *)&orig_ini1);
|
||||
|
||||
/* Ensure we know where embedded INI is if present, and we don't if not. */
|
||||
if ((target_firmware < ATMOSPHERE_TARGET_FIRMWARE_800 && orig_ini1 != NULL) ||
|
||||
@@ -100,7 +100,7 @@ void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firm
|
||||
package2_get_src_section((void *)&orig_ini1, package2, PACKAGE2_SECTION_INI1);
|
||||
} else {
|
||||
/* On 8.0.0, place INI1 right after kernelldr for our sanity. */
|
||||
package2->metadata.section_offsets[PACKAGE2_SECTION_INI1] = package2->metadata.section_offsets[PACKAGE2_SECTION_KERNEL] + package2->metadata.section_sizes[PACKAGE2_SECTION_KERNEL];
|
||||
package2->metadata.section_offsets[PACKAGE2_SECTION_INI1] = package2->metadata.section_offsets[PACKAGE2_SECTION_KERNEL] + kernel_size;
|
||||
}
|
||||
|
||||
/* Perform any patches to the INI1, rebuilding it (This is where our built-in sysmodules will be added.) */
|
||||
|
||||
@@ -39,20 +39,20 @@ void NOINLINE ll_init(volatile se_ll_t *ll, void *buffer, size_t size) {
|
||||
}
|
||||
|
||||
void se_check_error_status_reg(void) {
|
||||
if (se_get_regs()->ERR_STATUS_REG) {
|
||||
if (se_get_regs()->SE_ERR_STATUS) {
|
||||
generic_panic();
|
||||
}
|
||||
}
|
||||
|
||||
void se_check_for_error(void) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
if (se->INT_STATUS_REG & 0x10000 || se->FLAGS_REG & 3 || se->ERR_STATUS_REG) {
|
||||
if (se->SE_INT_STATUS & 0x10000 || se->SE_STATUS & 3 || se->SE_ERR_STATUS) {
|
||||
generic_panic();
|
||||
}
|
||||
}
|
||||
|
||||
void se_verify_flags_cleared(void) {
|
||||
if (se_get_regs()->FLAGS_REG & 3) {
|
||||
if (se_get_regs()->SE_STATUS & 3) {
|
||||
generic_panic();
|
||||
}
|
||||
}
|
||||
@@ -67,12 +67,12 @@ void set_aes_keyslot_flags(unsigned int keyslot, unsigned int flags) {
|
||||
|
||||
/* Misc flags. */
|
||||
if (flags & ~0x80) {
|
||||
se->AES_KEYSLOT_FLAGS[keyslot] = ~flags;
|
||||
se->SE_CRYPTO_KEYTABLE_ACCESS[keyslot] = ~flags;
|
||||
}
|
||||
|
||||
/* Disable keyslot reads. */
|
||||
if (flags & 0x80) {
|
||||
se->AES_KEY_READ_DISABLE_REG &= ~(1 << keyslot);
|
||||
se->SE_CRYPTO_SECURITY_PERKEY &= ~(1 << keyslot);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,12 +87,12 @@ void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags) {
|
||||
/* Misc flags. */
|
||||
if (flags & ~0x80) {
|
||||
/* TODO: Why are flags assigned this way? */
|
||||
se->RSA_KEYSLOT_FLAGS[keyslot] = (((flags >> 4) & 4) | (flags & 3)) ^ 7;
|
||||
se->SE_RSA_KEYTABLE_ACCESS[keyslot] = (((flags >> 4) & 4) | (flags & 3)) ^ 7;
|
||||
}
|
||||
|
||||
/* Disable keyslot reads. */
|
||||
if (flags & 0x80) {
|
||||
se->RSA_KEY_READ_DISABLE_REG &= ~(1 << keyslot);
|
||||
se->SE_RSA_SECURITY_PERKEY &= ~(1 << keyslot);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,8 +105,8 @@ void clear_aes_keyslot(unsigned int keyslot) {
|
||||
|
||||
/* Zero out the whole keyslot and IV. */
|
||||
for (unsigned int i = 0; i < 0x10; i++) {
|
||||
se->AES_KEYTABLE_ADDR = (keyslot << 4) | i;
|
||||
se->AES_KEYTABLE_DATA = 0;
|
||||
se->SE_CRYPTO_KEYTABLE_ADDR = (keyslot << 4) | i;
|
||||
se->SE_CRYPTO_KEYTABLE_DATA = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,13 +120,13 @@ void clear_rsa_keyslot(unsigned int keyslot) {
|
||||
/* Zero out the whole keyslot. */
|
||||
for (unsigned int i = 0; i < 0x40; i++) {
|
||||
/* Select Keyslot Modulus[i] */
|
||||
se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i | 0x40;
|
||||
se->RSA_KEYTABLE_DATA = 0;
|
||||
se->SE_RSA_KEYTABLE_ADDR = (keyslot << 7) | i | 0x40;
|
||||
se->SE_RSA_KEYTABLE_DATA = 0;
|
||||
}
|
||||
for (unsigned int i = 0; i < 0x40; i++) {
|
||||
/* Select Keyslot Expontent[i] */
|
||||
se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i;
|
||||
se->RSA_KEYTABLE_DATA = 0;
|
||||
se->SE_RSA_KEYTABLE_ADDR = (keyslot << 7) | i;
|
||||
se->SE_RSA_KEYTABLE_DATA = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,8 +138,8 @@ void set_aes_keyslot(unsigned int keyslot, const void *key, size_t key_size) {
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < (key_size >> 2); i++) {
|
||||
se->AES_KEYTABLE_ADDR = (keyslot << 4) | i;
|
||||
se->AES_KEYTABLE_DATA = read32le(key, 4 * i);
|
||||
se->SE_CRYPTO_KEYTABLE_ADDR = (keyslot << 4) | i;
|
||||
se->SE_CRYPTO_KEYTABLE_DATA = read32le(key, 4 * i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,13 +151,13 @@ void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < (modulus_size >> 2); i++) {
|
||||
se->RSA_KEYTABLE_ADDR = (keyslot << 7) | 0x40 | i;
|
||||
se->RSA_KEYTABLE_DATA = read32be(modulus, (4 * (modulus_size >> 2)) - (4 * i) - 4);
|
||||
se->SE_RSA_KEYTABLE_ADDR = (keyslot << 7) | 0x40 | i;
|
||||
se->SE_RSA_KEYTABLE_DATA = read32be(modulus, (4 * (modulus_size >> 2)) - (4 * i) - 4);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < (exp_size >> 2); i++) {
|
||||
se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i;
|
||||
se->RSA_KEYTABLE_DATA = read32be(exponent, (4 * (exp_size >> 2)) - (4 * i) - 4);
|
||||
se->SE_RSA_KEYTABLE_ADDR = (keyslot << 7) | i;
|
||||
se->SE_RSA_KEYTABLE_DATA = read32be(exponent, (4 * (exp_size >> 2)) - (4 * i) - 4);
|
||||
}
|
||||
|
||||
g_se_modulus_sizes[keyslot] = modulus_size;
|
||||
@@ -172,8 +172,8 @@ void set_aes_keyslot_iv(unsigned int keyslot, const void *iv, size_t iv_size) {
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < (iv_size >> 2); i++) {
|
||||
se->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i;
|
||||
se->AES_KEYTABLE_DATA = read32le(iv, 4 * i);
|
||||
se->SE_CRYPTO_KEYTABLE_ADDR = (keyslot << 4) | 8 | i;
|
||||
se->SE_CRYPTO_KEYTABLE_DATA = read32le(iv, 4 * i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,14 +185,14 @@ void clear_aes_keyslot_iv(unsigned int keyslot) {
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < (0x10 >> 2); i++) {
|
||||
se->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i;
|
||||
se->AES_KEYTABLE_DATA = 0;
|
||||
se->SE_CRYPTO_KEYTABLE_ADDR = (keyslot << 4) | 8 | i;
|
||||
se->SE_CRYPTO_KEYTABLE_DATA = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void set_se_ctr(const void *ctr) {
|
||||
for (unsigned int i = 0; i < 4; i++) {
|
||||
se_get_regs()->CRYPTO_CTR_REG[i] = read32le(ctr, i * 4);
|
||||
se_get_regs()->SE_CRYPTO_LINEAR_CTR[i] = read32le(ctr, i * 4);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,10 +203,10 @@ void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_sr
|
||||
generic_panic();
|
||||
}
|
||||
|
||||
se->CONFIG_REG = (ALG_AES_DEC | DST_KEYTAB);
|
||||
se->CRYPTO_REG = keyslot_src << 24;
|
||||
se->BLOCK_COUNT_REG = 0;
|
||||
se->CRYPTO_KEYTABLE_DST_REG = keyslot_dst << 8;
|
||||
se->SE_CONFIG = (ALG_AES_DEC | DST_KEYTAB);
|
||||
se->SE_CRYPTO_CONFIG = keyslot_src << 24;
|
||||
se->SE_CRYPTO_LAST_BLOCK = 0;
|
||||
se->SE_CRYPTO_KEYTABLE_DST = keyslot_dst << 8;
|
||||
|
||||
trigger_se_blocking_op(OP_START, NULL, 0, wrapped_key, wrapped_key_size);
|
||||
}
|
||||
@@ -224,10 +224,10 @@ void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, co
|
||||
stack_buf[i] = *((uint8_t *)src + src_size - i - 1);
|
||||
}
|
||||
|
||||
se->CONFIG_REG = (ALG_RSA | DST_RSAREG);
|
||||
se->RSA_CONFIG = keyslot << 24;
|
||||
se->RSA_KEY_SIZE_REG = (g_se_modulus_sizes[keyslot] >> 6) - 1;
|
||||
se->RSA_EXP_SIZE_REG = g_se_exp_sizes[keyslot] >> 2;
|
||||
se->SE_CONFIG = (ALG_RSA | DST_RSAREG);
|
||||
se->SE_RSA_CONFIG = keyslot << 24;
|
||||
se->SE_RSA_KEY_SIZE = (g_se_modulus_sizes[keyslot] >> 6) - 1;
|
||||
se->SE_RSA_EXP_SIZE = g_se_exp_sizes[keyslot] >> 2;
|
||||
|
||||
trigger_se_blocking_op(OP_START, NULL, 0, stack_buf, src_size);
|
||||
se_get_exp_mod_output(dst, dst_size);
|
||||
@@ -245,7 +245,7 @@ void se_get_exp_mod_output(void *buf, size_t size) {
|
||||
|
||||
/* Copy endian swapped output. */
|
||||
while (num_dwords) {
|
||||
*p_out = read32be(se_get_regs()->RSA_OUTPUT, offset);
|
||||
*p_out = read32be(se_get_regs()->SE_RSA_OUTPUT, offset);
|
||||
offset += 4;
|
||||
p_out--;
|
||||
num_dwords--;
|
||||
@@ -314,15 +314,15 @@ void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const v
|
||||
ll_init(&out_ll, dst, dst_size);
|
||||
|
||||
/* Set the LLs. */
|
||||
se->IN_LL_ADDR_REG = (uint32_t) get_physical_address(&in_ll);
|
||||
se->OUT_LL_ADDR_REG = (uint32_t) get_physical_address(&out_ll);
|
||||
se->SE_IN_LL_ADDR = (uint32_t) get_physical_address(&in_ll);
|
||||
se->SE_OUT_LL_ADDR = (uint32_t) get_physical_address(&out_ll);
|
||||
|
||||
/* Set registers for operation. */
|
||||
se->ERR_STATUS_REG = se->ERR_STATUS_REG;
|
||||
se->INT_STATUS_REG = se->INT_STATUS_REG;
|
||||
se->OPERATION_REG = op;
|
||||
se->SE_ERR_STATUS = se->SE_ERR_STATUS;
|
||||
se->SE_INT_STATUS = se->SE_INT_STATUS;
|
||||
se->SE_OPERATION = op;
|
||||
|
||||
while (!(se->INT_STATUS_REG & 0x10)) { /* Wait a while */ }
|
||||
while (!(se->SE_INT_STATUS & 0x10)) { /* Wait a while */ }
|
||||
se_check_for_error();
|
||||
}
|
||||
|
||||
@@ -340,7 +340,7 @@ void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src,
|
||||
}
|
||||
|
||||
/* Trigger AES operation. */
|
||||
se_get_regs()->BLOCK_COUNT_REG = 0;
|
||||
se_get_regs()->SE_CRYPTO_LAST_BLOCK = 0;
|
||||
trigger_se_blocking_op(OP_START, block, sizeof(block), block, sizeof(block));
|
||||
|
||||
/* Copy output data into dst. */
|
||||
@@ -358,15 +358,15 @@ void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const vo
|
||||
unsigned int num_blocks = src_size >> 4;
|
||||
|
||||
/* Unknown what this write does, but official code writes it for CTR mode. */
|
||||
se->SPARE_0 = 1;
|
||||
se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY);
|
||||
se->CRYPTO_REG = (keyslot << 24) | 0x91E;
|
||||
se->SE_SPARE = 1;
|
||||
se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY);
|
||||
se->SE_CRYPTO_CONFIG = (keyslot << 24) | 0x91E;
|
||||
set_se_ctr(ctr);
|
||||
|
||||
/* Handle any aligned blocks. */
|
||||
size_t aligned_size = (size_t)num_blocks << 4;
|
||||
if (aligned_size) {
|
||||
se->BLOCK_COUNT_REG = num_blocks - 1;
|
||||
se->SE_CRYPTO_LAST_BLOCK = num_blocks - 1;
|
||||
trigger_se_blocking_op(OP_START, dst, dst_size, src, aligned_size);
|
||||
}
|
||||
|
||||
@@ -388,8 +388,8 @@ void se_aes_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size,
|
||||
}
|
||||
|
||||
/* Set configuration high (256-bit vs 128-bit) based on parameter. */
|
||||
se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY) | (config_high << 16);
|
||||
se->CRYPTO_REG = keyslot << 24 | 0x100;
|
||||
se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY) | (config_high << 16);
|
||||
se->SE_CRYPTO_CONFIG = keyslot << 24 | 0x100;
|
||||
se_perform_aes_block_operation(dst, 0x10, src, 0x10);
|
||||
}
|
||||
|
||||
@@ -408,8 +408,8 @@ void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size,
|
||||
generic_panic();
|
||||
}
|
||||
|
||||
se->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY);
|
||||
se->CRYPTO_REG = keyslot << 24;
|
||||
se->SE_CONFIG = (ALG_AES_DEC | DST_MEMORY);
|
||||
se->SE_CRYPTO_CONFIG = keyslot << 24;
|
||||
se_perform_aes_block_operation(dst, 0x10, src, 0x10);
|
||||
}
|
||||
|
||||
@@ -472,13 +472,13 @@ void aes_128_xts_nintendo_crypt_sector(unsigned int keyslot_1, unsigned int keys
|
||||
|
||||
/* Encrypt/Decrypt. */
|
||||
if (encrypt) {
|
||||
se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY);
|
||||
se->CRYPTO_REG = keyslot_1 << 24 | 0x100;
|
||||
se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY);
|
||||
se->SE_CRYPTO_CONFIG = keyslot_1 << 24 | 0x100;
|
||||
} else {
|
||||
se->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY);
|
||||
se->CRYPTO_REG = keyslot_1 << 24;
|
||||
se->SE_CONFIG = (ALG_AES_DEC | DST_MEMORY);
|
||||
se->SE_CRYPTO_CONFIG = keyslot_1 << 24;
|
||||
}
|
||||
se->BLOCK_COUNT_REG = (size >> 4) - 1;
|
||||
se->SE_CRYPTO_LAST_BLOCK = (size >> 4) - 1;
|
||||
trigger_se_blocking_op(OP_START, dst, size, src, size);
|
||||
|
||||
/* XOR. */
|
||||
@@ -524,16 +524,16 @@ void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, con
|
||||
shift_left_xor_rb(derived_key);
|
||||
}
|
||||
|
||||
se->CONFIG_REG = (ALG_AES_ENC | DST_HASHREG) | (config_high << 16);
|
||||
se->CRYPTO_REG = (keyslot << 24) | (0x145);
|
||||
se->SE_CONFIG = (ALG_AES_ENC | DST_HASHREG) | (config_high << 16);
|
||||
se->SE_CRYPTO_CONFIG = (keyslot << 24) | (0x145);
|
||||
clear_aes_keyslot_iv(keyslot);
|
||||
|
||||
unsigned int num_blocks = (data_size + 0xF) >> 4;
|
||||
/* Handle aligned blocks. */
|
||||
if (num_blocks > 1) {
|
||||
se->BLOCK_COUNT_REG = num_blocks - 2;
|
||||
se->SE_CRYPTO_LAST_BLOCK = num_blocks - 2;
|
||||
trigger_se_blocking_op(OP_START, NULL, 0, data, data_size);
|
||||
se->CRYPTO_REG |= 0x80;
|
||||
se->SE_CRYPTO_CONFIG |= 0x80;
|
||||
}
|
||||
|
||||
/* Create final block. */
|
||||
@@ -550,12 +550,12 @@ void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, con
|
||||
}
|
||||
|
||||
/* Perform last operation. */
|
||||
se->BLOCK_COUNT_REG = 0;
|
||||
se->SE_CRYPTO_LAST_BLOCK = 0;
|
||||
trigger_se_blocking_op(OP_START, NULL, 0, last_block, sizeof(last_block));
|
||||
|
||||
/* Copy output CMAC. */
|
||||
for (unsigned int i = 0; i < (cmac_size >> 2); i++) {
|
||||
((uint32_t *)cmac)[i] = read32le(se->HASH_RESULT_REG, i << 2);
|
||||
((uint32_t *)cmac)[i] = read32le(se->SE_HASH_RESULT, i << 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -573,10 +573,10 @@ void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, co
|
||||
generic_panic();
|
||||
}
|
||||
|
||||
se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY) | (0x202 << 16);
|
||||
se->CRYPTO_REG = (keyslot << 24) | 0x144;
|
||||
se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY) | (0x202 << 16);
|
||||
se->SE_CRYPTO_CONFIG = (keyslot << 24) | 0x144;
|
||||
set_aes_keyslot_iv(keyslot, iv, 0x10);
|
||||
se->BLOCK_COUNT_REG = (src_size >> 4) - 1;
|
||||
se->SE_CRYPTO_LAST_BLOCK = (src_size >> 4) - 1;
|
||||
trigger_se_blocking_op(OP_START, dst, dst_size, src, src_size);
|
||||
}
|
||||
|
||||
@@ -585,23 +585,23 @@ void se_calculate_sha256(void *dst, const void *src, size_t src_size) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
|
||||
/* Setup config for SHA256, size = BITS(src_size) */
|
||||
se->CONFIG_REG = (ENCMODE_SHA256 | ALG_SHA | DST_HASHREG);
|
||||
se->SHA_CONFIG_REG = 1;
|
||||
se->SHA_MSG_LENGTH_REG = (uint32_t)(src_size << 3);
|
||||
se->_0x208 = 0;
|
||||
se->_0x20C = 0;
|
||||
se->_0x210 = 0;
|
||||
se->SHA_MSG_LEFT_REG = (uint32_t)(src_size << 3);
|
||||
se->_0x218 = 0;
|
||||
se->_0x21C = 0;
|
||||
se->_0x220 = 0;
|
||||
se->SE_CONFIG = (ENCMODE_SHA256 | ALG_SHA | DST_HASHREG);
|
||||
se->SE_SHA_CONFIG = 1;
|
||||
se->SE_SHA_MSG_LENGTH[0] = (uint32_t)(src_size << 3);
|
||||
se->SE_SHA_MSG_LENGTH[1] = 0;
|
||||
se->SE_SHA_MSG_LENGTH[2] = 0;
|
||||
se->SE_SHA_MSG_LENGTH[3] = 0;
|
||||
se->SE_SHA_MSG_LEFT[0] = (uint32_t)(src_size << 3);
|
||||
se->SE_SHA_MSG_LEFT[1] = 0;
|
||||
se->SE_SHA_MSG_LEFT[2] = 0;
|
||||
se->SE_SHA_MSG_LEFT[3] = 0;
|
||||
|
||||
/* Trigger the operation. */
|
||||
trigger_se_blocking_op(OP_START, NULL, 0, src, src_size);
|
||||
|
||||
/* Copy output hash. */
|
||||
for (unsigned int i = 0; i < (0x20 >> 2); i++) {
|
||||
((uint32_t *)dst)[i] = read32be(se->HASH_RESULT_REG, i << 2);
|
||||
((uint32_t *)dst)[i] = read32be(se->SE_HASH_RESULT, i << 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -617,12 +617,12 @@ void se_initialize_rng(unsigned int keyslot) {
|
||||
/* This will be discarded, when done. */
|
||||
uint8_t ALIGN(16) output_buf[0x10];
|
||||
|
||||
se->RNG_SRC_CONFIG_REG = 3; /* Entropy enable + Entropy lock enable */
|
||||
se->RNG_RESEED_INTERVAL_REG = 70001;
|
||||
se->CONFIG_REG = (ALG_RNG | DST_MEMORY);
|
||||
se->CRYPTO_REG = (keyslot << 24) | 0x108;
|
||||
se->RNG_CONFIG_REG = 5;
|
||||
se->BLOCK_COUNT_REG = 0;
|
||||
se->SE_RNG_SRC_CONFIG = 3; /* Entropy enable + Entropy lock enable */
|
||||
se->SE_RNG_RESEED_INTERVAL = 70001;
|
||||
se->SE_CONFIG = (ALG_RNG | DST_MEMORY);
|
||||
se->SE_CRYPTO_CONFIG = (keyslot << 24) | 0x108;
|
||||
se->SE_RNG_CONFIG = 5;
|
||||
se->SE_CRYPTO_LAST_BLOCK = 0;
|
||||
trigger_se_blocking_op(OP_START, output_buf, 0x10, NULL, 0);
|
||||
}
|
||||
|
||||
@@ -635,12 +635,12 @@ void se_generate_random(unsigned int keyslot, void *dst, size_t size) {
|
||||
|
||||
uint32_t num_blocks = size >> 4;
|
||||
size_t aligned_size = num_blocks << 4;
|
||||
se->CONFIG_REG = (ALG_RNG | DST_MEMORY);
|
||||
se->CRYPTO_REG = (keyslot << 24) | 0x108;
|
||||
se->RNG_CONFIG_REG = 4;
|
||||
se->SE_CONFIG = (ALG_RNG | DST_MEMORY);
|
||||
se->SE_CRYPTO_CONFIG = (keyslot << 24) | 0x108;
|
||||
se->SE_RNG_CONFIG = 4;
|
||||
|
||||
if (num_blocks >= 1) {
|
||||
se->BLOCK_COUNT_REG = num_blocks - 1;
|
||||
se->SE_CRYPTO_LAST_BLOCK = num_blocks - 1;
|
||||
trigger_se_blocking_op(OP_START, dst, aligned_size, NULL, 0);
|
||||
}
|
||||
if (size > aligned_size) {
|
||||
|
||||
@@ -92,71 +92,59 @@
|
||||
#define RSA_2048_BYTES 0x100
|
||||
|
||||
typedef struct {
|
||||
uint32_t _0x0;
|
||||
uint32_t _0x4;
|
||||
uint32_t OPERATION_REG;
|
||||
uint32_t INT_ENABLE_REG;
|
||||
uint32_t INT_STATUS_REG;
|
||||
uint32_t CONFIG_REG;
|
||||
uint32_t IN_LL_ADDR_REG;
|
||||
uint32_t _0x1C;
|
||||
uint32_t _0x20;
|
||||
uint32_t OUT_LL_ADDR_REG;
|
||||
uint32_t _0x28;
|
||||
uint32_t _0x2C;
|
||||
uint8_t HASH_RESULT_REG[0x20];
|
||||
uint8_t _0x50[0x20];
|
||||
uint32_t CONTEXT_SAVE_CONFIG_REG;
|
||||
uint8_t _0x74[0x18C];
|
||||
uint32_t SHA_CONFIG_REG;
|
||||
uint32_t SHA_MSG_LENGTH_REG;
|
||||
uint32_t _0x208;
|
||||
uint32_t _0x20C;
|
||||
uint32_t _0x210;
|
||||
uint32_t SHA_MSG_LEFT_REG;
|
||||
uint32_t _0x218;
|
||||
uint32_t _0x21C;
|
||||
uint32_t _0x220;
|
||||
uint32_t _0x224;
|
||||
uint8_t _0x228[0x58];
|
||||
uint32_t AES_KEY_READ_DISABLE_REG;
|
||||
uint32_t AES_KEYSLOT_FLAGS[0x10];
|
||||
uint8_t _0x2C4[0x3C];
|
||||
uint32_t _0x300;
|
||||
uint32_t CRYPTO_REG;
|
||||
uint32_t CRYPTO_CTR_REG[4];
|
||||
uint32_t BLOCK_COUNT_REG;
|
||||
uint32_t AES_KEYTABLE_ADDR;
|
||||
uint32_t AES_KEYTABLE_DATA;
|
||||
uint32_t _0x324;
|
||||
uint32_t _0x328;
|
||||
uint32_t _0x32C;
|
||||
uint32_t CRYPTO_KEYTABLE_DST_REG;
|
||||
uint8_t _0x334[0xC];
|
||||
uint32_t RNG_CONFIG_REG;
|
||||
uint32_t RNG_SRC_CONFIG_REG;
|
||||
uint32_t RNG_RESEED_INTERVAL_REG;
|
||||
uint8_t _0x34C[0xB4];
|
||||
uint32_t RSA_CONFIG;
|
||||
uint32_t RSA_KEY_SIZE_REG;
|
||||
uint32_t RSA_EXP_SIZE_REG;
|
||||
uint32_t RSA_KEY_READ_DISABLE_REG;
|
||||
uint32_t RSA_KEYSLOT_FLAGS[2];
|
||||
uint32_t _0x418;
|
||||
uint32_t _0x41C;
|
||||
uint32_t RSA_KEYTABLE_ADDR;
|
||||
uint32_t RSA_KEYTABLE_DATA;
|
||||
uint8_t RSA_OUTPUT[0x100];
|
||||
uint8_t _0x528[0x2D8];
|
||||
uint32_t FLAGS_REG;
|
||||
uint32_t ERR_STATUS_REG;
|
||||
uint32_t _0x808;
|
||||
uint32_t SPARE_0;
|
||||
uint32_t _0x810;
|
||||
uint32_t SE_SE_SECURITY;
|
||||
uint32_t SE_TZRAM_SECURITY;
|
||||
uint32_t SE_OPERATION;
|
||||
uint32_t SE_INT_ENABLE;
|
||||
uint32_t SE_INT_STATUS;
|
||||
uint32_t SE_CONFIG;
|
||||
uint32_t SE_IN_LL_ADDR;
|
||||
uint32_t SE_IN_CUR_BYTE_ADDR;
|
||||
uint32_t SE_IN_CUR_LL_ID;
|
||||
uint32_t SE_OUT_LL_ADDR;
|
||||
uint32_t SE_OUT_CUR_BYTE_ADDR;
|
||||
uint32_t SE_OUT_CUR_LL_ID;
|
||||
uint32_t SE_HASH_RESULT[0x10];
|
||||
uint32_t SE_CTX_SAVE_CONFIG;
|
||||
uint32_t _0x74[0x63];
|
||||
uint32_t SE_SHA_CONFIG;
|
||||
uint32_t SE_SHA_MSG_LENGTH[0x4];
|
||||
uint32_t SE_SHA_MSG_LEFT[0x4];
|
||||
uint32_t _0x224[0x17];
|
||||
uint32_t SE_CRYPTO_SECURITY_PERKEY;
|
||||
uint32_t SE_CRYPTO_KEYTABLE_ACCESS[0x10];
|
||||
uint32_t _0x2C4[0x10];
|
||||
uint32_t SE_CRYPTO_CONFIG;
|
||||
uint32_t SE_CRYPTO_LINEAR_CTR[0x4];
|
||||
uint32_t SE_CRYPTO_LAST_BLOCK;
|
||||
uint32_t SE_CRYPTO_KEYTABLE_ADDR;
|
||||
uint32_t SE_CRYPTO_KEYTABLE_DATA;
|
||||
uint32_t _0x324[0x3];
|
||||
uint32_t SE_CRYPTO_KEYTABLE_DST;
|
||||
uint32_t _0x334[0x3];
|
||||
uint32_t SE_RNG_CONFIG;
|
||||
uint32_t SE_RNG_SRC_CONFIG;
|
||||
uint32_t SE_RNG_RESEED_INTERVAL;
|
||||
uint32_t _0x34C[0x2D];
|
||||
uint32_t SE_RSA_CONFIG;
|
||||
uint32_t SE_RSA_KEY_SIZE;
|
||||
uint32_t SE_RSA_EXP_SIZE;
|
||||
uint32_t SE_RSA_SECURITY_PERKEY;
|
||||
uint32_t SE_RSA_KEYTABLE_ACCESS[0x2];
|
||||
uint32_t _0x418[0x2];
|
||||
uint32_t SE_RSA_KEYTABLE_ADDR;
|
||||
uint32_t SE_RSA_KEYTABLE_DATA;
|
||||
uint32_t SE_RSA_OUTPUT[0x40];
|
||||
uint32_t _0x528[0xB6];
|
||||
uint32_t SE_STATUS;
|
||||
uint32_t SE_ERR_STATUS;
|
||||
uint32_t SE_MISC;
|
||||
uint32_t SE_SPARE;
|
||||
uint32_t SE_ENTROPY_DEBUG_COUNTER;
|
||||
uint32_t _0x814;
|
||||
uint32_t _0x818;
|
||||
uint32_t _0x81C;
|
||||
uint8_t _0x820[0x17E0];
|
||||
uint32_t _0x820[0x5F8];
|
||||
} tegra_se_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -237,7 +237,6 @@ void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_si
|
||||
mc_page[0x65C/4] = 0;
|
||||
mc_page[0x660/4] = 0x80000000;
|
||||
|
||||
|
||||
/* Run the TSEC firmware. */
|
||||
tsec_run_fw();
|
||||
|
||||
@@ -245,7 +244,7 @@ void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_si
|
||||
volatile uint32_t *key_data = (volatile uint32_t *)((void *)se_page + 0x320);
|
||||
uint32_t old_key_data = *key_data;
|
||||
uint32_t buf_counter = 0;
|
||||
while (!(tsec->FALCON_CPUCTL & 0x10)) {
|
||||
while (!(tsec->TSEC_FALCON_CPUCTL & 0x10)) {
|
||||
const uint32_t new_key_data = *key_data;
|
||||
if (new_key_data != old_key_data) {
|
||||
old_key_data = new_key_data;
|
||||
|
||||
@@ -94,6 +94,8 @@ _metadata:
|
||||
#define CONTENT_TYPE_KIP 6
|
||||
#define CONTENT_TYPE_BMP 7
|
||||
#define CONTENT_TYPE_EMC 8
|
||||
#define CONTENT_TYPE_KLD 9
|
||||
#define CONTENT_TYPE_KRN 10
|
||||
|
||||
_content_headers:
|
||||
/* ams_mitm content header */
|
||||
@@ -208,6 +210,14 @@ _content_headers:
|
||||
.asciz "emummc"
|
||||
.align 5
|
||||
|
||||
/* kernel_ldr content header */
|
||||
.word __kernel_ldr_bin_start__
|
||||
.word __kernel_ldr_bin_size__
|
||||
.word CONTENT_TYPE_KLD
|
||||
.word 0xCCCCCCCC
|
||||
.asciz "kernel_ldr"
|
||||
.align 5
|
||||
|
||||
/* splash_screen content header */
|
||||
.word __splash_screen_bmp_start__
|
||||
.word __splash_screen_bmp_size__
|
||||
|
||||
@@ -25,10 +25,12 @@ static int tsec_dma_wait_idle()
|
||||
volatile tegra_tsec_t *tsec = tsec_get_regs();
|
||||
uint32_t timeout = (get_time_ms() + 10000);
|
||||
|
||||
while (!(tsec->FALCON_DMATRFCMD & 2))
|
||||
while (!(tsec->TSEC_FALCON_DMATRFCMD & 2))
|
||||
{
|
||||
if (get_time_ms() > timeout)
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -42,13 +44,31 @@ static int tsec_dma_phys_to_flcn(bool is_imem, uint32_t flcn_offset, uint32_t ph
|
||||
else
|
||||
cmd = 0x10;
|
||||
|
||||
tsec->FALCON_DMATRFMOFFS = flcn_offset;
|
||||
tsec->FALCON_DMATRFFBOFFS = phys_offset;
|
||||
tsec->FALCON_DMATRFCMD = cmd;
|
||||
tsec->TSEC_FALCON_DMATRFMOFFS = flcn_offset;
|
||||
tsec->TSEC_FALCON_DMATRFFBOFFS = phys_offset;
|
||||
tsec->TSEC_FALCON_DMATRFCMD = cmd;
|
||||
|
||||
return tsec_dma_wait_idle();
|
||||
}
|
||||
|
||||
static int tsec_kfuse_wait_ready()
|
||||
{
|
||||
uint32_t timeout = (get_time_ms() + 10000);
|
||||
|
||||
/* Wait for STATE_DONE. */
|
||||
while (!(KFUSE_STATE & 0x10000))
|
||||
{
|
||||
if (get_time_ms() > timeout)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check for STATE_CRCPASS. */
|
||||
if (!(KFUSE_STATE & 0x20000))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void tsec_enable_clkrst()
|
||||
{
|
||||
/* Enable all devices used by TSEC. */
|
||||
@@ -77,23 +97,33 @@ int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw, size_t tsec_fw
|
||||
|
||||
/* Enable clocks. */
|
||||
tsec_enable_clkrst();
|
||||
|
||||
/* Configure Falcon. */
|
||||
tsec->FALCON_DMACTL = 0;
|
||||
tsec->FALCON_IRQMSET = 0xFFF2;
|
||||
tsec->FALCON_IRQDEST = 0xFFF0;
|
||||
tsec->FALCON_ITFEN = 3;
|
||||
|
||||
if (!tsec_dma_wait_idle())
|
||||
/* Make sure KFUSE is ready. */
|
||||
if (!tsec_kfuse_wait_ready())
|
||||
{
|
||||
/* Disable clocks. */
|
||||
tsec_disable_clkrst();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Configure Falcon. */
|
||||
tsec->TSEC_FALCON_DMACTL = 0;
|
||||
tsec->TSEC_FALCON_IRQMSET = 0xFFF2;
|
||||
tsec->TSEC_FALCON_IRQDEST = 0xFFF0;
|
||||
tsec->TSEC_FALCON_ITFEN = 3;
|
||||
|
||||
/* Make sure the DMA block is idle. */
|
||||
if (!tsec_dma_wait_idle())
|
||||
{
|
||||
/* Disable clocks. */
|
||||
tsec_disable_clkrst();
|
||||
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* Load firmware. */
|
||||
tsec->FALCON_DMATRFBASE = (uint32_t)tsec_fw >> 8;
|
||||
tsec->TSEC_FALCON_DMATRFBASE = (uint32_t)tsec_fw >> 8;
|
||||
for (uint32_t addr = 0; addr < tsec_fw_size; addr += 0x100)
|
||||
{
|
||||
if (!tsec_dma_phys_to_flcn(true, addr, addr))
|
||||
@@ -101,48 +131,49 @@ int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw, size_t tsec_fw
|
||||
/* Disable clocks. */
|
||||
tsec_disable_clkrst();
|
||||
|
||||
return -2;
|
||||
return -3;
|
||||
}
|
||||
}
|
||||
|
||||
/* Unknown host1x write. */
|
||||
/* Write magic value to HOST1X scratch register. */
|
||||
MAKE_HOST1X_REG(0x3300) = 0x34C2E1DA;
|
||||
|
||||
/* Execute firmware. */
|
||||
tsec->FALCON_SCRATCH1 = 0;
|
||||
tsec->FALCON_SCRATCH0 = rev;
|
||||
tsec->FALCON_BOOTVEC = 0;
|
||||
tsec->FALCON_CPUCTL = 2;
|
||||
tsec->TSEC_FALCON_MAILBOX1 = 0;
|
||||
tsec->TSEC_FALCON_MAILBOX0 = rev;
|
||||
tsec->TSEC_FALCON_BOOTVEC = 0;
|
||||
tsec->TSEC_FALCON_CPUCTL = 2;
|
||||
|
||||
/* Make sure the DMA block is idle. */
|
||||
if (!tsec_dma_wait_idle())
|
||||
{
|
||||
/* Disable clocks. */
|
||||
tsec_disable_clkrst();
|
||||
|
||||
return -3;
|
||||
return -4;
|
||||
}
|
||||
|
||||
uint32_t timeout = (get_time_ms() + 2000);
|
||||
while (!tsec->FALCON_SCRATCH1)
|
||||
while (!tsec->TSEC_FALCON_MAILBOX1)
|
||||
{
|
||||
if (get_time_ms() > timeout)
|
||||
{
|
||||
/* Disable clocks. */
|
||||
tsec_disable_clkrst();
|
||||
|
||||
return -4;
|
||||
return -5;
|
||||
}
|
||||
}
|
||||
|
||||
if (tsec->FALCON_SCRATCH1 != 0xB0B0B0B0)
|
||||
if (tsec->TSEC_FALCON_MAILBOX1 != 0xB0B0B0B0)
|
||||
{
|
||||
/* Disable clocks. */
|
||||
tsec_disable_clkrst();
|
||||
|
||||
return -5;
|
||||
return -6;
|
||||
}
|
||||
|
||||
/* Unknown host1x write. */
|
||||
/* Clear magic value from HOST1X scratch register. */
|
||||
MAKE_HOST1X_REG(0x3300) = 0;
|
||||
|
||||
/* Fetch result from SOR1. */
|
||||
@@ -170,23 +201,33 @@ int tsec_load_fw(const void *tsec_fw, size_t tsec_fw_size)
|
||||
|
||||
/* Enable clocks. */
|
||||
tsec_enable_clkrst();
|
||||
|
||||
/* Configure Falcon. */
|
||||
tsec->FALCON_DMACTL = 0;
|
||||
tsec->FALCON_IRQMSET = 0xFFF2;
|
||||
tsec->FALCON_IRQDEST = 0xFFF0;
|
||||
tsec->FALCON_ITFEN = 3;
|
||||
|
||||
if (!tsec_dma_wait_idle())
|
||||
/* Make sure KFUSE is ready. */
|
||||
if (!tsec_kfuse_wait_ready())
|
||||
{
|
||||
/* Disable clocks. */
|
||||
tsec_disable_clkrst();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Configure Falcon. */
|
||||
tsec->TSEC_FALCON_DMACTL = 0;
|
||||
tsec->TSEC_FALCON_IRQMSET = 0xFFF2;
|
||||
tsec->TSEC_FALCON_IRQDEST = 0xFFF0;
|
||||
tsec->TSEC_FALCON_ITFEN = 3;
|
||||
|
||||
/* Make sure the DMA block is idle. */
|
||||
if (!tsec_dma_wait_idle())
|
||||
{
|
||||
/* Disable clocks. */
|
||||
tsec_disable_clkrst();
|
||||
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* Load firmware. */
|
||||
tsec->FALCON_DMATRFBASE = (uint32_t)tsec_fw >> 8;
|
||||
tsec->TSEC_FALCON_DMATRFBASE = (uint32_t)tsec_fw >> 8;
|
||||
for (uint32_t addr = 0; addr < tsec_fw_size; addr += 0x100)
|
||||
{
|
||||
if (!tsec_dma_phys_to_flcn(true, addr, addr))
|
||||
@@ -194,7 +235,7 @@ int tsec_load_fw(const void *tsec_fw, size_t tsec_fw_size)
|
||||
/* Disable clocks. */
|
||||
tsec_disable_clkrst();
|
||||
|
||||
return -2;
|
||||
return -3;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,12 +246,12 @@ void tsec_run_fw()
|
||||
{
|
||||
volatile tegra_tsec_t *tsec = tsec_get_regs();
|
||||
|
||||
/* Unknown host1x write. */
|
||||
/* Write magic value to HOST1X scratch register. */
|
||||
MAKE_HOST1X_REG(0x3300) = 0x34C2E1DA;
|
||||
|
||||
/* Execute firmware. */
|
||||
tsec->FALCON_SCRATCH1 = 0;
|
||||
tsec->FALCON_SCRATCH0 = 1;
|
||||
tsec->FALCON_BOOTVEC = 0;
|
||||
tsec->FALCON_CPUCTL = 2;
|
||||
tsec->TSEC_FALCON_MAILBOX1 = 0;
|
||||
tsec->TSEC_FALCON_MAILBOX0 = 1;
|
||||
tsec->TSEC_FALCON_BOOTVEC = 0;
|
||||
tsec->TSEC_FALCON_CPUCTL = 2;
|
||||
}
|
||||
@@ -23,85 +23,280 @@
|
||||
|
||||
#define TSEC_BASE 0x54500000
|
||||
#define SOR1_BASE 0x54580000
|
||||
#define KFUSE_BASE 0x7000FC00
|
||||
|
||||
#define SOR1_DP_HDCP_BKSV_LSB MAKE_REG32(SOR1_BASE + 0x1E8)
|
||||
#define SOR1_TMDS_HDCP_BKSV_LSB MAKE_REG32(SOR1_BASE + 0x21C)
|
||||
#define SOR1_TMDS_HDCP_CN_MSB MAKE_REG32(SOR1_BASE + 0x208)
|
||||
#define SOR1_TMDS_HDCP_CN_LSB MAKE_REG32(SOR1_BASE + 0x20C)
|
||||
|
||||
#define KFUSE_FUSECTRL MAKE_REG32(KFUSE_BASE + 0x00)
|
||||
#define KFUSE_FUSEADDR MAKE_REG32(KFUSE_BASE + 0x04)
|
||||
#define KFUSE_FUSEDATA0 MAKE_REG32(KFUSE_BASE + 0x08)
|
||||
#define KFUSE_FUSEWRDATA0 MAKE_REG32(KFUSE_BASE + 0x0C)
|
||||
#define KFUSE_FUSETIME_RD1 MAKE_REG32(KFUSE_BASE + 0x10)
|
||||
#define KFUSE_FUSETIME_RD2 MAKE_REG32(KFUSE_BASE + 0x14)
|
||||
#define KFUSE_FUSETIME_PGM1 MAKE_REG32(KFUSE_BASE + 0x18)
|
||||
#define KFUSE_FUSETIME_PGM2 MAKE_REG32(KFUSE_BASE + 0x1C)
|
||||
#define KFUSE_REGULATOR MAKE_REG32(KFUSE_BASE + 0x20)
|
||||
#define KFUSE_PD MAKE_REG32(KFUSE_BASE + 0x24)
|
||||
#define KFUSE_FUSETIME_RD3 MAKE_REG32(KFUSE_BASE + 0x28)
|
||||
#define KFUSE_STATE MAKE_REG32(KFUSE_BASE + 0x80)
|
||||
#define KFUSE_ERRCOUNT MAKE_REG32(KFUSE_BASE + 0x84)
|
||||
#define KFUSE_KEYADDR MAKE_REG32(KFUSE_BASE + 0x88)
|
||||
#define KFUSE_KEYS MAKE_REG32(KFUSE_BASE + 0x8C)
|
||||
|
||||
typedef struct {
|
||||
uint8_t _0x0[0x1000]; /* Ignore non Falcon registers. */
|
||||
uint32_t FALCON_IRQSSET;
|
||||
uint32_t FALCON_IRQSCLR;
|
||||
uint32_t FALCON_IRQSTAT;
|
||||
uint32_t FALCON_IRQMODE;
|
||||
uint32_t FALCON_IRQMSET;
|
||||
uint32_t FALCON_IRQMCLR;
|
||||
uint32_t FALCON_IRQMASK;
|
||||
uint32_t FALCON_IRQDEST;
|
||||
uint8_t _0x1020[0x20];
|
||||
uint32_t FALCON_SCRATCH0;
|
||||
uint32_t FALCON_SCRATCH1;
|
||||
uint32_t FALCON_ITFEN;
|
||||
uint32_t FALCON_IDLESTATE;
|
||||
uint32_t FALCON_CURCTX;
|
||||
uint32_t FALCON_NXTCTX;
|
||||
uint8_t _0x1058[0x28];
|
||||
uint32_t FALCON_SCRATCH2;
|
||||
uint32_t FALCON_SCRATCH3;
|
||||
uint8_t _0x1088[0x18];
|
||||
uint32_t FALCON_CGCTL;
|
||||
uint32_t FALCON_ENGCTL;
|
||||
uint8_t _0x10A8[0x58];
|
||||
uint32_t FALCON_CPUCTL;
|
||||
uint32_t FALCON_BOOTVEC;
|
||||
uint32_t FALCON_HWCFG;
|
||||
uint32_t FALCON_DMACTL;
|
||||
uint32_t FALCON_DMATRFBASE;
|
||||
uint32_t FALCON_DMATRFMOFFS;
|
||||
uint32_t FALCON_DMATRFCMD;
|
||||
uint32_t FALCON_DMATRFFBOFFS;
|
||||
uint8_t _0x1120[0x10];
|
||||
uint32_t FALCON_CPUCTL_ALIAS;
|
||||
uint8_t _0x1134[0x20];
|
||||
uint32_t FALCON_IMFILLRNG1;
|
||||
uint32_t FALCON_IMFILLCTL;
|
||||
uint32_t _0x115C;
|
||||
uint32_t _0x1160;
|
||||
uint32_t _0x1164;
|
||||
uint32_t FALCON_EXTERRADDR;
|
||||
uint32_t FALCON_EXTERRSTAT;
|
||||
uint32_t _0x1170;
|
||||
uint32_t _0x1174;
|
||||
uint32_t _0x1178;
|
||||
uint32_t FALCON_CG2;
|
||||
uint32_t FALCON_CODE_INDEX;
|
||||
uint32_t FALCON_CODE;
|
||||
uint32_t FALCON_CODE_VIRT_ADDR;
|
||||
uint8_t _0x118C[0x34];
|
||||
uint32_t FALCON_DATA_INDEX0;
|
||||
uint32_t FALCON_DATA0;
|
||||
uint32_t FALCON_DATA_INDEX1;
|
||||
uint32_t FALCON_DATA1;
|
||||
uint32_t FALCON_DATA_INDEX2;
|
||||
uint32_t FALCON_DATA2;
|
||||
uint32_t FALCON_DATA_INDEX3;
|
||||
uint32_t FALCON_DATA3;
|
||||
uint32_t FALCON_DATA_INDEX4;
|
||||
uint32_t FALCON_DATA4;
|
||||
uint32_t FALCON_DATA_INDEX5;
|
||||
uint32_t FALCON_DATA5;
|
||||
uint32_t FALCON_DATA_INDEX6;
|
||||
uint32_t FALCON_DATA6;
|
||||
uint32_t FALCON_DATA_INDEX7;
|
||||
uint32_t FALCON_DATA7;
|
||||
uint32_t FALCON_ICD_CMD;
|
||||
uint32_t FALCON_ICD_ADDR;
|
||||
uint32_t FALCON_ICD_WDATA;
|
||||
uint32_t FALCON_ICD_RDATA;
|
||||
uint8_t _0x1210[0x30];
|
||||
uint32_t FALCON_SCTL;
|
||||
uint8_t _0x1244[0x5F8]; /* Ignore non Falcon registers. */
|
||||
uint32_t TSEC_THI_INCR_SYNCPT; /* Tegra Host Interface registers. */
|
||||
uint32_t TSEC_THI_INCR_SYNCPT_CTRL;
|
||||
uint32_t TSEC_THI_INCR_SYNCPT_ERR;
|
||||
uint32_t TSEC_THI_CTXSW_INCR_SYNCPT;
|
||||
uint32_t _0x10[0x4];
|
||||
uint32_t TSEC_THI_CTXSW;
|
||||
uint32_t TSEC_THI_CTXSW_NEXT;
|
||||
uint32_t TSEC_THI_CONT_SYNCPT_EOF;
|
||||
uint32_t TSEC_THI_CONT_SYNCPT_L1;
|
||||
uint32_t TSEC_THI_STREAMID0;
|
||||
uint32_t TSEC_THI_STREAMID1;
|
||||
uint32_t TSEC_THI_THI_SEC;
|
||||
uint32_t _0x3C;
|
||||
uint32_t TSEC_THI_METHOD0;
|
||||
uint32_t TSEC_THI_METHOD1;
|
||||
uint32_t _0x48[0x6];
|
||||
uint32_t TSEC_THI_CONTEXT_SWITCH;
|
||||
uint32_t _0x64[0x5];
|
||||
uint32_t TSEC_THI_INT_STATUS;
|
||||
uint32_t TSEC_THI_INT_MASK;
|
||||
uint32_t TSEC_THI_CONFIG0;
|
||||
uint32_t TSEC_THI_DBG_MISC;
|
||||
uint32_t TSEC_THI_SLCG_OVERRIDE_HIGH_A;
|
||||
uint32_t TSEC_THI_SLCG_OVERRIDE_LOW_A;
|
||||
uint32_t _0x90[0x35C];
|
||||
uint32_t TSEC_THI_CLK_OVERRIDE;
|
||||
uint32_t _0xE04[0x7F];
|
||||
uint32_t TSEC_FALCON_IRQSSET; /* Falcon microcontroller registers. */
|
||||
uint32_t TSEC_FALCON_IRQSCLR;
|
||||
uint32_t TSEC_FALCON_IRQSTAT;
|
||||
uint32_t TSEC_FALCON_IRQMODE;
|
||||
uint32_t TSEC_FALCON_IRQMSET;
|
||||
uint32_t TSEC_FALCON_IRQMCLR;
|
||||
uint32_t TSEC_FALCON_IRQMASK;
|
||||
uint32_t TSEC_FALCON_IRQDEST;
|
||||
uint32_t TSEC_FALCON_GPTMRINT;
|
||||
uint32_t TSEC_FALCON_GPTMRVAL;
|
||||
uint32_t TSEC_FALCON_GPTMRCTL;
|
||||
uint32_t TSEC_FALCON_PTIMER0;
|
||||
uint32_t TSEC_FALCON_PTIMER1;
|
||||
uint32_t TSEC_FALCON_WDTMRVAL;
|
||||
uint32_t TSEC_FALCON_WDTMRCTL;
|
||||
uint32_t TSEC_FALCON_IRQDEST2;
|
||||
uint32_t TSEC_FALCON_MAILBOX0;
|
||||
uint32_t TSEC_FALCON_MAILBOX1;
|
||||
uint32_t TSEC_FALCON_ITFEN;
|
||||
uint32_t TSEC_FALCON_IDLESTATE;
|
||||
uint32_t TSEC_FALCON_CURCTX;
|
||||
uint32_t TSEC_FALCON_NXTCTX;
|
||||
uint32_t TSEC_FALCON_CTXACK;
|
||||
uint32_t TSEC_FALCON_FHSTATE;
|
||||
uint32_t TSEC_FALCON_PRIVSTATE;
|
||||
uint32_t TSEC_FALCON_MTHDDATA;
|
||||
uint32_t TSEC_FALCON_MTHDID;
|
||||
uint32_t TSEC_FALCON_MTHDWDAT;
|
||||
uint32_t TSEC_FALCON_MTHDCOUNT;
|
||||
uint32_t TSEC_FALCON_MTHDPOP;
|
||||
uint32_t TSEC_FALCON_MTHDRAMSZ;
|
||||
uint32_t TSEC_FALCON_SFTRESET;
|
||||
uint32_t TSEC_FALCON_OS;
|
||||
uint32_t TSEC_FALCON_RM;
|
||||
uint32_t TSEC_FALCON_SOFT_PM;
|
||||
uint32_t TSEC_FALCON_SOFT_MODE;
|
||||
uint32_t TSEC_FALCON_DEBUG1;
|
||||
uint32_t TSEC_FALCON_DEBUGINFO;
|
||||
uint32_t TSEC_FALCON_IBRKPT1;
|
||||
uint32_t TSEC_FALCON_IBRKPT2;
|
||||
uint32_t TSEC_FALCON_CGCTL;
|
||||
uint32_t TSEC_FALCON_ENGCTL;
|
||||
uint32_t TSEC_FALCON_PMM;
|
||||
uint32_t TSEC_FALCON_ADDR;
|
||||
uint32_t TSEC_FALCON_IBRKPT3;
|
||||
uint32_t TSEC_FALCON_IBRKPT4;
|
||||
uint32_t TSEC_FALCON_IBRKPT5;
|
||||
uint32_t _0x10BC[0x5];
|
||||
uint32_t TSEC_FALCON_EXCI;
|
||||
uint32_t TSEC_FALCON_SVEC_SPR;
|
||||
uint32_t TSEC_FALCON_RSTAT0;
|
||||
uint32_t TSEC_FALCON_RSTAT3;
|
||||
uint32_t _0x10E0[0x8];
|
||||
uint32_t TSEC_FALCON_CPUCTL;
|
||||
uint32_t TSEC_FALCON_BOOTVEC;
|
||||
uint32_t TSEC_FALCON_HWCFG;
|
||||
uint32_t TSEC_FALCON_DMACTL;
|
||||
uint32_t TSEC_FALCON_DMATRFBASE;
|
||||
uint32_t TSEC_FALCON_DMATRFMOFFS;
|
||||
uint32_t TSEC_FALCON_DMATRFCMD;
|
||||
uint32_t TSEC_FALCON_DMATRFFBOFFS;
|
||||
uint32_t TSEC_FALCON_DMAPOLL_FB;
|
||||
uint32_t TSEC_FALCON_DMAPOLL_CP;
|
||||
uint32_t TSEC_FALCON_DBG_STATE;
|
||||
uint32_t TSEC_FALCON_HWCFG1;
|
||||
uint32_t TSEC_FALCON_CPUCTL_ALIAS;
|
||||
uint32_t _0x1134;
|
||||
uint32_t TSEC_FALCON_STACKCFG;
|
||||
uint32_t _0x113C;
|
||||
uint32_t TSEC_FALCON_IMCTL;
|
||||
uint32_t TSEC_FALCON_IMSTAT;
|
||||
uint32_t TSEC_FALCON_TRACEIDX;
|
||||
uint32_t TSEC_FALCON_TRACEPC;
|
||||
uint32_t TSEC_FALCON_IMFILLRNG0;
|
||||
uint32_t TSEC_FALCON_IMFILLRNG1;
|
||||
uint32_t TSEC_FALCON_IMFILLCTL;
|
||||
uint32_t TSEC_FALCON_IMCTL_DEBUG;
|
||||
uint32_t TSEC_FALCON_CMEMBASE;
|
||||
uint32_t TSEC_FALCON_DMEMAPERT;
|
||||
uint32_t TSEC_FALCON_EXTERRADDR;
|
||||
uint32_t TSEC_FALCON_EXTERRSTAT;
|
||||
uint32_t _0x1170[0x3];
|
||||
uint32_t TSEC_FALCON_CG2;
|
||||
uint32_t TSEC_FALCON_IMEMC0;
|
||||
uint32_t TSEC_FALCON_IMEMD0;
|
||||
uint32_t TSEC_FALCON_IMEMT0;
|
||||
uint32_t _0x118C;
|
||||
uint32_t TSEC_FALCON_IMEMC1;
|
||||
uint32_t TSEC_FALCON_IMEMD1;
|
||||
uint32_t TSEC_FALCON_IMEMT1;
|
||||
uint32_t _0x119C;
|
||||
uint32_t TSEC_FALCON_IMEMC2;
|
||||
uint32_t TSEC_FALCON_IMEMD2;
|
||||
uint32_t TSEC_FALCON_IMEMT2;
|
||||
uint32_t _0x11AC;
|
||||
uint32_t TSEC_FALCON_IMEMC3;
|
||||
uint32_t TSEC_FALCON_IMEMD3;
|
||||
uint32_t TSEC_FALCON_IMEMT3;
|
||||
uint32_t _0x11BC;
|
||||
uint32_t TSEC_FALCON_DMEMC0;
|
||||
uint32_t TSEC_FALCON_DMEMD0;
|
||||
uint32_t TSEC_FALCON_DMEMC1;
|
||||
uint32_t TSEC_FALCON_DMEMD1;
|
||||
uint32_t TSEC_FALCON_DMEMC2;
|
||||
uint32_t TSEC_FALCON_DMEMD2;
|
||||
uint32_t TSEC_FALCON_DMEMC3;
|
||||
uint32_t TSEC_FALCON_DMEMD3;
|
||||
uint32_t TSEC_FALCON_DMEMC4;
|
||||
uint32_t TSEC_FALCON_DMEMD4;
|
||||
uint32_t TSEC_FALCON_DMEMC5;
|
||||
uint32_t TSEC_FALCON_DMEMD5;
|
||||
uint32_t TSEC_FALCON_DMEMC6;
|
||||
uint32_t TSEC_FALCON_DMEMD6;
|
||||
uint32_t TSEC_FALCON_DMEMC7;
|
||||
uint32_t TSEC_FALCON_DMEMD7;
|
||||
uint32_t TSEC_FALCON_ICD_CMD;
|
||||
uint32_t TSEC_FALCON_ICD_ADDR;
|
||||
uint32_t TSEC_FALCON_ICD_WDATA;
|
||||
uint32_t TSEC_FALCON_ICD_RDATA;
|
||||
uint32_t _0x1210[0xC];
|
||||
uint32_t TSEC_FALCON_SCTL;
|
||||
uint32_t TSEC_FALCON_SSTAT;
|
||||
uint32_t _0x1248[0xE];
|
||||
uint32_t TSEC_FALCON_SPROT_IMEM;
|
||||
uint32_t TSEC_FALCON_SPROT_DMEM;
|
||||
uint32_t TSEC_FALCON_SPROT_CPUCTL;
|
||||
uint32_t TSEC_FALCON_SPROT_MISC;
|
||||
uint32_t TSEC_FALCON_SPROT_IRQ;
|
||||
uint32_t TSEC_FALCON_SPROT_MTHD;
|
||||
uint32_t TSEC_FALCON_SPROT_SCTL;
|
||||
uint32_t TSEC_FALCON_SPROT_WDTMR;
|
||||
uint32_t _0x12A0[0x8];
|
||||
uint32_t TSEC_FALCON_DMAINFO_FINISHED_FBRD_LOW;
|
||||
uint32_t TSEC_FALCON_DMAINFO_FINISHED_FBRD_HIGH;
|
||||
uint32_t TSEC_FALCON_DMAINFO_FINISHED_FBWR_LOW;
|
||||
uint32_t TSEC_FALCON_DMAINFO_FINISHED_FBWR_HIGH;
|
||||
uint32_t TSEC_FALCON_DMAINFO_CURRENT_FBRD_LOW;
|
||||
uint32_t TSEC_FALCON_DMAINFO_CURRENT_FBRD_HIGH;
|
||||
uint32_t TSEC_FALCON_DMAINFO_CURRENT_FBWR_LOW;
|
||||
uint32_t TSEC_FALCON_DMAINFO_CURRENT_FBWR_HIGH;
|
||||
uint32_t TSEC_FALCON_DMAINFO_CTL;
|
||||
uint32_t _0x12E4[0x47];
|
||||
uint32_t TSEC_SCP_CTL0; /* Secure Co-processor registers. */
|
||||
uint32_t TSEC_SCP_CTL1;
|
||||
uint32_t TSEC_SCP_CTL_STAT;
|
||||
uint32_t TSEC_SCP_CTL_LOCK;
|
||||
uint32_t TSEC_SCP_CFG;
|
||||
uint32_t TSEC_SCP_CTL_SCP;
|
||||
uint32_t TSEC_SCP_CTL_PKEY;
|
||||
uint32_t TSEC_SCP_CTL_DBG;
|
||||
uint32_t TSEC_SCP_DBG0;
|
||||
uint32_t TSEC_SCP_DBG1;
|
||||
uint32_t TSEC_SCP_DBG2;
|
||||
uint32_t _0x142C;
|
||||
uint32_t TSEC_SCP_CMD;
|
||||
uint32_t _0x1434[0x7];
|
||||
uint32_t TSEC_SCP_STAT0;
|
||||
uint32_t TSEC_SCP_STAT1;
|
||||
uint32_t TSEC_SCP_STAT2;
|
||||
uint32_t _0x145C[0x5];
|
||||
uint32_t TSEC_SCP_RND_STAT0;
|
||||
uint32_t TSEC_SCP_RND_STAT1;
|
||||
uint32_t _0x1478[0x2];
|
||||
uint32_t TSEC_SCP_IRQSTAT;
|
||||
uint32_t TSEC_SCP_IRQMASK;
|
||||
uint32_t _0x1488[0x2];
|
||||
uint32_t TSEC_SCP_ACL_ERR;
|
||||
uint32_t TSEC_SCP_SEC_ERR;
|
||||
uint32_t TSEC_SCP_CMD_ERR;
|
||||
uint32_t _0x149C[0x19];
|
||||
uint32_t TSEC_RND_CTL0; /* Random Number Generator registers. */
|
||||
uint32_t TSEC_RND_CTL1;
|
||||
uint32_t TSEC_RND_CTL2;
|
||||
uint32_t TSEC_RND_CTL3;
|
||||
uint32_t TSEC_RND_CTL4;
|
||||
uint32_t TSEC_RND_CTL5;
|
||||
uint32_t TSEC_RND_CTL6;
|
||||
uint32_t TSEC_RND_CTL7;
|
||||
uint32_t TSEC_RND_CTL8;
|
||||
uint32_t TSEC_RND_CTL9;
|
||||
uint32_t TSEC_RND_CTL10;
|
||||
uint32_t TSEC_RND_CTL11;
|
||||
uint32_t _0x1530[0x34];
|
||||
uint32_t TSEC_TFBIF_CTL; /* Tegra Framebuffer Interface registers. */
|
||||
uint32_t TSEC_TFBIF_MCCIF_FIFOCTRL;
|
||||
uint32_t TSEC_TFBIF_THROTTLE;
|
||||
uint32_t TSEC_TFBIF_DBG_STAT0;
|
||||
uint32_t TSEC_TFBIF_DBG_STAT1;
|
||||
uint32_t TSEC_TFBIF_DBG_RDCOUNT_LO;
|
||||
uint32_t TSEC_TFBIF_DBG_RDCOUNT_HI;
|
||||
uint32_t TSEC_TFBIF_DBG_WRCOUNT_LO;
|
||||
uint32_t TSEC_TFBIF_DBG_WRCOUNT_HI;
|
||||
uint32_t TSEC_TFBIF_DBG_R32COUNT;
|
||||
uint32_t TSEC_TFBIF_DBG_R64COUNT;
|
||||
uint32_t TSEC_TFBIF_DBG_R128COUNT;
|
||||
uint32_t _0x1630;
|
||||
uint32_t TSEC_TFBIF_MCCIF_FIFOCTRL1;
|
||||
uint32_t TSEC_TFBIF_WRR_RDP;
|
||||
uint32_t _0x163C;
|
||||
uint32_t TSEC_TFBIF_SPROT_EMEM;
|
||||
uint32_t TSEC_TFBIF_TRANSCFG;
|
||||
uint32_t TSEC_TFBIF_REGIONCFG;
|
||||
uint32_t TSEC_TFBIF_ACTMON_ACTIVE_MASK;
|
||||
uint32_t TSEC_TFBIF_ACTMON_ACTIVE_BORPS;
|
||||
uint32_t TSEC_TFBIF_ACTMON_ACTIVE_WEIGHT;
|
||||
uint32_t _0x1658[0x2];
|
||||
uint32_t TSEC_TFBIF_ACTMON_MCB_MASK;
|
||||
uint32_t TSEC_TFBIF_ACTMON_MCB_BORPS;
|
||||
uint32_t TSEC_TFBIF_ACTMON_MCB_WEIGHT;
|
||||
uint32_t _0x166C;
|
||||
uint32_t TSEC_TFBIF_THI_TRANSPROP;
|
||||
uint32_t _0x1674[0x17];
|
||||
uint32_t TSEC_CG; /* Clock Gate registers. */
|
||||
uint32_t _0x16D4[0xB];
|
||||
uint32_t TSEC_BAR0_CTL; /* HOST1X device DMA registers. */
|
||||
uint32_t TSEC_BAR0_ADDR;
|
||||
uint32_t TSEC_BAR0_DATA;
|
||||
uint32_t TSEC_BAR0_TIMEOUT;
|
||||
uint32_t _0x1710[0x3C];
|
||||
uint32_t TSEC_TEGRA_FALCON_IP_VER; /* Miscellaneous registers. */
|
||||
uint32_t _0x1804[0xD];
|
||||
uint32_t TSEC_TEGRA_CTL;
|
||||
uint32_t _0x183C[0x31];
|
||||
} tegra_tsec_t;
|
||||
|
||||
static inline volatile tegra_tsec_t *tsec_get_regs(void)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
[subrepo]
|
||||
remote = https://github.com/Atmosphere-NX/Atmosphere-libs
|
||||
branch = master
|
||||
commit = 4d5a09e5d44d04134bb8ac484e0f4b822f9d0cb4
|
||||
parent = 2c9e1a814ca6a2b085fbcd9e7e5c4b0ea1c74ede
|
||||
commit = 9261160c738465556195e9326348782edf80556f
|
||||
parent = 0fdbdb1f4d2965e09af73bded58762aaa145a576
|
||||
method = merge
|
||||
cmdver = 0.4.0
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
ATMOSPHERE_LIBRARIES := libstratosphere
|
||||
ATMOSPHERE_LIBRARIES := libmesosphere libstratosphere
|
||||
|
||||
TOPTARGETS := all clean
|
||||
|
||||
|
||||
5
libraries/config/arch/arm64/cpu/cortex_a57/cpu.mk
Normal file
5
libraries/config/arch/arm64/cpu/cortex_a57/cpu.mk
Normal file
@@ -0,0 +1,5 @@
|
||||
export ATMOSPHERE_DEFINES += -DATMOSPHERE_CPU_ARM_CORTEX_A57
|
||||
export ATMOSPHERE_SETTINGS += -mtune=cortex-a57
|
||||
export ATMOSPHERE_CFLAGS +=
|
||||
export ATMOSPHERE_CXXFLAGS +=
|
||||
export ATMOSPHERE_ASFLAGS +=
|
||||
@@ -1,5 +1,5 @@
|
||||
export ATMOSPHERE_DEFINES += -DATMOSPHERE_BOARD_NINTENDO_SWITCH -D__SWITCH__
|
||||
export ATMOSPHERE_SETTINGS += -mtune=cortex-a57
|
||||
export ATMOSPHERE_SETTINGS +=
|
||||
export ATMOSPHERE_CFLAGS +=
|
||||
export ATMOSPHERE_CXXFLAGS +=
|
||||
export ATMOSPHERE_ASFLAGS +=
|
||||
@@ -1,6 +1,7 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
DIR_WILDCARD=$(foreach d,$(wildcard $(1:=/*)),$(if $(wildcard $d/.),$(call DIR_WILDCARD,$d) $d,))
|
||||
|
||||
export ATMOSPHERE_CONFIG_MAKE_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||
export ATMOSPHERE_LIBRARIES_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/..
|
||||
@@ -9,6 +10,10 @@ ifeq ($(strip $(ATMOSPHERE_BOARD)),)
|
||||
export ATMOSPHERE_BOARD := nx-hac-001
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(ATMOSPHERE_CPU)),)
|
||||
export ATMOSPHERE_CPU := arm-cortex-a57
|
||||
endif
|
||||
|
||||
export ATMOSPHERE_DEFINES := -DATMOSPHERE
|
||||
export ATMOSPHERE_SETTINGS := -fPIE -g
|
||||
export ATMOSPHERE_CFLAGS := -Wall -ffunction-sections -fdata-sections -fno-strict-aliasing -fwrapv \
|
||||
@@ -27,14 +32,21 @@ export ATMOSPHERE_BOARD_NAME := nintendo_switch
|
||||
export ATMOSPHERE_OS_NAME := horizon
|
||||
endif
|
||||
|
||||
ifeq ($(ATMOSPHERE_CPU),arm-cortex-a57)
|
||||
export ATMOSPHERE_CPU_DIR := arch/arm64/cpu/cortex_a57
|
||||
export ATMOSPHERE_CPU_NAME := arm_cortex_a57
|
||||
endif
|
||||
|
||||
|
||||
export ATMOSPHERE_ARCH_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/$(ATMOSPHERE_ARCH_DIR)
|
||||
export ATMOSPHERE_BOARD_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/$(ATMOSPHERE_BOARD_DIR)
|
||||
export ATMOSPHERE_OS_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/$(ATMOSPHERE_OS_DIR)
|
||||
export ATMOSPHERE_CPU_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/$(ATMOSPHERE_CPU_DIR)
|
||||
|
||||
include $(ATMOSPHERE_ARCH_MAKE_DIR)/arch.mk
|
||||
include $(ATMOSPHERE_BOARD_MAKE_DIR)/board.mk
|
||||
include $(ATMOSPHERE_OS_MAKE_DIR)/os.mk
|
||||
include $(ATMOSPHERE_CPU_MAKE_DIR)/cpu.mk
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# get atmosphere git revision information
|
||||
@@ -49,26 +61,29 @@ endif
|
||||
|
||||
ATMOSPHERE_DEFINES += -DATMOSPHERE_GIT_BRANCH=\"$(ATMOSPHERE_GIT_BRANCH)\" -DATMOSPHERE_GIT_REVISION=\"$(ATMOSPHERE_GIT_REVISION)\"
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# Ensure top directory is set.
|
||||
#---------------------------------------------------------------------------------
|
||||
TOPDIR ?= $(CURDIR)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# SOURCES is a list of directories containing source code
|
||||
# DATA is a list of directories containing data files
|
||||
# INCLUDES is a list of directories containing header files
|
||||
#---------------------------------------------------------------------------------
|
||||
export TARGET := $(notdir $(CURDIR))
|
||||
export BUILD := build
|
||||
export DATA := data
|
||||
export INCLUDES := include
|
||||
export SOURCES ?= $(shell find source -type d \
|
||||
-not \( -path source/arch -prune \) \
|
||||
-not \( -path source/board -prune \) \)
|
||||
TARGET := $(notdir $(CURDIR))
|
||||
BUILD := build
|
||||
DATA := data
|
||||
INCLUDES := include
|
||||
SOURCES ?= $(foreach d,$(filter-out source/arch source/board,$(wildcard source)),$(call DIR_WILDCARD,$d) $d)
|
||||
|
||||
ifneq ($(strip $(wildcard source/$(ATMOSPHERE_ARCH_DIR)./.*)),)
|
||||
SOURCES += $(shell find source/$(ATMOSPHERE_ARCH_DIR) -type d)
|
||||
ifneq ($(strip $(wildcard source/$(ATMOSPHERE_ARCH_DIR)/.*)),)
|
||||
SOURCES += $(call DIR_WILDCARD,source/$(ATMOSPHERE_ARCH_DIR))
|
||||
endif
|
||||
ifneq ($(strip $(wildcard source/$(ATMOSPHERE_BOARD_DIR)./.*)),)
|
||||
SOURCES += $(shell find source/$(ATMOSPHERE_BOARD_DIR) -type d)
|
||||
ifneq ($(strip $(wildcard source/$(ATMOSPHERE_BOARD_DIR)/.*)),)
|
||||
SOURCES += $(call DIR_WILDCARD,source/$(ATMOSPHERE_BOARD_DIR))
|
||||
endif
|
||||
ifneq ($(strip $(wildcard source/$(ATMOSPHERE_OS_DIR)./.*)),)
|
||||
SOURCES += $(shell find source/$(ATMOSPHERE_OS_DIR) -type d)
|
||||
ifneq ($(strip $(wildcard source/$(ATMOSPHERE_OS_DIR)/.*)),)
|
||||
SOURCES += $(call DIR_WILDCARD,source/$(ATMOSPHERE_OS_DIR))
|
||||
endif
|
||||
|
||||
39
libraries/config/templates/mesosphere.mk
Normal file
39
libraries/config/templates/mesosphere.mk
Normal file
@@ -0,0 +1,39 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
# pull in common atmosphere configuration
|
||||
#---------------------------------------------------------------------------------
|
||||
include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../common.mk
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
export DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_MESOSPHERE
|
||||
export SETTINGS := $(ATMOSPHERE_SETTINGS) -O2 -mgeneral-regs-only -ffixed-x18 -Werror
|
||||
export CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
||||
export CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS)
|
||||
export ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS) $(DEFINES)
|
||||
|
||||
export LDFLAGS = -specs=$(TOPDIR)/kernel_ldr.specs -nostdlib -nostartfiles -g $(SETTINGS) -Wl,-Map,$(notdir $*.map)
|
||||
|
||||
export CXXWRAPS := -Wl,--wrap,__cxa_pure_virtual \
|
||||
-Wl,--wrap,__cxa_throw \
|
||||
-Wl,--wrap,__cxa_rethrow \
|
||||
-Wl,--wrap,__cxa_allocate_exception \
|
||||
-Wl,--wrap,__cxa_free_exception \
|
||||
-Wl,--wrap,__cxa_begin_catch \
|
||||
-Wl,--wrap,__cxa_end_catch \
|
||||
-Wl,--wrap,__cxa_call_unexpected \
|
||||
-Wl,--wrap,__cxa_call_terminate \
|
||||
-Wl,--wrap,__gxx_personality_v0 \
|
||||
-Wl,--wrap,_Unwind_Resume \
|
||||
-Wl,--wrap,_Unwind_Resume \
|
||||
-Wl,--wrap,_ZSt19__throw_logic_errorPKc \
|
||||
-Wl,--wrap,_ZSt20__throw_length_errorPKc \
|
||||
-Wl,--wrap,_ZNSt11logic_errorC2EPKc
|
||||
|
||||
export LIBS := -lmesosphere
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS := $(ATMOSPHERE_LIBRARIES_DIR)/libvapours $(ATMOSPHERE_LIBRARIES_DIR)/libmesosphere
|
||||
@@ -19,7 +19,7 @@ export DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_STRATOSPHERE
|
||||
export SETTINGS := $(ATMOSPHERE_SETTINGS) -O2
|
||||
export CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
||||
export CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS)
|
||||
export ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS)
|
||||
export ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS) $(DEFINES)
|
||||
|
||||
export CXXWRAPS := -Wl,--wrap,__cxa_pure_virtual \
|
||||
-Wl,--wrap,__cxa_throw \
|
||||
|
||||
129
libraries/libmesosphere/Makefile
Normal file
129
libraries/libmesosphere/Makefile
Normal file
@@ -0,0 +1,129 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
# pull in common atmosphere configuration
|
||||
#---------------------------------------------------------------------------------
|
||||
include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../config/common.mk
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_MESOSPHERE
|
||||
SETTINGS := $(ATMOSPHERE_SETTINGS) -O2 -mgeneral-regs-only -ffixed-x18 -Werror
|
||||
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
||||
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -flto
|
||||
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS)
|
||||
|
||||
LIBS :=
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS := $(ATMOSPHERE_LIBRARIES_DIR)/libvapours
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#---------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||
|
||||
CFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.c)) $(notdir $(wildcard $(dir)/*.board.*.c)) $(notdir $(wildcard $(dir)/*.os.*.c)), \
|
||||
$(notdir $(wildcard $(dir)/*.c))))
|
||||
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).c)))
|
||||
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).c)))
|
||||
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).c)))
|
||||
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.cpp)) $(notdir $(wildcard $(dir)/*.board.*.cpp)) $(notdir $(wildcard $(dir)/*.os.*.cpp)), \
|
||||
$(notdir $(wildcard $(dir)/*.cpp))))
|
||||
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).cpp)))
|
||||
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).cpp)))
|
||||
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).cpp)))
|
||||
|
||||
SFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.s)) $(notdir $(wildcard $(dir)/*.board.*.s)) $(notdir $(wildcard $(dir)/*.os.*.s)), \
|
||||
$(notdir $(wildcard $(dir)/*.s))))
|
||||
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).s)))
|
||||
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).s)))
|
||||
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).s)))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(CPPFILES)),)
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CC)
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CXX)
|
||||
#---------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
|
||||
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
|
||||
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
|
||||
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
-I.
|
||||
|
||||
.PHONY: clean all
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
all: lib/$(TARGET).a
|
||||
|
||||
lib:
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
|
||||
release:
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
|
||||
lib/$(TARGET).a : lib release $(SOURCES) $(INCLUDES)
|
||||
@$(MAKE) BUILD=release OUTPUT=$(CURDIR)/$@ \
|
||||
BUILD_CFLAGS="-DNDEBUG=1 -O2" \
|
||||
DEPSDIR=$(CURDIR)/release \
|
||||
--no-print-directory -C release \
|
||||
-f $(CURDIR)/Makefile
|
||||
|
||||
dist-bin: all
|
||||
@tar --exclude=*~ -cjf $(TARGET).tar.bz2 include lib
|
||||
|
||||
dist-src:
|
||||
@tar --exclude=*~ -cjf $(TARGET)-src.tar.bz2 include source Makefile
|
||||
|
||||
dist: dist-src dist-bin
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr release lib *.bz2
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
$(OUTPUT) : $(OFILES)
|
||||
|
||||
$(OFILES_SRC) : $(HFILES_BIN)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%_bin.h %.bin.o : %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
||||
|
||||
28
libraries/libmesosphere/README.md
Normal file
28
libraries/libmesosphere/README.md
Normal file
@@ -0,0 +1,28 @@
|
||||

|
||||
|
||||
libmesosphere is a work-in-progress C++ library implementing functionality for the Horizon Kernel.
|
||||
|
||||
Licensing
|
||||
=====
|
||||
|
||||
This software is licensed under the terms of the GPLv2, with exemptions for specific projects noted below.
|
||||
|
||||
You can find a copy of the license in the [LICENSE file](LICENSE).
|
||||
|
||||
Exemptions:
|
||||
* The [yuzu emulator project](https://github.com/yuzu-emu/yuzu) is exempt from GPLv2 licensing and may (at its option) instead license any source code authored for the libmesosphere project as GPLv2 or later.
|
||||
|
||||
Credits
|
||||
=====
|
||||
|
||||
libmesosphere is currently being developed and maintained by __SciresM__.<br>
|
||||
|
||||
In addition to those credited in [Atmosphère's credits](https://github.com/Atmosphere-NX/Atmosphere/blob/master/README.md#Credits), we would like to thank for contributing to libmesosphere in some significant way:
|
||||
|
||||
* @[devkitPro](https://github.com/devkitPro)
|
||||
* @[yellows8](https://github.com/yellows8)
|
||||
* @[qlutoo](https://github.com/plutooo)
|
||||
* @[hedgeberg](https://github.com/hedgeberg)
|
||||
* @[Nintendo](https://github.com/Nintendo)
|
||||
* @[NVidia](https://github.com/NVidia)
|
||||
* @[Kaphotics](https://github.com/kwsch)
|
||||
38
libraries/libmesosphere/include/mesosphere.hpp
Normal file
38
libraries/libmesosphere/include/mesosphere.hpp
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/* All kernel code should have access to libvapours. */
|
||||
#include <vapours.hpp>
|
||||
|
||||
/* First, pull in core macros (panic, etc). */
|
||||
#include "mesosphere/kern_panic.hpp"
|
||||
|
||||
/* Primitive types. */
|
||||
#include "mesosphere/kern_k_typed_address.hpp"
|
||||
#include "mesosphere/kern_initial_process.hpp"
|
||||
|
||||
/* Core pre-initialization includes. */
|
||||
#include "mesosphere/kern_select_cpu.hpp"
|
||||
|
||||
/* Initialization headers. */
|
||||
#include "mesosphere/init/kern_init_elf.hpp"
|
||||
#include "mesosphere/init/kern_init_layout.hpp"
|
||||
#include "mesosphere/init/kern_init_page_table_select.hpp"
|
||||
|
||||
/* Core functionality. */
|
||||
#include "mesosphere/kern_select_interrupts.hpp"
|
||||
#include "mesosphere/kern_select_k_system_control.hpp"
|
||||
@@ -0,0 +1,498 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <mesosphere/kern_panic.hpp>
|
||||
#include <mesosphere/kern_k_typed_address.hpp>
|
||||
#include "../kern_cpu.hpp"
|
||||
|
||||
namespace ams::kern::init {
|
||||
|
||||
constexpr size_t PageSize = 0x1000;
|
||||
constexpr size_t L1BlockSize = 0x40000000;
|
||||
constexpr size_t L2BlockSize = 0x200000;
|
||||
constexpr size_t L2ContiguousBlockSize = 0x10 * L2BlockSize;
|
||||
constexpr size_t L3BlockSize = 0x1000;
|
||||
constexpr size_t L3ContiguousBlockSize = 0x10 * L3BlockSize;
|
||||
|
||||
class PageTableEntry {
|
||||
public:
|
||||
enum Permission : u64 {
|
||||
Permission_KernelRWX = ((0ul << 53) | (1ul << 54) | (0ul << 6)),
|
||||
Permission_KernelRX = ((0ul << 53) | (1ul << 54) | (2ul << 6)),
|
||||
Permission_KernelR = ((1ul << 53) | (1ul << 54) | (2ul << 6)),
|
||||
Permission_KernelRW = ((1ul << 53) | (1ul << 54) | (0ul << 6)),
|
||||
|
||||
Permission_UserRX = ((1ul << 53) | (0ul << 54) | (3ul << 6)),
|
||||
Permission_UserR = ((1ul << 53) | (1ul << 54) | (3ul << 6)),
|
||||
Permission_UserRW = ((1ul << 53) | (1ul << 54) | (1ul << 6)),
|
||||
};
|
||||
|
||||
enum Shareable : u64 {
|
||||
Shareable_NonShareable = (0 << 8),
|
||||
Shareable_OuterShareable = (2 << 8),
|
||||
Shareable_InnerShareable = (3 << 8),
|
||||
};
|
||||
|
||||
/* Official attributes are: */
|
||||
/* 0x00, 0x04, 0xFF, 0x44. 4-7 are unused. */
|
||||
enum PageAttribute : u64 {
|
||||
PageAttribute_Device_nGnRnE = (0 << 2),
|
||||
PageAttribute_Device_nGnRE = (1 << 2),
|
||||
PageAttribute_NormalMemory = (2 << 2),
|
||||
PageAttribute_NormalMemoryNotCacheable = (3 << 2),
|
||||
};
|
||||
|
||||
enum AccessFlag : u64 {
|
||||
AccessFlag_NotAccessed = (0 << 10),
|
||||
AccessFlag_Accessed = (1 << 10),
|
||||
};
|
||||
protected:
|
||||
u64 attributes;
|
||||
public:
|
||||
/* Take in a raw attribute. */
|
||||
constexpr ALWAYS_INLINE PageTableEntry(u64 attr) : attributes(attr) { /* ... */ }
|
||||
|
||||
/* Extend a previous attribute. */
|
||||
constexpr ALWAYS_INLINE PageTableEntry(const PageTableEntry &rhs, u64 new_attr) : attributes(rhs.attributes | new_attr) { /* ... */ }
|
||||
|
||||
/* Construct a new attribute. */
|
||||
constexpr ALWAYS_INLINE PageTableEntry(Permission perm, PageAttribute p_a, Shareable share)
|
||||
: attributes(static_cast<u64>(perm) | static_cast<u64>(AccessFlag_Accessed) | static_cast<u64>(p_a) | static_cast<u64>(share))
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
protected:
|
||||
constexpr ALWAYS_INLINE u64 GetBits(size_t offset, size_t count) const {
|
||||
return (this->attributes >> offset) & ((1ul << count) - 1);
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE u64 SelectBits(size_t offset, size_t count) const {
|
||||
return this->attributes & (((1ul << count) - 1) << offset);
|
||||
}
|
||||
public:
|
||||
constexpr ALWAYS_INLINE bool IsUserExecuteNever() const { return this->GetBits(54, 1) != 0; }
|
||||
constexpr ALWAYS_INLINE bool IsPrivilegedExecuteNever() const { return this->GetBits(53, 1) != 0; }
|
||||
constexpr ALWAYS_INLINE bool IsContiguous() const { return this->GetBits(52, 1) != 0; }
|
||||
constexpr ALWAYS_INLINE AccessFlag GetAccessFlag() const { return static_cast<AccessFlag>(this->GetBits(10, 1)); }
|
||||
constexpr ALWAYS_INLINE Shareable GetShareable() const { return static_cast<Shareable>(this->GetBits(8, 2)); }
|
||||
constexpr ALWAYS_INLINE PageAttribute GetPageAttribute() const { return static_cast<PageAttribute>(this->GetBits(2, 3)); }
|
||||
constexpr ALWAYS_INLINE bool IsNonSecure() const { return this->GetBits(5, 1) != 0; }
|
||||
constexpr ALWAYS_INLINE bool IsBlock() const { return this->GetBits(0, 2) == 0x1; }
|
||||
constexpr ALWAYS_INLINE bool IsTable() const { return this->GetBits(0, 2) == 0x3; }
|
||||
|
||||
/* Should not be called except by derived classes. */
|
||||
constexpr ALWAYS_INLINE u64 GetRawAttributes() const {
|
||||
return this->attributes;
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(PageTableEntry) == sizeof(u64));
|
||||
|
||||
constexpr PageTableEntry InvalidPageTableEntry = PageTableEntry(0);
|
||||
|
||||
constexpr size_t MaxPageTableEntries = PageSize / sizeof(PageTableEntry);
|
||||
|
||||
class L1PageTableEntry : public PageTableEntry {
|
||||
public:
|
||||
constexpr ALWAYS_INLINE L1PageTableEntry(KPhysicalAddress phys_addr, bool pxn)
|
||||
: PageTableEntry((0x3ul << 60) | (static_cast<u64>(pxn) << 59) | GetInteger(phys_addr) | 0x3)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE L1PageTableEntry(KPhysicalAddress phys_addr, const PageTableEntry &attr, bool contig)
|
||||
: PageTableEntry(attr, (static_cast<u64>(contig) << 52) | GetInteger(phys_addr) | 0x1)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE KPhysicalAddress GetBlock() const {
|
||||
return this->SelectBits(30, 18);
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE KPhysicalAddress GetTable() const {
|
||||
return this->SelectBits(12, 36);
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE bool IsCompatibleWithAttribute(const PageTableEntry &rhs, bool contig) const {
|
||||
/* Check whether this has the same permission/etc as the desired attributes. */
|
||||
return L1PageTableEntry(this->GetBlock(), rhs, contig).GetRawAttributes() == this->GetRawAttributes();
|
||||
}
|
||||
};
|
||||
|
||||
class L2PageTableEntry : public PageTableEntry {
|
||||
public:
|
||||
constexpr ALWAYS_INLINE L2PageTableEntry(KPhysicalAddress phys_addr, bool pxn)
|
||||
: PageTableEntry((0x3ul << 60) | (static_cast<u64>(pxn) << 59) | GetInteger(phys_addr) | 0x3)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE L2PageTableEntry(KPhysicalAddress phys_addr, const PageTableEntry &attr, bool contig)
|
||||
: PageTableEntry(attr, (static_cast<u64>(contig) << 52) | GetInteger(phys_addr) | 0x1)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE KPhysicalAddress GetBlock() const {
|
||||
return this->SelectBits(21, 27);
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE KPhysicalAddress GetTable() const {
|
||||
return this->SelectBits(12, 36);
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE bool IsCompatibleWithAttribute(const PageTableEntry &rhs, bool contig) const {
|
||||
/* Check whether this has the same permission/etc as the desired attributes. */
|
||||
return L2PageTableEntry(this->GetBlock(), rhs, contig).GetRawAttributes() == this->GetRawAttributes();
|
||||
}
|
||||
};
|
||||
|
||||
class L3PageTableEntry : public PageTableEntry {
|
||||
public:
|
||||
constexpr ALWAYS_INLINE L3PageTableEntry(KPhysicalAddress phys_addr, const PageTableEntry &attr, bool contig)
|
||||
: PageTableEntry(attr, (static_cast<u64>(contig) << 52) | GetInteger(phys_addr) | 0x3)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE bool IsBlock() const { return this->GetBits(0, 2) == 0x3; }
|
||||
|
||||
constexpr ALWAYS_INLINE KPhysicalAddress GetBlock() const {
|
||||
return this->SelectBits(12, 36);
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE bool IsCompatibleWithAttribute(const PageTableEntry &rhs, bool contig) const {
|
||||
/* Check whether this has the same permission/etc as the desired attributes. */
|
||||
return L3PageTableEntry(this->GetBlock(), rhs, contig).GetRawAttributes() == this->GetRawAttributes();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class KInitialPageTable {
|
||||
public:
|
||||
class IPageAllocator {
|
||||
public:
|
||||
virtual KPhysicalAddress Allocate() { return Null<KPhysicalAddress>; }
|
||||
virtual void Free(KPhysicalAddress phys_addr) { /* Nothing to do here. */ (void)(phys_addr); }
|
||||
};
|
||||
private:
|
||||
KPhysicalAddress l1_table;
|
||||
public:
|
||||
constexpr ALWAYS_INLINE KInitialPageTable(KPhysicalAddress l1) : l1_table(l1) {
|
||||
ClearNewPageTable(this->l1_table);
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE uintptr_t GetL1TableAddress() const {
|
||||
return GetInteger(this->l1_table);
|
||||
}
|
||||
private:
|
||||
static constexpr ALWAYS_INLINE L1PageTableEntry *GetL1Entry(KPhysicalAddress _l1_table, KVirtualAddress address) {
|
||||
L1PageTableEntry *l1_table = reinterpret_cast<L1PageTableEntry *>(GetInteger(_l1_table));
|
||||
return l1_table + ((GetInteger(address) >> 30) & (MaxPageTableEntries - 1));
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE L2PageTableEntry *GetL2Entry(const L1PageTableEntry *entry, KVirtualAddress address) {
|
||||
L2PageTableEntry *l2_table = reinterpret_cast<L2PageTableEntry *>(GetInteger(entry->GetTable()));
|
||||
return l2_table + ((GetInteger(address) >> 21) & (MaxPageTableEntries - 1));
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE L3PageTableEntry *GetL3Entry(const L2PageTableEntry *entry, KVirtualAddress address) {
|
||||
L3PageTableEntry *l3_table = reinterpret_cast<L3PageTableEntry *>(GetInteger(entry->GetTable()));
|
||||
return l3_table + ((GetInteger(address) >> 12) & (MaxPageTableEntries - 1));
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE void ClearNewPageTable(KPhysicalAddress address) {
|
||||
/* This Physical Address -> void * conversion is valid, because this is page table code. */
|
||||
/* The MMU is necessarily not yet turned on, if we are creating an initial page table. */
|
||||
std::memset(reinterpret_cast<void *>(GetInteger(address)), 0, PageSize);
|
||||
}
|
||||
public:
|
||||
void NOINLINE Map(KVirtualAddress virt_addr, size_t size, KPhysicalAddress phys_addr, const PageTableEntry &attr, IPageAllocator &allocator) {
|
||||
/* Ensure that addresses and sizes are page aligned. */
|
||||
MESOSPHERE_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), PageSize));
|
||||
MESOSPHERE_ABORT_UNLESS(util::IsAligned(GetInteger(phys_addr), PageSize));
|
||||
MESOSPHERE_ABORT_UNLESS(util::IsAligned(size, PageSize));
|
||||
|
||||
/* Iteratively map pages until the requested region is mapped. */
|
||||
while (size > 0) {
|
||||
L1PageTableEntry *l1_entry = GetL1Entry(this->l1_table, virt_addr);
|
||||
|
||||
/* Can we make an L1 block? */
|
||||
if (util::IsAligned(GetInteger(virt_addr), L1BlockSize) && util::IsAligned(GetInteger(phys_addr), L1BlockSize) && util::IsAligned(size, L1BlockSize)) {
|
||||
*l1_entry = L1PageTableEntry(phys_addr, attr, false);
|
||||
cpu::DataSynchronizationBarrierInnerShareable();
|
||||
|
||||
virt_addr += L1BlockSize;
|
||||
phys_addr += L1BlockSize;
|
||||
size -= L1BlockSize;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If we don't already have an L2 table, we need to make a new one. */
|
||||
if (!l1_entry->IsTable()) {
|
||||
KPhysicalAddress new_table = allocator.Allocate();
|
||||
ClearNewPageTable(new_table);
|
||||
*l1_entry = L1PageTableEntry(new_table, attr.IsPrivilegedExecuteNever());
|
||||
cpu::DataSynchronizationBarrierInnerShareable();
|
||||
}
|
||||
|
||||
L2PageTableEntry *l2_entry = GetL2Entry(l1_entry, virt_addr);
|
||||
|
||||
/* Can we make a contiguous L2 block? */
|
||||
if (util::IsAligned(GetInteger(virt_addr), L2ContiguousBlockSize) && util::IsAligned(GetInteger(phys_addr), L2ContiguousBlockSize) && util::IsAligned(size, L2ContiguousBlockSize)) {
|
||||
for (size_t i = 0; i < L2ContiguousBlockSize / L2BlockSize; i++) {
|
||||
l2_entry[i] = L2PageTableEntry(phys_addr, attr, true);
|
||||
cpu::DataSynchronizationBarrierInnerShareable();
|
||||
|
||||
virt_addr += L2BlockSize;
|
||||
phys_addr += L2BlockSize;
|
||||
size -= L2BlockSize;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Can we make an L2 block? */
|
||||
if (util::IsAligned(GetInteger(virt_addr), L2BlockSize) && util::IsAligned(GetInteger(phys_addr), L2BlockSize) && util::IsAligned(size, L2BlockSize)) {
|
||||
*l2_entry = L2PageTableEntry(phys_addr, attr, false);
|
||||
cpu::DataSynchronizationBarrierInnerShareable();
|
||||
|
||||
virt_addr += L2BlockSize;
|
||||
phys_addr += L2BlockSize;
|
||||
size -= L2BlockSize;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If we don't already have an L3 table, we need to make a new one. */
|
||||
if (!l2_entry->IsTable()) {
|
||||
KPhysicalAddress new_table = allocator.Allocate();
|
||||
ClearNewPageTable(new_table);
|
||||
*l2_entry = L2PageTableEntry(new_table, attr.IsPrivilegedExecuteNever());
|
||||
cpu::DataSynchronizationBarrierInnerShareable();
|
||||
}
|
||||
|
||||
L3PageTableEntry *l3_entry = GetL3Entry(l2_entry, virt_addr);
|
||||
|
||||
/* Can we make a contiguous L3 block? */
|
||||
if (util::IsAligned(GetInteger(virt_addr), L3ContiguousBlockSize) && util::IsAligned(GetInteger(phys_addr), L3ContiguousBlockSize) && util::IsAligned(size, L3ContiguousBlockSize)) {
|
||||
for (size_t i = 0; i < L3ContiguousBlockSize / L3BlockSize; i++) {
|
||||
l3_entry[i] = L3PageTableEntry(phys_addr, attr, true);
|
||||
cpu::DataSynchronizationBarrierInnerShareable();
|
||||
|
||||
virt_addr += L3BlockSize;
|
||||
phys_addr += L3BlockSize;
|
||||
size -= L3BlockSize;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Make an L3 block. */
|
||||
*l3_entry = L3PageTableEntry(phys_addr, attr, false);
|
||||
cpu::DataSynchronizationBarrierInnerShareable();
|
||||
virt_addr += L3BlockSize;
|
||||
phys_addr += L3BlockSize;
|
||||
size -= L3BlockSize;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsFree(KVirtualAddress virt_addr, size_t size) {
|
||||
/* Ensure that addresses and sizes are page aligned. */
|
||||
MESOSPHERE_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), PageSize));
|
||||
MESOSPHERE_ABORT_UNLESS(util::IsAligned(size, PageSize));
|
||||
|
||||
const KVirtualAddress end_virt_addr = virt_addr + size;
|
||||
while (virt_addr < end_virt_addr) {
|
||||
L1PageTableEntry *l1_entry = GetL1Entry(this->l1_table, virt_addr);
|
||||
|
||||
/* If an L1 block is mapped, the address isn't free. */
|
||||
if (l1_entry->IsBlock()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!l1_entry->IsTable()) {
|
||||
/* Not a table, so just move to check the next region. */
|
||||
virt_addr = util::AlignDown(GetInteger(virt_addr) + L1BlockSize, L1BlockSize);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Table, so check if we're mapped in L2. */
|
||||
L2PageTableEntry *l2_entry = GetL2Entry(l1_entry, virt_addr);
|
||||
|
||||
if (l2_entry->IsBlock()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!l2_entry->IsTable()) {
|
||||
/* Not a table, so just move to check the next region. */
|
||||
virt_addr = util::AlignDown(GetInteger(virt_addr) + L2BlockSize, L2BlockSize);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Table, so check if we're mapped in L3. */
|
||||
L3PageTableEntry *l3_entry = GetL3Entry(l2_entry, virt_addr);
|
||||
|
||||
if (l3_entry->IsBlock()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Not a block, so move on to check the next page. */
|
||||
virt_addr = util::AlignDown(GetInteger(virt_addr) + L3BlockSize, L3BlockSize);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Reprotect(KVirtualAddress virt_addr, size_t size, const PageTableEntry &attr_before, const PageTableEntry &attr_after) {
|
||||
/* Ensure data consistency before we begin reprotection. */
|
||||
cpu::DataSynchronizationBarrierInnerShareable();
|
||||
|
||||
/* Ensure that addresses and sizes are page aligned. */
|
||||
MESOSPHERE_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), PageSize));
|
||||
MESOSPHERE_ABORT_UNLESS(util::IsAligned(size, PageSize));
|
||||
|
||||
/* Iteratively reprotect pages until the requested region is reprotected. */
|
||||
while (size > 0) {
|
||||
L1PageTableEntry *l1_entry = GetL1Entry(this->l1_table, virt_addr);
|
||||
|
||||
/* Check if an L1 block is present. */
|
||||
if (l1_entry->IsBlock()) {
|
||||
/* Ensure that we are allowed to have an L1 block here. */
|
||||
const KPhysicalAddress block = l1_entry->GetBlock();
|
||||
MESOSPHERE_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), L1BlockSize));
|
||||
MESOSPHERE_ABORT_UNLESS(util::IsAligned(size, L1BlockSize));
|
||||
MESOSPHERE_ABORT_UNLESS(l1_entry->IsCompatibleWithAttribute(attr_before, false));
|
||||
|
||||
/* Invalidate the existing L1 block. */
|
||||
*static_cast<PageTableEntry *>(l1_entry) = InvalidPageTableEntry;
|
||||
cpu::DataSynchronizationBarrierInnerShareable();
|
||||
cpu::InvalidateEntireTlb();
|
||||
|
||||
/* Create new L1 block. */
|
||||
*l1_entry = L1PageTableEntry(block, attr_after, false);
|
||||
|
||||
virt_addr += L1BlockSize;
|
||||
size -= L1BlockSize;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Not a block, so we must be a table. */
|
||||
MESOSPHERE_ABORT_UNLESS(l1_entry->IsTable());
|
||||
|
||||
L2PageTableEntry *l2_entry = GetL2Entry(l1_entry, virt_addr);
|
||||
if (l2_entry->IsBlock()) {
|
||||
const KPhysicalAddress block = l2_entry->GetBlock();
|
||||
|
||||
if (l2_entry->IsContiguous()) {
|
||||
/* Ensure that we are allowed to have a contiguous L2 block here. */
|
||||
MESOSPHERE_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), L2ContiguousBlockSize));
|
||||
MESOSPHERE_ABORT_UNLESS(util::IsAligned(GetInteger(block), L2ContiguousBlockSize));
|
||||
MESOSPHERE_ABORT_UNLESS(util::IsAligned(size, L2ContiguousBlockSize));
|
||||
|
||||
/* Invalidate the existing contiguous L2 block. */
|
||||
for (size_t i = 0; i < L2ContiguousBlockSize / L2BlockSize; i++) {
|
||||
/* Ensure that the entry is valid. */
|
||||
MESOSPHERE_ABORT_UNLESS(l2_entry[i].IsCompatibleWithAttribute(attr_before, true));
|
||||
static_cast<PageTableEntry *>(l2_entry)[i] = InvalidPageTableEntry;
|
||||
}
|
||||
cpu::DataSynchronizationBarrierInnerShareable();
|
||||
cpu::InvalidateEntireTlb();
|
||||
|
||||
/* Create a new contiguous L2 block. */
|
||||
for (size_t i = 0; i < L2ContiguousBlockSize / L2BlockSize; i++) {
|
||||
l2_entry[i] = L2PageTableEntry(block + L2BlockSize * i, attr_after, true);
|
||||
}
|
||||
|
||||
virt_addr += L2ContiguousBlockSize;
|
||||
size -= L2ContiguousBlockSize;
|
||||
} else {
|
||||
/* Ensure that we are allowed to have an L2 block here. */
|
||||
MESOSPHERE_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), L2BlockSize));
|
||||
MESOSPHERE_ABORT_UNLESS(util::IsAligned(GetInteger(block), L2BlockSize));
|
||||
MESOSPHERE_ABORT_UNLESS(util::IsAligned(size, L2BlockSize));
|
||||
MESOSPHERE_ABORT_UNLESS(l2_entry->IsCompatibleWithAttribute(attr_before, false));
|
||||
|
||||
/* Invalidate the existing L2 block. */
|
||||
*static_cast<PageTableEntry *>(l2_entry) = InvalidPageTableEntry;
|
||||
cpu::DataSynchronizationBarrierInnerShareable();
|
||||
cpu::InvalidateEntireTlb();
|
||||
|
||||
/* Create new L2 block. */
|
||||
*l2_entry = L2PageTableEntry(block, attr_after, false);
|
||||
|
||||
virt_addr += L2BlockSize;
|
||||
size -= L2BlockSize;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Not a block, so we must be a table. */
|
||||
MESOSPHERE_ABORT_UNLESS(l2_entry->IsTable());
|
||||
|
||||
/* We must have a mapped l3 entry to reprotect. */
|
||||
L3PageTableEntry *l3_entry = GetL3Entry(l2_entry, virt_addr);
|
||||
MESOSPHERE_ABORT_UNLESS(l3_entry->IsBlock());
|
||||
const KPhysicalAddress block = l3_entry->GetBlock();
|
||||
|
||||
if (l3_entry->IsContiguous()) {
|
||||
/* Ensure that we are allowed to have a contiguous L3 block here. */
|
||||
MESOSPHERE_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), L3ContiguousBlockSize));
|
||||
MESOSPHERE_ABORT_UNLESS(util::IsAligned(GetInteger(block), L3ContiguousBlockSize));
|
||||
MESOSPHERE_ABORT_UNLESS(util::IsAligned(size, L3ContiguousBlockSize));
|
||||
|
||||
/* Invalidate the existing contiguous L3 block. */
|
||||
for (size_t i = 0; i < L3ContiguousBlockSize / L3BlockSize; i++) {
|
||||
/* Ensure that the entry is valid. */
|
||||
MESOSPHERE_ABORT_UNLESS(l3_entry[i].IsCompatibleWithAttribute(attr_before, true));
|
||||
static_cast<PageTableEntry *>(l3_entry)[i] = InvalidPageTableEntry;
|
||||
}
|
||||
cpu::DataSynchronizationBarrierInnerShareable();
|
||||
cpu::InvalidateEntireTlb();
|
||||
|
||||
/* Create a new contiguous L3 block. */
|
||||
for (size_t i = 0; i < L3ContiguousBlockSize / L3BlockSize; i++) {
|
||||
l3_entry[i] = L3PageTableEntry(block + L3BlockSize * i, attr_after, true);
|
||||
}
|
||||
|
||||
virt_addr += L3ContiguousBlockSize;
|
||||
size -= L3ContiguousBlockSize;
|
||||
} else {
|
||||
/* Ensure that we are allowed to have an L3 block here. */
|
||||
MESOSPHERE_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), L3BlockSize));
|
||||
MESOSPHERE_ABORT_UNLESS(util::IsAligned(GetInteger(block), L3BlockSize));
|
||||
MESOSPHERE_ABORT_UNLESS(util::IsAligned(size, L3BlockSize));
|
||||
MESOSPHERE_ABORT_UNLESS(l3_entry->IsCompatibleWithAttribute(attr_before, false));
|
||||
|
||||
/* Invalidate the existing L3 block. */
|
||||
*static_cast<PageTableEntry *>(l3_entry) = InvalidPageTableEntry;
|
||||
cpu::DataSynchronizationBarrierInnerShareable();
|
||||
cpu::InvalidateEntireTlb();
|
||||
|
||||
/* Create new L3 block. */
|
||||
*l3_entry = L3PageTableEntry(block, attr_after, false);
|
||||
|
||||
virt_addr += L3BlockSize;
|
||||
size -= L3BlockSize;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure data consistency after we complete reprotection. */
|
||||
cpu::DataSynchronizationBarrierInnerShareable();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include "kern_cpu_system_registers.hpp"
|
||||
|
||||
namespace ams::kern::arm64::cpu {
|
||||
|
||||
/* Helpers for managing memory state. */
|
||||
ALWAYS_INLINE void DataSynchronizationBarrier() {
|
||||
__asm__ __volatile__("dsb sy" ::: "memory");
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void DataSynchronizationBarrierInnerShareable() {
|
||||
__asm__ __volatile__("dsb ish" ::: "memory");
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void DataMemoryBarrier() {
|
||||
__asm__ __volatile__("dmb sy" ::: "memory");
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void InstructionMemoryBarrier() {
|
||||
__asm__ __volatile__("isb" ::: "memory");
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void EnsureInstructionConsistency() {
|
||||
DataSynchronizationBarrier();
|
||||
InstructionMemoryBarrier();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void InvalidateEntireInstructionCache() {
|
||||
__asm__ __volatile__("ic iallu" ::: "memory");
|
||||
EnsureInstructionConsistency();
|
||||
}
|
||||
|
||||
/* Cache management helpers. */
|
||||
void FlushEntireDataCacheShared();
|
||||
void FlushEntireDataCacheLocal();
|
||||
|
||||
ALWAYS_INLINE void InvalidateEntireTlb() {
|
||||
__asm__ __volatile__("tlbi vmalle1is" ::: "memory");
|
||||
EnsureInstructionConsistency();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
|
||||
namespace ams::kern::arm64::cpu {
|
||||
|
||||
#define MESOSPHERE_CPU_GET_SYSREG(name) \
|
||||
({ \
|
||||
u64 temp_value; \
|
||||
__asm__ __volatile__("mrs %0, " #name "" : "=&r"(temp_value) :: "memory"); \
|
||||
temp_value; \
|
||||
})
|
||||
|
||||
#define MESOSPHERE_CPU_SET_SYSREG(name, value) \
|
||||
({ \
|
||||
__asm__ __volatile__("msr " #name ", %0" :: "r"(value) : "memory", "cc"); \
|
||||
})
|
||||
|
||||
#define MESOSPHERE_CPU_DEFINE_SYSREG_ACCESSORS(name, reg_name) \
|
||||
ALWAYS_INLINE void Set##name(u64 value) { MESOSPHERE_CPU_SET_SYSREG(reg_name, value); } \
|
||||
ALWAYS_INLINE u64 Get##name() { return MESOSPHERE_CPU_GET_SYSREG(reg_name); }
|
||||
|
||||
MESOSPHERE_CPU_DEFINE_SYSREG_ACCESSORS(Ttbr0El1, ttbr0_el1)
|
||||
MESOSPHERE_CPU_DEFINE_SYSREG_ACCESSORS(Ttbr1El1, ttbr1_el1)
|
||||
|
||||
MESOSPHERE_CPU_DEFINE_SYSREG_ACCESSORS(MairEl1, mair_el1)
|
||||
MESOSPHERE_CPU_DEFINE_SYSREG_ACCESSORS(TcrEl1, tcr_el1)
|
||||
|
||||
MESOSPHERE_CPU_DEFINE_SYSREG_ACCESSORS(SctlrEl1, sctlr_el1)
|
||||
|
||||
MESOSPHERE_CPU_DEFINE_SYSREG_ACCESSORS(CpuActlrEl1, s3_1_c15_c2_0)
|
||||
MESOSPHERE_CPU_DEFINE_SYSREG_ACCESSORS(CpuEctlrEl1, s3_1_c15_c2_1)
|
||||
|
||||
MESOSPHERE_CPU_DEFINE_SYSREG_ACCESSORS(CsselrEl1, csselr_el1)
|
||||
|
||||
/* Base class for register accessors. */
|
||||
class GenericRegisterAccessor {
|
||||
private:
|
||||
u64 value;
|
||||
public:
|
||||
ALWAYS_INLINE GenericRegisterAccessor(u64 v) : value(v) { /* ... */ }
|
||||
protected:
|
||||
constexpr ALWAYS_INLINE u64 GetBits(size_t offset, size_t count) const {
|
||||
return (this->value >> offset) & ((1ul << count) - 1);
|
||||
}
|
||||
};
|
||||
|
||||
/* Special code for main id register. */
|
||||
class MainIdRegisterAccessor : public GenericRegisterAccessor {
|
||||
public:
|
||||
enum class Implementer {
|
||||
ArmLimited = 0x41,
|
||||
};
|
||||
enum class PrimaryPartNumber {
|
||||
CortexA53 = 0xD03,
|
||||
CortexA57 = 0xD07,
|
||||
};
|
||||
public:
|
||||
ALWAYS_INLINE MainIdRegisterAccessor() : GenericRegisterAccessor(MESOSPHERE_CPU_GET_SYSREG(midr_el1)) { /* ... */ }
|
||||
public:
|
||||
constexpr ALWAYS_INLINE Implementer GetImplementer() const {
|
||||
return static_cast<Implementer>(this->GetBits(24, 8));
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE u64 GetVariant() const {
|
||||
return this->GetBits(20, 4);
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE u64 GetArchitecture() const {
|
||||
return this->GetBits(16, 4);
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE PrimaryPartNumber GetPrimaryPartNumber() const {
|
||||
return static_cast<PrimaryPartNumber>(this->GetBits(4, 12));
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE u64 GetRevision() const {
|
||||
return this->GetBits(0, 4);
|
||||
}
|
||||
};
|
||||
|
||||
/* Accessors for cache registers. */
|
||||
class CacheLineIdAccessor : public GenericRegisterAccessor {
|
||||
public:
|
||||
ALWAYS_INLINE CacheLineIdAccessor() : GenericRegisterAccessor(MESOSPHERE_CPU_GET_SYSREG(clidr_el1)) { /* ... */ }
|
||||
public:
|
||||
constexpr ALWAYS_INLINE int GetLevelsOfCoherency() const {
|
||||
return static_cast<int>(this->GetBits(24, 3));
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE int GetLevelsOfUnification() const {
|
||||
return static_cast<int>(this->GetBits(21, 3));
|
||||
}
|
||||
|
||||
/* TODO: Other bitfield accessors? */
|
||||
};
|
||||
|
||||
class CacheSizeIdAccessor : public GenericRegisterAccessor {
|
||||
public:
|
||||
ALWAYS_INLINE CacheSizeIdAccessor() : GenericRegisterAccessor(MESOSPHERE_CPU_GET_SYSREG(ccsidr_el1)) { /* ... */ }
|
||||
public:
|
||||
constexpr ALWAYS_INLINE int GetNumberOfSets() const {
|
||||
return static_cast<int>(this->GetBits(13, 15));
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE int GetAssociativity() const {
|
||||
return static_cast<int>(this->GetBits(3, 10));
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE int GetLineSize() const {
|
||||
return static_cast<int>(this->GetBits(0, 3));
|
||||
}
|
||||
|
||||
/* TODO: Other bitfield accessors? */
|
||||
};
|
||||
|
||||
#undef MESOSPHERE_CPU_DEFINE_SYSREG_ACCESSORS
|
||||
#undef MESOSPHERE_CPU_GET_SYSREG
|
||||
#undef MESOSPHERE_CPU_SET_SYSREG
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
class KSystemControl {
|
||||
public:
|
||||
class Init {
|
||||
public:
|
||||
/* Initialization. */
|
||||
static KPhysicalAddress GetKernelPhysicalBaseAddress(uintptr_t base_address);
|
||||
static bool ShouldIncreaseThreadResourceLimit();
|
||||
|
||||
/* Randomness. */
|
||||
static void GenerateRandomBytes(void *dst, size_t size);
|
||||
static u64 GenerateRandomRange(u64 min, u64 max);
|
||||
};
|
||||
public:
|
||||
/* Panic. */
|
||||
static NORETURN void StopSystem();
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
|
||||
#ifdef ATMOSPHERE_ARCH_ARM64
|
||||
#include "kern_init_elf64.hpp"
|
||||
#else
|
||||
#error "Unknown Architecture"
|
||||
#endif
|
||||
|
||||
namespace ams::kern::init::Elf {
|
||||
|
||||
#ifdef ATMOSPHERE_ARCH_ARM64
|
||||
using namespace ams::kern::init::Elf::Elf64;
|
||||
|
||||
enum RelocationType {
|
||||
R_ARCHITECTURE_RELATIVE = 0x403, /* Real name R_AARCH64_RELATIVE */
|
||||
};
|
||||
#else
|
||||
#error "Unknown Architecture"
|
||||
#endif
|
||||
|
||||
/* API to apply relocations or call init array. */
|
||||
void ApplyRelocations(uintptr_t base_address, const Dyn *dynamic);
|
||||
void CallInitArrayFuncs(uintptr_t init_array_start, uintptr_t init_array_end);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
/*
|
||||
From musl include/elf.h
|
||||
|
||||
Copyright © 2005-2014 Rich Felker, et al.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
|
||||
namespace ams::kern::init::Elf::Elf64 {
|
||||
|
||||
/* Type declarations required to perform relocations */
|
||||
using Half = u16;
|
||||
using Word = u32;
|
||||
using Sword = s32;
|
||||
using Xword = u64;
|
||||
using SXword = s64;
|
||||
|
||||
using Addr = u64;
|
||||
using Off = u64;
|
||||
|
||||
class Dyn {
|
||||
private:
|
||||
SXword tag;
|
||||
union {
|
||||
Xword value;
|
||||
Addr ptr;
|
||||
};
|
||||
public:
|
||||
constexpr ALWAYS_INLINE SXword GetTag() const {
|
||||
return this->tag;
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE Xword GetValue() const {
|
||||
return this->value;
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE Addr GetPtr() const {
|
||||
return this->ptr;
|
||||
}
|
||||
};
|
||||
|
||||
class Rel {
|
||||
private:
|
||||
Addr offset;
|
||||
Xword info;
|
||||
public:
|
||||
constexpr ALWAYS_INLINE Addr GetOffset() const {
|
||||
return this->offset;
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE Xword GetSym() const {
|
||||
return this->info >> 32;
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE Xword GetType() const {
|
||||
return this->info & 0xFFFFFFFF;
|
||||
}
|
||||
};
|
||||
|
||||
class Rela {
|
||||
private:
|
||||
Addr offset;
|
||||
Xword info;
|
||||
SXword addend;
|
||||
public:
|
||||
constexpr ALWAYS_INLINE Addr GetOffset() const {
|
||||
return this->offset;
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE Xword GetSym() const {
|
||||
return this->info >> 32;
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE Xword GetType() const {
|
||||
return this->info & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE SXword GetAddend() const {
|
||||
return this->addend;
|
||||
}
|
||||
};
|
||||
|
||||
enum DynamicTag {
|
||||
DT_NULL = 0,
|
||||
DT_RELA = 7,
|
||||
DT_RELAENT = 9,
|
||||
DT_REL = 17,
|
||||
DT_RELENT = 19,
|
||||
|
||||
DT_RELACOUNT = 0x6ffffff9,
|
||||
DT_RELCOUNT = 0x6ffffffa
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
|
||||
namespace ams::kern::init {
|
||||
|
||||
struct KernelLayout {
|
||||
u32 rx_offset;
|
||||
u32 rx_end_offset;
|
||||
u32 ro_offset;
|
||||
u32 ro_end_offset;
|
||||
u32 rw_offset;
|
||||
u32 rw_end_offset;
|
||||
u32 bss_offset;
|
||||
u32 bss_end_offset;
|
||||
u32 ini_end_offset;
|
||||
u32 dynamic_offset;
|
||||
u32 init_array_offset;
|
||||
u32 init_array_end_offset;
|
||||
};
|
||||
static_assert(std::is_pod<KernelLayout>::value);
|
||||
static_assert(sizeof(KernelLayout) == 0x30);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifdef ATMOSPHERE_ARCH_ARM64
|
||||
#include "../arch/arm64/init/kern_k_init_page_table.hpp"
|
||||
#else
|
||||
#error "Unknown architecture for KInitialPageTable"
|
||||
#endif
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include "kern_panic.hpp"
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
constexpr u32 InitialProcessBinaryMagic = util::FourCC<'I','N','I','1'>::Code;
|
||||
constexpr size_t InitialProcessBinarySizeMax = 0xC00000;
|
||||
|
||||
struct InitialProcessBinaryHeader {
|
||||
u32 magic;
|
||||
u32 size;
|
||||
u32 num_processes;
|
||||
u32 reserved;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
#ifndef MESOSPHERE_DISABLE_TYPED_ADDRESSES
|
||||
|
||||
template<bool Virtual, typename T>
|
||||
class KTypedAddress {
|
||||
private:
|
||||
uintptr_t address;
|
||||
public:
|
||||
/* Constructors. */
|
||||
constexpr ALWAYS_INLINE KTypedAddress() : address(0) { /* ... */ }
|
||||
constexpr ALWAYS_INLINE KTypedAddress(uintptr_t a) : address(a) { /* ... */ }
|
||||
template<typename U>
|
||||
constexpr ALWAYS_INLINE explicit KTypedAddress(U *ptr) : address(reinterpret_cast<uintptr_t>(ptr)) { /* ... */ }
|
||||
|
||||
/* Assignment operator. */
|
||||
constexpr ALWAYS_INLINE KTypedAddress operator=(KTypedAddress rhs) {
|
||||
this->address = rhs.address;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* Arithmetic operators. */
|
||||
template<typename I>
|
||||
constexpr ALWAYS_INLINE KTypedAddress operator+(I rhs) const {
|
||||
static_assert(std::is_integral<I>::value);
|
||||
return this->address + rhs;
|
||||
}
|
||||
|
||||
template<typename I>
|
||||
constexpr ALWAYS_INLINE KTypedAddress operator-(I rhs) const {
|
||||
static_assert(std::is_integral<I>::value);
|
||||
return this->address - rhs;
|
||||
}
|
||||
|
||||
template<typename I>
|
||||
constexpr ALWAYS_INLINE KTypedAddress operator+=(I rhs) {
|
||||
static_assert(std::is_integral<I>::value);
|
||||
this->address += rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename I>
|
||||
constexpr ALWAYS_INLINE KTypedAddress operator-=(I rhs) {
|
||||
static_assert(std::is_integral<I>::value);
|
||||
this->address -= rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* Logical operators. */
|
||||
constexpr ALWAYS_INLINE uintptr_t operator&(uintptr_t mask) const {
|
||||
return this->address & mask;
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE uintptr_t operator|(uintptr_t mask) const {
|
||||
return this->address | mask;
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE uintptr_t operator<<(int shift) const {
|
||||
return this->address << shift;
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE uintptr_t operator>>(int shift) const {
|
||||
return this->address >> shift;
|
||||
}
|
||||
|
||||
/* Comparison operators. */
|
||||
constexpr ALWAYS_INLINE bool operator==(KTypedAddress rhs) const {
|
||||
return this->address == rhs.address;
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE bool operator!=(KTypedAddress rhs) const {
|
||||
return this->address != rhs.address;
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE bool operator<(KTypedAddress rhs) const {
|
||||
return this->address < rhs.address;
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE bool operator<=(KTypedAddress rhs) const {
|
||||
return this->address <= rhs.address;
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE bool operator>(KTypedAddress rhs) const {
|
||||
return this->address > rhs.address;
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE bool operator>=(KTypedAddress rhs) const {
|
||||
return this->address >= rhs.address;
|
||||
}
|
||||
|
||||
/* For convenience, also define comparison operators versus uintptr_t. */
|
||||
constexpr ALWAYS_INLINE bool operator==(uintptr_t rhs) const {
|
||||
return this->address == rhs;
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE bool operator!=(uintptr_t rhs) const {
|
||||
return this->address != rhs;
|
||||
}
|
||||
|
||||
/* TODO: <, <=, >, >= against uintptr_t? would need to be declared outside of class. Maybe worth it. */
|
||||
|
||||
/* Allow getting the address explicitly, for use in accessors. */
|
||||
constexpr ALWAYS_INLINE uintptr_t GetValue() const {
|
||||
return this->address;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct KPhysicalAddressTag{};
|
||||
struct KVirtualAddressTag{};
|
||||
struct KProcessAddressTag{};
|
||||
|
||||
using KPhysicalAddress = KTypedAddress<false, KPhysicalAddressTag>;
|
||||
using KVirtualAddress = KTypedAddress<true, KVirtualAddressTag>;
|
||||
using KProcessAddress = KTypedAddress<true, KProcessAddressTag>;
|
||||
|
||||
/* Define accessors. */
|
||||
template<bool Virtual, typename T>
|
||||
constexpr ALWAYS_INLINE uintptr_t GetInteger(KTypedAddress<Virtual, T> address) {
|
||||
return address.GetValue();
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
constexpr ALWAYS_INLINE T *GetPointer(KTypedAddress<true, U> address) {
|
||||
return CONST_FOLD(reinterpret_cast<T *>(address.GetValue()));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr ALWAYS_INLINE void *GetVoidPointer(KTypedAddress<true, T> address) {
|
||||
return CONST_FOLD(reinterpret_cast<void *>(address.GetValue()));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* Plausibly, we may not want compiler overhead from using strongly typed addresses. */
|
||||
/* In this case, we should just use uintptr_t. */
|
||||
using KPhysicalAddress = uintptr_t;
|
||||
using KVirtualAddress = uintptr_t;
|
||||
using KProcessAddress = uintptr_t;
|
||||
|
||||
/* Define accessors. */
|
||||
constexpr ALWAYS_INLINE uintptr_t GetInteger(uintptr_t address) {
|
||||
return address;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr ALWAYS_INLINE T *GetPointer(uintptr_t address) {
|
||||
return CONST_FOLD(reinterpret_cast<T *>(address));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr ALWAYS_INLINE void *GetVoidPointer(uintptr_t address) {
|
||||
return CONST_FOLD(reinterpret_cast<void *>(address));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
constexpr inline T Null = [] {
|
||||
if constexpr (std::is_same<T, uintptr_t>::value) {
|
||||
return 0;
|
||||
} else {
|
||||
static_assert(std::is_same<T, KPhysicalAddress>::value ||
|
||||
std::is_same<T, KVirtualAddress>::value ||
|
||||
std::is_same<T, KProcessAddress>::value);
|
||||
return T(0);
|
||||
}
|
||||
}();
|
||||
|
||||
/* Basic type validations. */
|
||||
static_assert(sizeof(KPhysicalAddress) == sizeof(uintptr_t));
|
||||
static_assert(sizeof(KVirtualAddress) == sizeof(uintptr_t));
|
||||
static_assert(sizeof(KProcessAddress) == sizeof(uintptr_t));
|
||||
|
||||
static_assert(std::is_trivially_destructible<KPhysicalAddress>::value);
|
||||
static_assert(std::is_trivially_destructible<KVirtualAddress>::value);
|
||||
static_assert(std::is_trivially_destructible<KProcessAddress>::value);
|
||||
|
||||
static_assert(Null<uintptr_t> == 0);
|
||||
static_assert(Null<KPhysicalAddress> == Null<uintptr_t>);
|
||||
static_assert(Null<KVirtualAddress> == Null<uintptr_t>);
|
||||
static_assert(Null<KProcessAddress> == Null<uintptr_t>);
|
||||
|
||||
/* Arithmetic validations. */
|
||||
static_assert(KPhysicalAddress(10) + 5 == KPhysicalAddress(15));
|
||||
static_assert(KPhysicalAddress(10) - 5 == KPhysicalAddress(5));
|
||||
static_assert([]{ KPhysicalAddress v(10); v += 5; return v; }() == KPhysicalAddress(15));
|
||||
static_assert([]{ KPhysicalAddress v(10); v -= 5; return v; }() == KPhysicalAddress(5));
|
||||
|
||||
/* Logical validations. */
|
||||
static_assert((KPhysicalAddress(0b11111111) >> 1) == 0b01111111);
|
||||
static_assert((KPhysicalAddress(0b10101010) >> 1) == 0b01010101);
|
||||
static_assert((KPhysicalAddress(0b11111111) << 1) == 0b111111110);
|
||||
static_assert((KPhysicalAddress(0b01010101) << 1) == 0b10101010);
|
||||
static_assert((KPhysicalAddress(0b11111111) & 0b01010101) == 0b01010101);
|
||||
static_assert((KPhysicalAddress(0b11111111) & 0b10101010) == 0b10101010);
|
||||
static_assert((KPhysicalAddress(0b01010101) & 0b10101010) == 0b00000000);
|
||||
static_assert((KPhysicalAddress(0b00000000) | 0b01010101) == 0b01010101);
|
||||
static_assert((KPhysicalAddress(0b11111111) | 0b01010101) == 0b11111111);
|
||||
static_assert((KPhysicalAddress(0b10101010) | 0b01010101) == 0b11111111);
|
||||
|
||||
/* Comparisons. */
|
||||
static_assert(KPhysicalAddress(0) == KPhysicalAddress(0));
|
||||
static_assert(KPhysicalAddress(0) != KPhysicalAddress(1));
|
||||
static_assert(KPhysicalAddress(0) < KPhysicalAddress(1));
|
||||
static_assert(KPhysicalAddress(0) <= KPhysicalAddress(1));
|
||||
static_assert(KPhysicalAddress(1) > KPhysicalAddress(0));
|
||||
static_assert(KPhysicalAddress(1) >= KPhysicalAddress(0));
|
||||
|
||||
static_assert(!(KPhysicalAddress(0) == KPhysicalAddress(1)));
|
||||
static_assert(!(KPhysicalAddress(0) != KPhysicalAddress(0)));
|
||||
static_assert(!(KPhysicalAddress(1) < KPhysicalAddress(0)));
|
||||
static_assert(!(KPhysicalAddress(1) <= KPhysicalAddress(0)));
|
||||
static_assert(!(KPhysicalAddress(0) > KPhysicalAddress(1)));
|
||||
static_assert(!(KPhysicalAddress(0) >= KPhysicalAddress(1)));
|
||||
|
||||
/* Accessors. */
|
||||
static_assert(15 == GetInteger(KPhysicalAddress(15)));
|
||||
static_assert(0 == GetInteger(Null<KPhysicalAddress>));
|
||||
/* TODO: reinterpret_cast<> not valid in a constant expression, can't test get pointers. */
|
||||
|
||||
}
|
||||
53
libraries/libmesosphere/include/mesosphere/kern_panic.hpp
Normal file
53
libraries/libmesosphere/include/mesosphere/kern_panic.hpp
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
NORETURN void Panic(const char *file, int line, const char *format, ...);
|
||||
NORETURN void Panic();
|
||||
|
||||
}
|
||||
|
||||
#ifdef MESOSPHERE_ENABLE_DEBUG_PRINT
|
||||
#define MESOSPHERE_PANIC(...) ams::kern::Panic(__FILE__, __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
#define MESOSPHERE_PANIC(...) ams::kern::Panic()
|
||||
#endif
|
||||
|
||||
#ifdef MESOSPHERE_ENABLE_ASSERTIONS
|
||||
#define MESOSPHERE_ASSERT_IMPL(expr, ...) \
|
||||
({ \
|
||||
if (AMS_UNLIKELY(!(expr))) { \
|
||||
MESOSPHERE_PANIC(__VA_ARGS__); \
|
||||
} \
|
||||
})
|
||||
#else
|
||||
#define MESOSPHERE_ASSERT_IMPL(expr, ...) do { } while (0)
|
||||
#endif
|
||||
|
||||
#define MESOSPHERE_ASSERT(expr) MESOSPHERE_ASSERT_IMPL(expr, "Assertion failed: %s", #expr)
|
||||
#define MESOSPHERE_R_ASSERT(expr) MESOSPHERE_ASSERT_IMPL(R_SUCCEEDED(expr), "Result assertion failed: %s", #expr)
|
||||
|
||||
#define MESOSPHERE_ABORT() MESOSPHERE_PANIC("Abort()");
|
||||
|
||||
#define MESOSPHERE_ABORT_UNLESS(expr) \
|
||||
({ \
|
||||
if (AMS_UNLIKELY(!(expr))) { \
|
||||
MESOSPHERE_PANIC("Abort(): %s", #expr); \
|
||||
} \
|
||||
})
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifdef ATMOSPHERE_ARCH_ARM64
|
||||
#include "arch/arm64/kern_cpu.hpp"
|
||||
|
||||
namespace ams::kern::cpu {
|
||||
|
||||
using namespace ams::kern::arm64::cpu;
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
#error "Unknown architecture for CPU"
|
||||
#endif
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include "kern_panic.hpp"
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
/* TODO: Actually select between architecture-specific interrupt code. */
|
||||
|
||||
|
||||
/* Enable or disable interrupts for the lifetime of an object. */
|
||||
class KScopedInterruptDisable {
|
||||
NON_COPYABLE(KScopedInterruptDisable);
|
||||
NON_MOVEABLE(KScopedInterruptDisable);
|
||||
public:
|
||||
KScopedInterruptDisable();
|
||||
~KScopedInterruptDisable();
|
||||
};
|
||||
|
||||
class KScopedInterruptEnable {
|
||||
NON_COPYABLE(KScopedInterruptEnable);
|
||||
NON_MOVEABLE(KScopedInterruptEnable);
|
||||
public:
|
||||
KScopedInterruptEnable();
|
||||
~KScopedInterruptEnable();
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifdef ATMOSPHERE_BOARD_NINTENDO_SWITCH
|
||||
#include "board/nintendo/switch/kern_k_system_control.hpp"
|
||||
#else
|
||||
#error "Unknown board for KSystemControl"
|
||||
#endif
|
||||
69
libraries/libmesosphere/source/arch/arm64/kern_cpu.cpp
Normal file
69
libraries/libmesosphere/source/arch/arm64/kern_cpu.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||
*
|
||||
* 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 <mesosphere.hpp>
|
||||
|
||||
namespace ams::kern::arm64::cpu {
|
||||
|
||||
namespace {
|
||||
|
||||
void FlushEntireDataCacheImpl(int level) {
|
||||
/* Used in multiple locations. */
|
||||
const u64 level_sel_value = static_cast<u64>(level << 1);
|
||||
|
||||
/* Set selection register. */
|
||||
cpu::SetCsselrEl1(level_sel_value);
|
||||
cpu::InstructionMemoryBarrier();
|
||||
|
||||
/* Get cache size id info. */
|
||||
CacheSizeIdAccessor ccsidr_el1;
|
||||
const int num_sets = ccsidr_el1.GetNumberOfSets();
|
||||
const int num_ways = ccsidr_el1.GetAssociativity();
|
||||
const int line_size = ccsidr_el1.GetLineSize();
|
||||
|
||||
const u64 way_shift = static_cast<u64>(__builtin_clz(num_ways));
|
||||
const u64 set_shift = static_cast<u64>(line_size + 4);
|
||||
|
||||
for (int way = 0; way <= num_ways; way++) {
|
||||
for (int set = 0; set <= num_sets; set++) {
|
||||
const u64 way_value = static_cast<u64>(way) << way_shift;
|
||||
const u64 set_value = static_cast<u64>(set) << set_shift;
|
||||
const u64 cisw_value = way_value | set_value | level_sel_value;
|
||||
__asm__ __volatile__("dc cisw, %0" ::"r"(cisw_value) : "memory");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void FlushEntireDataCacheShared() {
|
||||
CacheLineIdAccessor clidr_el1;
|
||||
const int levels_of_coherency = clidr_el1.GetLevelsOfCoherency();
|
||||
const int levels_of_unification = clidr_el1.GetLevelsOfUnification();
|
||||
|
||||
for (int level = levels_of_coherency; level >= levels_of_unification; level--) {
|
||||
FlushEntireDataCacheImpl(level);
|
||||
}
|
||||
}
|
||||
|
||||
void FlushEntireDataCacheLocal() {
|
||||
CacheLineIdAccessor clidr_el1;
|
||||
const int levels_of_unification = clidr_el1.GetLevelsOfUnification();
|
||||
|
||||
for (int level = levels_of_unification - 1; level >= 0; level--) {
|
||||
FlushEntireDataCacheImpl(level);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||
*
|
||||
* 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 <mesosphere.hpp>
|
||||
#include "kern_secure_monitor.hpp"
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
namespace {
|
||||
|
||||
ALWAYS_INLINE size_t GetRealMemorySizeForInit() {
|
||||
/* TODO: Move this into a header for the MC in general. */
|
||||
constexpr u32 MemoryControllerConfigurationRegister = 0x70019050;
|
||||
u32 config_value;
|
||||
MESOSPHERE_ABORT_UNLESS(smc::init::ReadWriteRegister(&config_value, MemoryControllerConfigurationRegister, 0, 0));
|
||||
return static_cast<size_t>(config_value & 0x3FFF) << 20;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE util::BitPack32 GetKernelConfigurationForInit() {
|
||||
u64 value = 0;
|
||||
smc::init::GetConfig(&value, 1, smc::ConfigItem::KernelConfiguration);
|
||||
return util::BitPack32{static_cast<u32>(value)};
|
||||
}
|
||||
|
||||
ALWAYS_INLINE u64 GenerateRandomU64ForInit() {
|
||||
u64 value;
|
||||
smc::init::GenerateRandomBytes(&value, sizeof(value));
|
||||
return value;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE size_t GetIntendedMemorySizeForInit() {
|
||||
switch (GetKernelConfigurationForInit().Get<smc::KernelConfiguration::MemorySize>()) {
|
||||
case smc::MemorySize_4GB:
|
||||
default: /* All invalid modes should go to 4GB. */
|
||||
return 4_GB;
|
||||
case smc::MemorySize_6GB:
|
||||
return 6_GB;
|
||||
case smc::MemorySize_8GB:
|
||||
return 8_GB;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Initialization. */
|
||||
KPhysicalAddress KSystemControl::Init::GetKernelPhysicalBaseAddress(uintptr_t base_address) {
|
||||
const size_t real_dram_size = GetRealMemorySizeForInit();
|
||||
const size_t intended_dram_size = GetIntendedMemorySizeForInit();
|
||||
if (intended_dram_size * 2 < real_dram_size) {
|
||||
return base_address;
|
||||
} else {
|
||||
return base_address + ((real_dram_size - intended_dram_size) / 2);
|
||||
}
|
||||
}
|
||||
|
||||
bool KSystemControl::Init::ShouldIncreaseThreadResourceLimit() {
|
||||
return GetKernelConfigurationForInit().Get<smc::KernelConfiguration::IncreaseThreadResourceLimit>();
|
||||
}
|
||||
|
||||
/* Randomness for Initialization. */
|
||||
void KSystemControl::Init::GenerateRandomBytes(void *dst, size_t size) {
|
||||
MESOSPHERE_ABORT_UNLESS(size <= 0x38);
|
||||
smc::init::GenerateRandomBytes(dst, size);
|
||||
}
|
||||
|
||||
u64 KSystemControl::Init::GenerateRandomRange(u64 min, u64 max) {
|
||||
const u64 range_size = ((max + 1) - min);
|
||||
const u64 effective_max = (std::numeric_limits<u64>::max() / range_size) * range_size;
|
||||
while (true) {
|
||||
if (const u64 rnd = GenerateRandomU64ForInit(); rnd < effective_max) {
|
||||
return min + (rnd % range_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KSystemControl::StopSystem() {
|
||||
/* Display a panic screen via exosphere. */
|
||||
smc::Panic(0xF00);
|
||||
while (true) { /* ... */ }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||
*
|
||||
* 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 <mesosphere.hpp>
|
||||
#include "kern_secure_monitor.hpp"
|
||||
|
||||
namespace ams::kern::smc {
|
||||
|
||||
namespace {
|
||||
|
||||
struct SecureMonitorArguments {
|
||||
u64 x[8];
|
||||
};
|
||||
|
||||
enum FunctionId : u32 {
|
||||
FunctionId_CpuSuspend = 0xC4000001,
|
||||
FunctionId_CpuOff = 0x84000002,
|
||||
FunctionId_CpuOn = 0xC4000003,
|
||||
FunctionId_GetConfig = 0xC3000004,
|
||||
FunctionId_GenerateRandomBytes = 0xC3000005,
|
||||
FunctionId_Panic = 0xC3000006,
|
||||
FunctionId_ConfigureCarveout = 0xC3000007,
|
||||
FunctionId_ReadWriteRegister = 0xC3000008,
|
||||
};
|
||||
|
||||
void CallPrivilegedSecureMonitorFunction(SecureMonitorArguments &args) {
|
||||
/* Load arguments into registers. */
|
||||
register u64 x0 asm("x0") = args.x[0];
|
||||
register u64 x1 asm("x1") = args.x[1];
|
||||
register u64 x2 asm("x2") = args.x[2];
|
||||
register u64 x3 asm("x3") = args.x[3];
|
||||
register u64 x4 asm("x4") = args.x[4];
|
||||
register u64 x5 asm("x5") = args.x[5];
|
||||
register u64 x6 asm("x6") = args.x[6];
|
||||
register u64 x7 asm("x7") = args.x[7];
|
||||
|
||||
/* Actually make the call. */
|
||||
{
|
||||
/* Disable interrupts while making the call. */
|
||||
KScopedInterruptDisable intr_disable;
|
||||
__asm__ __volatile__("smc #1"
|
||||
: "+r"(x0), "+r"(x1), "+r"(x2), "+r"(x3), "+r"(x4), "+r"(x5), "+r"(x6), "+r"(x7)
|
||||
:
|
||||
: "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "cc", "memory"
|
||||
);
|
||||
/* TODO: Restore X18 */
|
||||
}
|
||||
|
||||
/* Store arguments to output. */
|
||||
args.x[0] = x0;
|
||||
args.x[1] = x1;
|
||||
args.x[2] = x2;
|
||||
args.x[3] = x3;
|
||||
args.x[4] = x4;
|
||||
args.x[5] = x5;
|
||||
args.x[6] = x6;
|
||||
args.x[7] = x7;
|
||||
}
|
||||
|
||||
void CallPrivilegedSecureMonitorFunctionForInit(SecureMonitorArguments &args) {
|
||||
/* Load arguments into registers. */
|
||||
register u64 x0 asm("x0") = args.x[0];
|
||||
register u64 x1 asm("x1") = args.x[1];
|
||||
register u64 x2 asm("x2") = args.x[2];
|
||||
register u64 x3 asm("x3") = args.x[3];
|
||||
register u64 x4 asm("x4") = args.x[4];
|
||||
register u64 x5 asm("x5") = args.x[5];
|
||||
register u64 x6 asm("x6") = args.x[6];
|
||||
register u64 x7 asm("x7") = args.x[7];
|
||||
|
||||
/* Actually make the call. */
|
||||
__asm__ __volatile__("smc #1"
|
||||
: "+r"(x0), "+r"(x1), "+r"(x2), "+r"(x3), "+r"(x4), "+r"(x5), "+r"(x6), "+r"(x7)
|
||||
:
|
||||
: "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "cc", "memory"
|
||||
);
|
||||
|
||||
/* Store arguments to output. */
|
||||
args.x[0] = x0;
|
||||
args.x[1] = x1;
|
||||
args.x[2] = x2;
|
||||
args.x[3] = x3;
|
||||
args.x[4] = x4;
|
||||
args.x[5] = x5;
|
||||
args.x[6] = x6;
|
||||
args.x[7] = x7;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* SMC functionality needed for init. */
|
||||
namespace init {
|
||||
|
||||
void GetConfig(u64 *out, size_t num_qwords, ConfigItem config_item) {
|
||||
SecureMonitorArguments args = { FunctionId_GetConfig, static_cast<u32>(config_item) };
|
||||
CallPrivilegedSecureMonitorFunctionForInit(args);
|
||||
MESOSPHERE_ABORT_UNLESS((static_cast<SmcResult>(args.x[0]) == SmcResult::Success));
|
||||
for (size_t i = 0; i < num_qwords && i < 7; i++) {
|
||||
out[i] = args.x[1 + i];
|
||||
}
|
||||
}
|
||||
|
||||
void GenerateRandomBytes(void *dst, size_t size) {
|
||||
/* Call SmcGenerateRandomBytes() */
|
||||
/* TODO: Lock this to ensure only one core calls at once. */
|
||||
SecureMonitorArguments args = { FunctionId_GenerateRandomBytes, size };
|
||||
MESOSPHERE_ABORT_UNLESS(size <= sizeof(args) - sizeof(args.x[0]));
|
||||
CallPrivilegedSecureMonitorFunctionForInit(args);
|
||||
MESOSPHERE_ABORT_UNLESS((static_cast<SmcResult>(args.x[0]) == SmcResult::Success));
|
||||
|
||||
/* Copy output. */
|
||||
std::memcpy(dst, &args.x[1], size);
|
||||
}
|
||||
|
||||
bool ReadWriteRegister(u32 *out, u64 address, u32 mask, u32 value) {
|
||||
SecureMonitorArguments args = { FunctionId_ReadWriteRegister, address, mask, value };
|
||||
CallPrivilegedSecureMonitorFunctionForInit(args);
|
||||
*out = args.x[1];
|
||||
return static_cast<SmcResult>(args.x[0]) == SmcResult::Success;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void NORETURN Panic(u32 color) {
|
||||
SecureMonitorArguments args = { FunctionId_Panic, color };
|
||||
CallPrivilegedSecureMonitorFunction(args);
|
||||
while (true) { /* ... */ }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <mesosphere.hpp>
|
||||
|
||||
namespace ams::kern::smc {
|
||||
|
||||
/* Types. */
|
||||
enum MemorySize {
|
||||
MemorySize_4GB = 0,
|
||||
MemorySize_6GB = 1,
|
||||
MemorySize_8GB = 2,
|
||||
};
|
||||
|
||||
enum class ConfigItem : u32 {
|
||||
/* Standard config items. */
|
||||
DisableProgramVerification = 1,
|
||||
DramId = 2,
|
||||
SecurityEngineIrqNumber = 3,
|
||||
Version = 4,
|
||||
HardwareType = 5,
|
||||
IsRetail = 6,
|
||||
IsRecoveryBoot = 7,
|
||||
DeviceId = 8,
|
||||
BootReason = 9,
|
||||
MemoryMode = 10,
|
||||
IsDebugMode = 11,
|
||||
KernelConfiguration = 12,
|
||||
IsChargerHiZModeEnabled = 13,
|
||||
IsQuest = 14,
|
||||
RegulatorType = 15,
|
||||
DeviceUniqueKeyGeneration = 16,
|
||||
Package2Hash = 17,
|
||||
|
||||
/* Extension config items for exosphere. */
|
||||
ExosphereApiVersion = 65000,
|
||||
ExosphereNeedsReboot = 65001,
|
||||
ExosphereNeedsShutdown = 65002,
|
||||
ExosphereGitCommitHash = 65003,
|
||||
ExosphereHasRcmBugPatch = 65004,
|
||||
};
|
||||
|
||||
enum class SmcResult {
|
||||
Success = 0,
|
||||
NotImplemented = 1,
|
||||
InvalidArgument = 2,
|
||||
InProgress = 3,
|
||||
NoAsyncOperation = 4,
|
||||
InvalidAsyncOperation = 5,
|
||||
NotPermitted = 6,
|
||||
};
|
||||
|
||||
struct KernelConfiguration {
|
||||
using DebugFillMemory = util::BitPack32::Field<0, 1, bool>;
|
||||
using EnableUserExceptionHandlers = util::BitPack32::Field<DebugFillMemory::Next, 1, bool>;
|
||||
using EnableUserPmuAccess = util::BitPack32::Field<EnableUserExceptionHandlers::Next, 1, bool>;
|
||||
using IncreaseThreadResourceLimit = util::BitPack32::Field<EnableUserPmuAccess::Next, 1, bool>;
|
||||
using Reserved4 = util::BitPack32::Field<IncreaseThreadResourceLimit::Next, 4, u32>;
|
||||
using UseSecureMonitorPanicCall = util::BitPack32::Field<Reserved4::Next, 1, bool>;
|
||||
using Reserved9 = util::BitPack32::Field<UseSecureMonitorPanicCall::Next, 7, u32>;
|
||||
using MemorySize = util::BitPack32::Field<Reserved9::Next, 2, smc::MemorySize>;
|
||||
};
|
||||
|
||||
/* TODO: Rest of Secure Monitor API. */
|
||||
void NORETURN Panic(u32 color);
|
||||
|
||||
namespace init {
|
||||
|
||||
void GetConfig(u64 *out, size_t num_qwords, ConfigItem config_item);
|
||||
void GenerateRandomBytes(void *dst, size_t size);
|
||||
bool ReadWriteRegister(u32 *out, u64 address, u32 mask, u32 value);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
84
libraries/libmesosphere/source/init/kern_init_elf.cpp
Normal file
84
libraries/libmesosphere/source/init/kern_init_elf.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||
*
|
||||
* 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 <mesosphere.hpp>
|
||||
|
||||
namespace ams::kern::init::Elf {
|
||||
|
||||
/* API to apply relocations or call init array. */
|
||||
void ApplyRelocations(uintptr_t base_address, const Dyn *dynamic) {
|
||||
uintptr_t dyn_rel = 0;
|
||||
uintptr_t dyn_rela = 0;
|
||||
uintptr_t rel_count = 0;
|
||||
uintptr_t rela_count = 0;
|
||||
uintptr_t rel_ent = 0;
|
||||
uintptr_t rela_ent = 0;
|
||||
|
||||
/* Iterate over all tags, identifying important extents. */
|
||||
for (const Dyn *cur_entry = dynamic; cur_entry->GetTag() != DT_NULL; cur_entry++) {
|
||||
switch (cur_entry->GetTag()) {
|
||||
case DT_REL:
|
||||
dyn_rel = base_address + cur_entry->GetPtr();
|
||||
break;
|
||||
case DT_RELA:
|
||||
dyn_rela = base_address + cur_entry->GetPtr();
|
||||
break;
|
||||
case DT_RELENT:
|
||||
rel_ent = cur_entry->GetValue();
|
||||
break;
|
||||
case DT_RELAENT:
|
||||
rela_ent = cur_entry->GetValue();
|
||||
break;
|
||||
case DT_RELCOUNT:
|
||||
rel_count = cur_entry->GetValue();
|
||||
break;
|
||||
case DT_RELACOUNT:
|
||||
rela_count = cur_entry->GetValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Apply all Rel relocations */
|
||||
for (size_t i = 0; i < rel_count; i++) {
|
||||
const auto &rel = *reinterpret_cast<const Elf::Rel *>(dyn_rel + rel_ent * i);
|
||||
|
||||
/* Only allow architecture-specific relocations. */
|
||||
while (rel.GetType() != R_ARCHITECTURE_RELATIVE) { /* ... */ }
|
||||
|
||||
/* Apply the relocation. */
|
||||
Elf::Addr *target_address = reinterpret_cast<Elf::Addr *>(base_address + rel.GetOffset());
|
||||
*target_address += base_address;
|
||||
}
|
||||
|
||||
/* Apply all Rela relocations. */
|
||||
for (size_t i = 0; i < rela_count; i++) {
|
||||
const auto &rela = *reinterpret_cast<const Elf::Rela *>(dyn_rela + rela_ent * i);
|
||||
|
||||
/* Only allow architecture-specific relocations. */
|
||||
while (rela.GetType() != R_ARCHITECTURE_RELATIVE) { /* ... */ }
|
||||
|
||||
/* Apply the relocation. */
|
||||
Elf::Addr *target_address = reinterpret_cast<Elf::Addr *>(base_address + rela.GetOffset());
|
||||
*target_address = base_address + rela.GetAddend();
|
||||
}
|
||||
}
|
||||
|
||||
void CallInitArrayFuncs(uintptr_t init_array_start, uintptr_t init_array_end) {
|
||||
for (uintptr_t cur_entry = init_array_start; cur_entry < init_array_end; cur_entry += sizeof(void *)) {
|
||||
(*(void (**)())(cur_entry))();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
36
libraries/libmesosphere/source/kern_k_scoped_interrupt.cpp
Normal file
36
libraries/libmesosphere/source/kern_k_scoped_interrupt.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||
*
|
||||
* 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 <mesosphere.hpp>
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
WEAK_SYMBOL KScopedInterruptDisable::KScopedInterruptDisable() {
|
||||
/* TODO: Disable interrupts. */
|
||||
}
|
||||
|
||||
WEAK_SYMBOL KScopedInterruptDisable::~KScopedInterruptDisable() {
|
||||
/* TODO: un-disable interrupts. */
|
||||
}
|
||||
|
||||
WEAK_SYMBOL KScopedInterruptEnable::KScopedInterruptEnable() {
|
||||
/* TODO: Enable interrupts. */
|
||||
}
|
||||
|
||||
WEAK_SYMBOL KScopedInterruptEnable::~KScopedInterruptEnable() {
|
||||
/* TODO: un-enable interrupts. */
|
||||
}
|
||||
|
||||
}
|
||||
45
libraries/libmesosphere/source/kern_panic.cpp
Normal file
45
libraries/libmesosphere/source/kern_panic.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||
*
|
||||
* 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 <mesosphere.hpp>
|
||||
|
||||
namespace ams::result::impl {
|
||||
|
||||
NORETURN void OnResultAssertion(Result result) {
|
||||
MESOSPHERE_PANIC("OnResultAssertion(2%03d-%04d)", result.GetModule(), result.GetDescription());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
namespace {
|
||||
|
||||
NORETURN void StopSystem() {
|
||||
KSystemControl::StopSystem();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
NORETURN WEAK_SYMBOL void Panic(const char *file, int line, const char *format, ...) {
|
||||
/* TODO: Implement printing, log this information. */
|
||||
StopSystem();
|
||||
}
|
||||
|
||||
NORETURN WEAK_SYMBOL void Panic() {
|
||||
StopSystem();
|
||||
}
|
||||
|
||||
}
|
||||
422
libraries/libmesosphere/source/libc/kern_libc.c
Normal file
422
libraries/libmesosphere/source/libc/kern_libc.c
Normal file
@@ -0,0 +1,422 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||
*
|
||||
* 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 <string.h>
|
||||
#include <stddef.h>
|
||||
#include <limits.h>
|
||||
|
||||
/* Note: copied from newlib */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
FUNCTION
|
||||
<<memmove>>---move possibly overlapping memory
|
||||
INDEX
|
||||
memmove
|
||||
SYNOPSIS
|
||||
#include <string.h>
|
||||
void *memmove(void *<[dst]>, const void *<[src]>, size_t <[length]>);
|
||||
DESCRIPTION
|
||||
This function moves <[length]> characters from the block of
|
||||
memory starting at <<*<[src]>>> to the memory starting at
|
||||
<<*<[dst]>>>. <<memmove>> reproduces the characters correctly
|
||||
at <<*<[dst]>>> even if the two areas overlap.
|
||||
RETURNS
|
||||
The function returns <[dst]> as passed.
|
||||
PORTABILITY
|
||||
<<memmove>> is ANSI C.
|
||||
<<memmove>> requires no supporting OS subroutines.
|
||||
QUICKREF
|
||||
memmove ansi pure
|
||||
*/
|
||||
|
||||
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
|
||||
#define UNALIGNED(X, Y) \
|
||||
(((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
|
||||
|
||||
/* How many bytes are copied each iteration of the 4X unrolled loop. */
|
||||
#define BIGBLOCKSIZE (sizeof (long) << 2)
|
||||
|
||||
/* How many bytes are copied each iteration of the word copy loop. */
|
||||
#define LITTLEBLOCKSIZE (sizeof (long))
|
||||
|
||||
/* Threshhold for punting to the byte copier. */
|
||||
#undef TOO_SMALL
|
||||
#define TOO_SMALL(LEN) ((LEN) < BIGBLOCKSIZE)
|
||||
|
||||
/*SUPPRESS 20*/
|
||||
void *
|
||||
//__inhibit_loop_to_libcall
|
||||
memmove (void *dst_void,
|
||||
const void *src_void,
|
||||
size_t length)
|
||||
{
|
||||
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
|
||||
char *dst = dst_void;
|
||||
const char *src = src_void;
|
||||
|
||||
if (src < dst && dst < src + length)
|
||||
{
|
||||
/* Have to copy backwards */
|
||||
src += length;
|
||||
dst += length;
|
||||
while (length--)
|
||||
{
|
||||
*--dst = *--src;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (length--)
|
||||
{
|
||||
*dst++ = *src++;
|
||||
}
|
||||
}
|
||||
|
||||
return dst_void;
|
||||
#else
|
||||
char *dst = dst_void;
|
||||
const char *src = src_void;
|
||||
long *aligned_dst;
|
||||
const long *aligned_src;
|
||||
|
||||
if (src < dst && dst < src + length)
|
||||
{
|
||||
/* Destructive overlap...have to copy backwards */
|
||||
src += length;
|
||||
dst += length;
|
||||
while (length--)
|
||||
{
|
||||
*--dst = *--src;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Use optimizing algorithm for a non-destructive copy to closely
|
||||
match memcpy. If the size is small or either SRC or DST is unaligned,
|
||||
then punt into the byte copy loop. This should be rare. */
|
||||
if (!TOO_SMALL(length) && !UNALIGNED (src, dst))
|
||||
{
|
||||
aligned_dst = (long*)dst;
|
||||
aligned_src = (long*)src;
|
||||
|
||||
/* Copy 4X long words at a time if possible. */
|
||||
while (length >= BIGBLOCKSIZE)
|
||||
{
|
||||
*aligned_dst++ = *aligned_src++;
|
||||
*aligned_dst++ = *aligned_src++;
|
||||
*aligned_dst++ = *aligned_src++;
|
||||
*aligned_dst++ = *aligned_src++;
|
||||
length -= BIGBLOCKSIZE;
|
||||
}
|
||||
|
||||
/* Copy one long word at a time if possible. */
|
||||
while (length >= LITTLEBLOCKSIZE)
|
||||
{
|
||||
*aligned_dst++ = *aligned_src++;
|
||||
length -= LITTLEBLOCKSIZE;
|
||||
}
|
||||
|
||||
/* Pick up any residual with a byte copier. */
|
||||
dst = (char*)aligned_dst;
|
||||
src = (char*)aligned_src;
|
||||
}
|
||||
|
||||
while (length--)
|
||||
{
|
||||
*dst++ = *src++;
|
||||
}
|
||||
}
|
||||
|
||||
return dst_void;
|
||||
#endif /* not PREFER_SIZE_OVER_SPEED */
|
||||
}
|
||||
|
||||
/*
|
||||
FUNCTION
|
||||
<<memcpy>>---copy memory regions
|
||||
SYNOPSIS
|
||||
#include <string.h>
|
||||
void* memcpy(void *restrict <[out]>, const void *restrict <[in]>,
|
||||
size_t <[n]>);
|
||||
DESCRIPTION
|
||||
This function copies <[n]> bytes from the memory region
|
||||
pointed to by <[in]> to the memory region pointed to by
|
||||
<[out]>.
|
||||
If the regions overlap, the behavior is undefined.
|
||||
RETURNS
|
||||
<<memcpy>> returns a pointer to the first byte of the <[out]>
|
||||
region.
|
||||
PORTABILITY
|
||||
<<memcpy>> is ANSI C.
|
||||
<<memcpy>> requires no supporting OS subroutines.
|
||||
QUICKREF
|
||||
memcpy ansi pure
|
||||
*/
|
||||
|
||||
void *
|
||||
memcpy (void * dst0,
|
||||
const void * __restrict src0,
|
||||
size_t len0)
|
||||
{
|
||||
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
|
||||
char *dst = (char *) dst0;
|
||||
char *src = (char *) src0;
|
||||
|
||||
void *save = dst0;
|
||||
|
||||
while (len0--)
|
||||
{
|
||||
*dst++ = *src++;
|
||||
}
|
||||
|
||||
return save;
|
||||
#else
|
||||
char *dst = dst0;
|
||||
const char *src = src0;
|
||||
long *aligned_dst;
|
||||
const long *aligned_src;
|
||||
|
||||
/* If the size is small, or either SRC or DST is unaligned,
|
||||
then punt into the byte copy loop. This should be rare. */
|
||||
if (!TOO_SMALL(len0) && !UNALIGNED (src, dst))
|
||||
{
|
||||
aligned_dst = (long*)dst;
|
||||
aligned_src = (long*)src;
|
||||
|
||||
/* Copy 4X long words at a time if possible. */
|
||||
while (len0 >= BIGBLOCKSIZE)
|
||||
{
|
||||
*aligned_dst++ = *aligned_src++;
|
||||
*aligned_dst++ = *aligned_src++;
|
||||
*aligned_dst++ = *aligned_src++;
|
||||
*aligned_dst++ = *aligned_src++;
|
||||
len0 -= BIGBLOCKSIZE;
|
||||
}
|
||||
|
||||
/* Copy one long word at a time if possible. */
|
||||
while (len0 >= LITTLEBLOCKSIZE)
|
||||
{
|
||||
*aligned_dst++ = *aligned_src++;
|
||||
len0 -= LITTLEBLOCKSIZE;
|
||||
}
|
||||
|
||||
/* Pick up any residual with a byte copier. */
|
||||
dst = (char*)aligned_dst;
|
||||
src = (char*)aligned_src;
|
||||
}
|
||||
|
||||
while (len0--)
|
||||
*dst++ = *src++;
|
||||
|
||||
return dst0;
|
||||
#endif /* not PREFER_SIZE_OVER_SPEED */
|
||||
}
|
||||
|
||||
/*
|
||||
FUNCTION
|
||||
<<memset>>---set an area of memory
|
||||
INDEX
|
||||
memset
|
||||
SYNOPSIS
|
||||
#include <string.h>
|
||||
void *memset(void *<[dst]>, int <[c]>, size_t <[length]>);
|
||||
DESCRIPTION
|
||||
This function converts the argument <[c]> into an unsigned
|
||||
char and fills the first <[length]> characters of the array
|
||||
pointed to by <[dst]> to the value.
|
||||
RETURNS
|
||||
<<memset>> returns the value of <[dst]>.
|
||||
PORTABILITY
|
||||
<<memset>> is ANSI C.
|
||||
<<memset>> requires no supporting OS subroutines.
|
||||
QUICKREF
|
||||
memset ansi pure
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#undef LBLOCKSIZE
|
||||
#undef UNALIGNED
|
||||
#undef TOO_SMALL
|
||||
|
||||
#define LBLOCKSIZE (sizeof(long))
|
||||
#define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1))
|
||||
#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
|
||||
|
||||
void *
|
||||
memset (void *m,
|
||||
int c,
|
||||
size_t n)
|
||||
{
|
||||
char *s = (char *) m;
|
||||
|
||||
#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
|
||||
unsigned int i;
|
||||
unsigned long buffer;
|
||||
unsigned long *aligned_addr;
|
||||
unsigned int d = c & 0xff; /* To avoid sign extension, copy C to an
|
||||
unsigned variable. */
|
||||
|
||||
while (UNALIGNED (s))
|
||||
{
|
||||
if (n--)
|
||||
*s++ = (char) c;
|
||||
else
|
||||
return m;
|
||||
}
|
||||
|
||||
if (!TOO_SMALL (n))
|
||||
{
|
||||
/* If we get this far, we know that n is large and s is word-aligned. */
|
||||
aligned_addr = (unsigned long *) s;
|
||||
|
||||
/* Store D into each char sized location in BUFFER so that
|
||||
we can set large blocks quickly. */
|
||||
buffer = (d << 8) | d;
|
||||
buffer |= (buffer << 16);
|
||||
for (i = 32; i < LBLOCKSIZE * 8; i <<= 1)
|
||||
buffer = (buffer << i) | buffer;
|
||||
|
||||
/* Unroll the loop. */
|
||||
while (n >= LBLOCKSIZE*4)
|
||||
{
|
||||
*aligned_addr++ = buffer;
|
||||
*aligned_addr++ = buffer;
|
||||
*aligned_addr++ = buffer;
|
||||
*aligned_addr++ = buffer;
|
||||
n -= 4*LBLOCKSIZE;
|
||||
}
|
||||
|
||||
while (n >= LBLOCKSIZE)
|
||||
{
|
||||
*aligned_addr++ = buffer;
|
||||
n -= LBLOCKSIZE;
|
||||
}
|
||||
/* Pick up the remainder with a bytewise loop. */
|
||||
s = (char*)aligned_addr;
|
||||
}
|
||||
|
||||
#endif /* not PREFER_SIZE_OVER_SPEED */
|
||||
|
||||
while (n--)
|
||||
*s++ = (char) c;
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/*
|
||||
FUNCTION
|
||||
<<memcmp>>---compare two memory areas
|
||||
INDEX
|
||||
memcmp
|
||||
SYNOPSIS
|
||||
#include <string.h>
|
||||
int memcmp(const void *<[s1]>, const void *<[s2]>, size_t <[n]>);
|
||||
DESCRIPTION
|
||||
This function compares not more than <[n]> characters of the
|
||||
object pointed to by <[s1]> with the object pointed to by <[s2]>.
|
||||
RETURNS
|
||||
The function returns an integer greater than, equal to or
|
||||
less than zero according to whether the object pointed to by
|
||||
<[s1]> is greater than, equal to or less than the object
|
||||
pointed to by <[s2]>.
|
||||
PORTABILITY
|
||||
<<memcmp>> is ANSI C.
|
||||
<<memcmp>> requires no supporting OS subroutines.
|
||||
QUICKREF
|
||||
memcmp ansi pure
|
||||
*/
|
||||
|
||||
#undef LBLOCKSIZE
|
||||
#undef UNALIGNED
|
||||
#undef TOO_SMALL
|
||||
|
||||
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
|
||||
#define UNALIGNED(X, Y) \
|
||||
(((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
|
||||
|
||||
/* How many bytes are copied each iteration of the word copy loop. */
|
||||
#define LBLOCKSIZE (sizeof (long))
|
||||
|
||||
/* Threshhold for punting to the byte copier. */
|
||||
#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
|
||||
|
||||
int
|
||||
memcmp (const void *m1,
|
||||
const void *m2,
|
||||
size_t n)
|
||||
{
|
||||
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
|
||||
unsigned char *s1 = (unsigned char *) m1;
|
||||
unsigned char *s2 = (unsigned char *) m2;
|
||||
|
||||
while (n--)
|
||||
{
|
||||
if (*s1 != *s2)
|
||||
{
|
||||
return *s1 - *s2;
|
||||
}
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
unsigned char *s1 = (unsigned char *) m1;
|
||||
unsigned char *s2 = (unsigned char *) m2;
|
||||
unsigned long *a1;
|
||||
unsigned long *a2;
|
||||
|
||||
/* If the size is too small, or either pointer is unaligned,
|
||||
then we punt to the byte compare loop. Hopefully this will
|
||||
not turn up in inner loops. */
|
||||
if (!TOO_SMALL(n) && !UNALIGNED(s1,s2))
|
||||
{
|
||||
/* Otherwise, load and compare the blocks of memory one
|
||||
word at a time. */
|
||||
a1 = (unsigned long*) s1;
|
||||
a2 = (unsigned long*) s2;
|
||||
while (n >= LBLOCKSIZE)
|
||||
{
|
||||
if (*a1 != *a2)
|
||||
break;
|
||||
a1++;
|
||||
a2++;
|
||||
n -= LBLOCKSIZE;
|
||||
}
|
||||
|
||||
/* check m mod LBLOCKSIZE remaining characters */
|
||||
|
||||
s1 = (unsigned char*)a1;
|
||||
s2 = (unsigned char*)a2;
|
||||
}
|
||||
|
||||
while (n--)
|
||||
{
|
||||
if (*s1 != *s2)
|
||||
return *s1 - *s2;
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
#endif /* not PREFER_SIZE_OVER_SPEED */
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
@@ -76,7 +76,7 @@ endif
|
||||
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
|
||||
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
|
||||
export HFILES := $(addsuffix .h,$(subst .,_,$(BINFILES)))
|
||||
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
|
||||
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
@@ -123,7 +123,7 @@ DEPENDS := $(OFILES:.o=.d)
|
||||
#---------------------------------------------------------------------------------
|
||||
$(OUTPUT) : $(OFILES)
|
||||
|
||||
$(OFILES_SRC) : $(HFILES)
|
||||
$(OFILES_SRC) : $(HFILES_BIN)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%_bin.h %.bin.o : %.bin
|
||||
|
||||
@@ -38,27 +38,41 @@ namespace ams::exosphere {
|
||||
};
|
||||
#undef AMS_DEFINE_TARGET_FIRMWARE_ENUM
|
||||
|
||||
constexpr inline u32 GetVersion(u32 major, u32 minor, u32 micro) {
|
||||
constexpr ALWAYS_INLINE u32 GetVersion(u32 major, u32 minor, u32 micro) {
|
||||
return (major << 16) | (minor << 8) | (micro);
|
||||
}
|
||||
|
||||
struct ApiInfo {
|
||||
u32 major_version;
|
||||
u32 minor_version;
|
||||
u32 micro_version;
|
||||
TargetFirmware target_firmware;
|
||||
u32 master_key_revision;
|
||||
using MasterKeyRevision = util::BitPack64::Field<0, 8, u32>;
|
||||
using TargetFirmwareVersion = util::BitPack64::Field<MasterKeyRevision::Next, 8, TargetFirmware>;
|
||||
using MicroVersion = util::BitPack64::Field<TargetFirmwareVersion::Next, 8, u32>;
|
||||
using MinorVersion = util::BitPack64::Field<MicroVersion::Next, 8, u32>;
|
||||
using MajorVersion = util::BitPack64::Field<MinorVersion::Next, 8, u32>;
|
||||
|
||||
constexpr u32 GetVersion() const {
|
||||
return ::ams::exosphere::GetVersion(this->major_version, this->minor_version, this->micro_version);
|
||||
util::BitPack64 value;
|
||||
|
||||
constexpr ALWAYS_INLINE u32 GetVersion() const {
|
||||
return ::ams::exosphere::GetVersion(this->GetMajorVersion(), this->GetMinorVersion(), this->GetMicroVersion());
|
||||
}
|
||||
|
||||
constexpr TargetFirmware GetTargetFirmware() const {
|
||||
return this->target_firmware;
|
||||
constexpr ALWAYS_INLINE u32 GetMajorVersion() const {
|
||||
return this->value.Get<MajorVersion>();
|
||||
}
|
||||
|
||||
constexpr u32 GetMasterKeyRevision() const {
|
||||
return this->master_key_revision;
|
||||
constexpr ALWAYS_INLINE u32 GetMinorVersion() const {
|
||||
return this->value.Get<MinorVersion>();
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE u32 GetMicroVersion() const {
|
||||
return this->value.Get<MicroVersion>();
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE TargetFirmware GetTargetFirmware() const {
|
||||
return this->value.Get<TargetFirmwareVersion>();
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE u32 GetMasterKeyRevision() const {
|
||||
return this->value.Get<MasterKeyRevision>();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -74,7 +88,7 @@ namespace ams {
|
||||
static constexpr u64 StdAbortMagicValue = 0xA55AF00DDEADCAFEul;
|
||||
static constexpr u32 StdAbortErrorDesc = 0xFFE;
|
||||
static constexpr u32 DataAbortErrorDesc = 0x101;
|
||||
static constexpr u32 Magic = 0x31454641;
|
||||
static constexpr u32 Magic = util::FourCC<'A', 'F', 'E', '1'>::Code;
|
||||
|
||||
u32 magic;
|
||||
u32 error_desc;
|
||||
|
||||
@@ -42,7 +42,6 @@ namespace ams::cfg {
|
||||
bool HasGlobalFlag(const char *flag);
|
||||
|
||||
/* HBL Configuration utilities. */
|
||||
bool IsHblProgramId(ncm::ProgramId program_id);
|
||||
bool HasHblFlag(const char *flag);
|
||||
const char *GetHblPath();
|
||||
|
||||
|
||||
@@ -327,7 +327,10 @@ namespace ams::fatal {
|
||||
Event erpt_event;
|
||||
Event battery_event;
|
||||
size_t stack_dump_size;
|
||||
u64 stack_dump_base;
|
||||
u8 stack_dump[0x100];
|
||||
u64 tls_address;
|
||||
u8 tls_dump[0x100];
|
||||
|
||||
void ClearState() {
|
||||
this->result = ResultSuccess();
|
||||
@@ -339,7 +342,10 @@ namespace ams::fatal {
|
||||
std::memset(&this->erpt_event, 0, sizeof(this->erpt_event));
|
||||
std::memset(&this->battery_event, 0, sizeof(this->battery_event));
|
||||
this->stack_dump_size = 0;
|
||||
this->stack_dump_base = 0;
|
||||
std::memset(this->stack_dump, 0, sizeof(this->stack_dump));
|
||||
this->tls_address = 0;
|
||||
std::memset(this->tls_dump, 0, sizeof(this->tls_dump));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace ams::ldr {
|
||||
|
||||
/* NSO types. */
|
||||
struct NsoHeader {
|
||||
static constexpr u32 Magic = 0x304F534E;
|
||||
static constexpr u32 Magic = util::FourCC<'N','S','O','0'>::Code;
|
||||
enum Segment : size_t {
|
||||
Segment_Text = 0,
|
||||
Segment_Ro = 1,
|
||||
@@ -145,7 +145,7 @@ namespace ams::ldr {
|
||||
|
||||
/* NPDM types. */
|
||||
struct Aci {
|
||||
static constexpr u32 Magic = 0x30494341;
|
||||
static constexpr u32 Magic = util::FourCC<'A','C','I','0'>::Code;
|
||||
|
||||
u32 magic;
|
||||
u8 reserved_04[0xC];
|
||||
@@ -162,7 +162,7 @@ namespace ams::ldr {
|
||||
static_assert(sizeof(Aci) == 0x40 && std::is_pod<Aci>::value, "Aci definition!");
|
||||
|
||||
struct Acid {
|
||||
static constexpr u32 Magic = 0x44494341;
|
||||
static constexpr u32 Magic = util::FourCC<'A','C','I','D'>::Code;
|
||||
|
||||
enum AcidFlag {
|
||||
AcidFlag_Production = (1 << 0),
|
||||
@@ -201,7 +201,7 @@ namespace ams::ldr {
|
||||
static_assert(sizeof(Acid) == 0x240 && std::is_pod<Acid>::value, "Acid definition!");
|
||||
|
||||
struct Npdm {
|
||||
static constexpr u32 Magic = 0x4154454D;
|
||||
static constexpr u32 Magic = util::FourCC<'M','E','T','A'>::Code;
|
||||
|
||||
enum MetaFlag {
|
||||
MetaFlag_Is64Bit = (1 << 0),
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace ams::ro {
|
||||
|
||||
class NrrHeader {
|
||||
public:
|
||||
static constexpr u32 Magic = 0x3052524E;
|
||||
static constexpr u32 Magic = util::FourCC<'N','R','R','0'>::Code;
|
||||
private:
|
||||
u32 magic;
|
||||
u8 reserved_04[0xC];
|
||||
@@ -85,7 +85,7 @@ namespace ams::ro {
|
||||
|
||||
class NroHeader {
|
||||
public:
|
||||
static constexpr u32 Magic = 0x304F524E;
|
||||
static constexpr u32 Magic = util::FourCC<'N','R','O','0'>::Code;
|
||||
private:
|
||||
u32 entrypoint_insn;
|
||||
u32 mod_offset;
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace ams::emummc {
|
||||
namespace {
|
||||
|
||||
/* Convenience Definitions. */
|
||||
constexpr u32 StorageMagic = 0x30534645; /* EFS0 */
|
||||
constexpr u32 StorageMagic = util::FourCC<'E','F','S','0'>::Code;
|
||||
constexpr size_t MaxDirLen = 0x7F;
|
||||
|
||||
/* Types. */
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace ams {
|
||||
|
||||
extern ncm::ProgramId CurrentProgramId;
|
||||
|
||||
void WEAK ExceptionHandler(FatalErrorContext *ctx) {
|
||||
void WEAK_SYMBOL ExceptionHandler(FatalErrorContext *ctx) {
|
||||
R_ASSERT(amsBpcInitialize());
|
||||
R_ASSERT(amsBpcRebootToFatalError(ctx));
|
||||
while (1) { /* ... */ }
|
||||
|
||||
@@ -26,13 +26,7 @@ namespace ams::exosphere {
|
||||
R_ASSERT(ResultNotPresent());
|
||||
}
|
||||
|
||||
return ApiInfo{
|
||||
.major_version = static_cast<u32>((exosphere_cfg >> 0x20) & 0xFF),
|
||||
.minor_version = static_cast<u32>((exosphere_cfg >> 0x18) & 0xFF),
|
||||
.micro_version = static_cast<u32>((exosphere_cfg >> 0x10) & 0xFF),
|
||||
.target_firmware = static_cast<TargetFirmware>((exosphere_cfg >> 0x08) & 0xFF),
|
||||
.master_key_revision = static_cast<u32>((exosphere_cfg >> 0x00) & 0xFF),
|
||||
};
|
||||
return ApiInfo{ util::BitPack64(exosphere_cfg) };
|
||||
}
|
||||
|
||||
void ForceRebootToRcm() {
|
||||
|
||||
@@ -26,10 +26,26 @@ namespace ams::cfg {
|
||||
bool override_by_default;
|
||||
};
|
||||
|
||||
struct HblOverrideConfig {
|
||||
OverrideKey override_key;
|
||||
OverrideKey override_any_app_key;
|
||||
struct ProgramOverrideKey {
|
||||
OverrideKey override_key;
|
||||
ncm::ProgramId program_id;
|
||||
};
|
||||
|
||||
constexpr ProgramOverrideKey InvalidProgramOverrideKey = {};
|
||||
|
||||
constexpr ProgramOverrideKey DefaultAppletPhotoViewerOverrideKey = {
|
||||
.override_key = {
|
||||
.key_combination = KEY_R,
|
||||
.override_by_default = true,
|
||||
},
|
||||
.program_id = ncm::ProgramId::AppletPhotoViewer,
|
||||
};
|
||||
|
||||
constexpr size_t MaxProgramOverrideKeys = 8;
|
||||
|
||||
struct HblOverrideConfig {
|
||||
ProgramOverrideKey program_configs[MaxProgramOverrideKeys];
|
||||
OverrideKey override_any_app_key;
|
||||
bool override_any_app;
|
||||
};
|
||||
|
||||
@@ -51,15 +67,20 @@ namespace ams::cfg {
|
||||
};
|
||||
|
||||
HblOverrideConfig g_hbl_override_config = {
|
||||
.override_key = {
|
||||
.key_combination = KEY_R,
|
||||
.override_by_default = true,
|
||||
.program_configs = {
|
||||
DefaultAppletPhotoViewerOverrideKey,
|
||||
InvalidProgramOverrideKey,
|
||||
InvalidProgramOverrideKey,
|
||||
InvalidProgramOverrideKey,
|
||||
InvalidProgramOverrideKey,
|
||||
InvalidProgramOverrideKey,
|
||||
InvalidProgramOverrideKey,
|
||||
InvalidProgramOverrideKey,
|
||||
},
|
||||
.override_any_app_key = {
|
||||
.key_combination = KEY_R,
|
||||
.override_by_default = false,
|
||||
},
|
||||
.program_id = ncm::ProgramId::AppletPhotoViewer,
|
||||
.override_any_app = true,
|
||||
};
|
||||
|
||||
@@ -117,15 +138,59 @@ namespace ams::cfg {
|
||||
return cfg;
|
||||
}
|
||||
|
||||
inline void SetHblSpecificProgramId(size_t i, const char *value) {
|
||||
g_hbl_override_config.program_configs[i].program_id = {strtoul(value, nullptr, 16)};
|
||||
}
|
||||
|
||||
inline void SetHblSpecificOverrideKey(size_t i, const char *value) {
|
||||
g_hbl_override_config.program_configs[i].override_key = ParseOverrideKey(value);
|
||||
}
|
||||
|
||||
int OverrideConfigIniHandler(void *user, const char *section, const char *name, const char *value) {
|
||||
/* Taken and modified, with love, from Rajkosto's implementation. */
|
||||
if (strcasecmp(section, "hbl_config") == 0) {
|
||||
/* TODO: Consider deprecating "title_id" string in the future." */
|
||||
if (strcasecmp(name, "program_id") == 0 || strcasecmp(name, "title_id") == 0) {
|
||||
u64 override_program_id = strtoul(value, NULL, 16);
|
||||
if (override_program_id != 0) {
|
||||
g_hbl_override_config.program_id = {override_program_id};
|
||||
if (strcasecmp(name, "program_id") == 0 || strcasecmp(name, "program_id_0") == 0) {
|
||||
SetHblSpecificProgramId(0, value);
|
||||
} else if (strcasecmp(name, "program_id_1") == 0) {
|
||||
SetHblSpecificProgramId(1, value);
|
||||
} else if (strcasecmp(name, "program_id_2") == 0) {
|
||||
SetHblSpecificProgramId(2, value);
|
||||
} else if (strcasecmp(name, "program_id_3") == 0) {
|
||||
SetHblSpecificProgramId(3, value);
|
||||
} else if (strcasecmp(name, "program_id_4") == 0) {
|
||||
SetHblSpecificProgramId(4, value);
|
||||
} else if (strcasecmp(name, "program_id_5") == 0) {
|
||||
SetHblSpecificProgramId(5, value);
|
||||
} else if (strcasecmp(name, "program_id_6") == 0) {
|
||||
SetHblSpecificProgramId(6, value);
|
||||
} else if (strcasecmp(name, "program_id_7") == 0) {
|
||||
SetHblSpecificProgramId(7, value);
|
||||
} else if (strcasecmp(name, "override_key") == 0 || strcasecmp(name, "override_key_0") == 0) {
|
||||
SetHblSpecificOverrideKey(0, value);
|
||||
} else if (strcasecmp(name, "override_key_1") == 0) {
|
||||
SetHblSpecificOverrideKey(1, value);
|
||||
} else if (strcasecmp(name, "override_key_2") == 0) {
|
||||
SetHblSpecificOverrideKey(2, value);
|
||||
} else if (strcasecmp(name, "override_key_3") == 0) {
|
||||
SetHblSpecificOverrideKey(3, value);
|
||||
} else if (strcasecmp(name, "override_key_4") == 0) {
|
||||
SetHblSpecificOverrideKey(4, value);
|
||||
} else if (strcasecmp(name, "override_key_5") == 0) {
|
||||
SetHblSpecificOverrideKey(5, value);
|
||||
} else if (strcasecmp(name, "override_key_6") == 0) {
|
||||
SetHblSpecificOverrideKey(6, value);
|
||||
} else if (strcasecmp(name, "override_key_7") == 0) {
|
||||
SetHblSpecificOverrideKey(7, value);
|
||||
} else if (strcasecmp(name, "override_any_app") == 0) {
|
||||
if (strcasecmp(value, "true") == 0 || strcasecmp(value, "1") == 0) {
|
||||
g_hbl_override_config.override_any_app = true;
|
||||
} else if (strcasecmp(value, "false") == 0 || strcasecmp(value, "0") == 0) {
|
||||
g_hbl_override_config.override_any_app = false;
|
||||
} else {
|
||||
/* I guess we default to not changing the value? */
|
||||
}
|
||||
} else if (strcasecmp(name, "override_any_app_key") == 0) {
|
||||
g_hbl_override_config.override_any_app_key = ParseOverrideKey(value);
|
||||
} else if (strcasecmp(name, "path") == 0) {
|
||||
while (*value == '/' || *value == '\\') {
|
||||
value++;
|
||||
@@ -138,18 +203,6 @@ namespace ams::cfg {
|
||||
g_hbl_sd_path[i] = '/';
|
||||
}
|
||||
}
|
||||
} else if (strcasecmp(name, "override_key") == 0) {
|
||||
g_hbl_override_config.override_key = ParseOverrideKey(value);
|
||||
} else if (strcasecmp(name, "override_any_app") == 0) {
|
||||
if (strcasecmp(value, "true") == 0 || strcasecmp(value, "1") == 0) {
|
||||
g_hbl_override_config.override_any_app = true;
|
||||
} else if (strcasecmp(value, "false") == 0 || strcasecmp(value, "0") == 0) {
|
||||
g_hbl_override_config.override_any_app = false;
|
||||
} else {
|
||||
/* I guess we default to not changing the value? */
|
||||
}
|
||||
} else if (strcasecmp(name, "override_any_app_key") == 0) {
|
||||
g_hbl_override_config.override_any_app_key = ParseOverrideKey(value);
|
||||
}
|
||||
} else if (strcasecmp(section, "default_config") == 0) {
|
||||
if (strcasecmp(name, "override_key") == 0) {
|
||||
@@ -202,12 +255,21 @@ namespace ams::cfg {
|
||||
return (cfg.override_by_default ^ keys_triggered);
|
||||
}
|
||||
|
||||
inline bool IsApplicationHblProgramId(ncm::ProgramId program_id) {
|
||||
return g_hbl_override_config.override_any_app && ncm::IsApplicationProgramId(program_id);
|
||||
inline bool IsAnySpecificHblProgramId(ncm::ProgramId program_id) {
|
||||
for (size_t i = 0; i < MaxProgramOverrideKeys; i++) {
|
||||
if (program_id == g_hbl_override_config.program_configs[i].program_id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool IsSpecificHblProgramId(ncm::ProgramId program_id) {
|
||||
return program_id == g_hbl_override_config.program_id;
|
||||
inline bool IsSpecificHblProgramId(size_t i, ncm::ProgramId program_id) {
|
||||
return program_id == g_hbl_override_config.program_configs[i].program_id;
|
||||
}
|
||||
|
||||
inline bool IsAnyApplicationHblProgramId(ncm::ProgramId program_id) {
|
||||
return g_hbl_override_config.override_any_app && ncm::IsApplicationProgramId(program_id) && !IsAnySpecificHblProgramId(program_id);
|
||||
}
|
||||
|
||||
void ParseIniFile(util::ini::Handler handler, const char *path, void *user_ctx) {
|
||||
@@ -272,11 +334,14 @@ namespace ams::cfg {
|
||||
}
|
||||
|
||||
/* Detect Hbl. */
|
||||
if ((IsApplicationHblProgramId(program_id) && IsOverrideMatch(status, g_hbl_override_config.override_any_app_key)) ||
|
||||
(IsSpecificHblProgramId(program_id) && IsOverrideMatch(status, g_hbl_override_config.override_key)))
|
||||
{
|
||||
if (IsAnyApplicationHblProgramId(program_id) && IsOverrideMatch(status, g_hbl_override_config.override_any_app_key)) {
|
||||
status.SetHbl();
|
||||
}
|
||||
for (size_t i = 0; i < MaxProgramOverrideKeys; i++) {
|
||||
if (IsSpecificHblProgramId(i, program_id) && IsOverrideMatch(status, g_hbl_override_config.program_configs[i].override_key)) {
|
||||
status.SetHbl();
|
||||
}
|
||||
}
|
||||
|
||||
/* Detect content specific keys. */
|
||||
const auto content_cfg = GetContentOverrideConfig(program_id);
|
||||
@@ -297,10 +362,6 @@ namespace ams::cfg {
|
||||
}
|
||||
|
||||
/* HBL Configuration utilities. */
|
||||
bool IsHblProgramId(ncm::ProgramId program_id) {
|
||||
return IsApplicationHblProgramId(program_id) || IsSpecificHblProgramId(program_id);
|
||||
}
|
||||
|
||||
const char *GetHblPath() {
|
||||
return g_hbl_sd_path;
|
||||
}
|
||||
|
||||
@@ -19,13 +19,13 @@ namespace ams::pm::bm {
|
||||
|
||||
/* Boot Mode API. */
|
||||
/* Both functions should be weakly linked, so that they can be overridden by ams::boot2 as needed. */
|
||||
BootMode WEAK GetBootMode() {
|
||||
BootMode WEAK_SYMBOL GetBootMode() {
|
||||
PmBootMode boot_mode = PmBootMode_Normal;
|
||||
R_ASSERT(pmbmGetBootMode(&boot_mode));
|
||||
return static_cast<BootMode>(boot_mode);
|
||||
}
|
||||
|
||||
void WEAK SetMaintenanceBoot() {
|
||||
void WEAK_SYMBOL SetMaintenanceBoot() {
|
||||
R_ASSERT(pmbmSetMaintenanceBoot());
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace ams::pm::info {
|
||||
return pminfoAtmosphereGetProcessInfo(reinterpret_cast<NcmProgramLocation *>(out_loc), reinterpret_cast<CfgOverrideStatus *>(out_status), static_cast<u64>(process_id));
|
||||
}
|
||||
|
||||
Result WEAK HasLaunchedProgram(bool *out, ncm::ProgramId program_id) {
|
||||
Result WEAK_SYMBOL HasLaunchedProgram(bool *out, ncm::ProgramId program_id) {
|
||||
std::scoped_lock lk(g_info_lock);
|
||||
|
||||
if (g_cached_launched_programs.find(static_cast<u64>(program_id)) != g_cached_launched_programs.end()) {
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
namespace ams::pm::shell {
|
||||
|
||||
/* Shell API. */
|
||||
Result WEAK LaunchProgram(os::ProcessId *out_process_id, const ncm::ProgramLocation &loc, u32 launch_flags) {
|
||||
Result WEAK_SYMBOL LaunchProgram(os::ProcessId *out_process_id, const ncm::ProgramLocation &loc, u32 launch_flags) {
|
||||
static_assert(sizeof(ncm::ProgramLocation) == sizeof(NcmProgramLocation));
|
||||
static_assert(alignof(ncm::ProgramLocation) == alignof(NcmProgramLocation));
|
||||
return pmshellLaunchProgram(launch_flags, reinterpret_cast<const NcmProgramLocation *>(&loc), reinterpret_cast<u64 *>(out_process_id));
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace ams::result {
|
||||
|
||||
namespace ams::result::impl {
|
||||
|
||||
NORETURN WEAK void OnResultAssertion(Result result) {
|
||||
NORETURN WEAK_SYMBOL void OnResultAssertion(Result result) {
|
||||
/* Assert that we should call fatal on result assertion. */
|
||||
/* If we shouldn't fatal, this will std::abort(); */
|
||||
/* If we should, we'll continue onwards. */
|
||||
|
||||
@@ -20,13 +20,13 @@ namespace ams::settings::fwdbg {
|
||||
/* TODO: Implement when libnx wrapper is added. */
|
||||
bool IsDebugModeEnabled();
|
||||
|
||||
size_t WEAK GetSettingsItemValueSize(const char *name, const char *key) {
|
||||
size_t WEAK_SYMBOL GetSettingsItemValueSize(const char *name, const char *key) {
|
||||
u64 size = 0;
|
||||
R_ASSERT(setsysGetSettingsItemValueSize(name, key, &size));
|
||||
return size;
|
||||
}
|
||||
|
||||
size_t WEAK GetSettingsItemValue(void *dst, size_t dst_size, const char *name, const char *key) {
|
||||
size_t WEAK_SYMBOL GetSettingsItemValue(void *dst, size_t dst_size, const char *name, const char *key) {
|
||||
u64 size = 0;
|
||||
R_ASSERT(setsysGetSettingsItemValue(name, key, dst, dst_size, &size));
|
||||
return size;
|
||||
|
||||
@@ -277,7 +277,8 @@ namespace ams::sf::hipc {
|
||||
/* Note: Nintendo does not validate this size before subtracting 0x10 from it. This is not exploitable. */
|
||||
R_UNLESS(in_raw_size >= 0x10, sf::hipc::ResultInvalidRequestSize());
|
||||
R_UNLESS(in_raw_addr + in_raw_size <= in_message_buffer_end, sf::hipc::ResultInvalidRequestSize());
|
||||
const uintptr_t recv_list_end = reinterpret_cast<uintptr_t>(dispatch_ctx.request.data.recv_list + dispatch_ctx.request.meta.num_recv_statics);
|
||||
const size_t recv_list_size = dispatch_ctx.request.meta.num_recv_statics == HIPC_AUTO_RECV_STATIC ? 1 : dispatch_ctx.request.meta.num_recv_statics;
|
||||
const uintptr_t recv_list_end = reinterpret_cast<uintptr_t>(dispatch_ctx.request.data.recv_list + recv_list_size);
|
||||
R_UNLESS(recv_list_end <= in_message_buffer_end, sf::hipc::ResultInvalidRequestSize());
|
||||
|
||||
/* CMIF has 0x10 of padding in raw data, and requires 0x10 alignment. */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user