Compare commits
66 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
37161c5d11 | ||
|
|
d646023bbd | ||
|
|
b63061a505 | ||
|
|
61b057c37d | ||
|
|
2388a3f4fd | ||
|
|
cfc9576eaf | ||
|
|
e9e3f29d74 | ||
|
|
83f21d7d2a | ||
|
|
4adf297c80 | ||
|
|
f5695145ef | ||
|
|
a0e06cf7b2 | ||
|
|
0288986e14 | ||
|
|
fa6cf1ffb8 | ||
|
|
5b235a4b03 | ||
|
|
771039e6a7 | ||
|
|
1a63078c32 | ||
|
|
4a60cee5ff | ||
|
|
0df92148a4 | ||
|
|
f1ea368585 | ||
|
|
656053582a | ||
|
|
37eb3315b6 | ||
|
|
d20cd73523 | ||
|
|
a0acbda9ce | ||
|
|
f00dd05f82 | ||
|
|
92d8829ee1 | ||
|
|
9979cec045 | ||
|
|
8cff208d36 | ||
|
|
7d170259d3 | ||
|
|
d0ff791260 | ||
|
|
ddc5222208 | ||
|
|
f1068d6c3f | ||
|
|
fb2baa8c8d | ||
|
|
c56561b234 | ||
|
|
f58f7c8a16 | ||
|
|
5fe24b620d | ||
|
|
26f45fab19 | ||
|
|
85669ef491 | ||
|
|
56246551e6 | ||
|
|
6027ff243d | ||
|
|
1d0efbf456 | ||
|
|
67c7ef69f4 | ||
|
|
e2a7f23214 | ||
|
|
784964d49d | ||
|
|
e715197290 | ||
|
|
5f836aca6d | ||
|
|
4e99eaa590 | ||
|
|
a3adb70a04 | ||
|
|
de07ed42bb | ||
|
|
53488eb8e5 | ||
|
|
752e0757d9 | ||
|
|
a71b2d9329 | ||
|
|
506ac3f167 | ||
|
|
46f4896992 | ||
|
|
6c41e105c4 | ||
|
|
bdfd7946e3 | ||
|
|
f78fd29e38 | ||
|
|
3d6405be85 | ||
|
|
7bdb2ae897 | ||
|
|
891b865da8 | ||
|
|
dc2b8ebab9 | ||
|
|
901723621c | ||
|
|
3f6325c358 | ||
|
|
ea02f389ac | ||
|
|
cd8621c632 | ||
|
|
e55a7bef26 | ||
|
|
da68d02c77 |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -73,10 +73,15 @@ dkms.conf
|
||||
*.nam
|
||||
*.til
|
||||
|
||||
# KEYS file for sept-secondary.
|
||||
*.pyc
|
||||
sept/sept-secondary/KEYS.py
|
||||
|
||||
.**/
|
||||
|
||||
# NOTE: make sure to make exceptions to this pattern when needed!
|
||||
*.bin
|
||||
*.enc
|
||||
|
||||
**/out
|
||||
**/build
|
||||
|
||||
22
Makefile
22
Makefile
@@ -6,7 +6,9 @@ ifneq (, $(strip $(shell git status --porcelain 2>/dev/null)))
|
||||
AMSREV := $(AMSREV)-dirty
|
||||
endif
|
||||
|
||||
all: fusee stratosphere exosphere thermosphere troposphere
|
||||
COMPONENTS := fusee stratosphere exosphere thermosphere troposphere
|
||||
|
||||
all: $(COMPONENTS)
|
||||
|
||||
thermosphere:
|
||||
$(MAKE) -C thermosphere all
|
||||
@@ -20,13 +22,16 @@ stratosphere: exosphere
|
||||
troposphere: stratosphere
|
||||
$(MAKE) -C troposphere all
|
||||
|
||||
fusee: exosphere stratosphere
|
||||
sept: exosphere
|
||||
$(MAKE) -C sept all
|
||||
|
||||
fusee: exosphere stratosphere sept
|
||||
$(MAKE) -C $@ all
|
||||
|
||||
clean:
|
||||
$(MAKE) -C fusee clean
|
||||
rm -rf out
|
||||
|
||||
|
||||
dist: all
|
||||
$(eval MAJORVER = $(shell grep '\ATMOSPHERE_RELEASE_VERSION_MAJOR\b' common/include/atmosphere/version.h \
|
||||
| tr -s [:blank:] \
|
||||
@@ -42,19 +47,24 @@ dist: all
|
||||
rm -rf out
|
||||
mkdir atmosphere-$(AMSVER)
|
||||
mkdir atmosphere-$(AMSVER)/atmosphere
|
||||
mkdir atmosphere-$(AMSVER)/sept
|
||||
mkdir atmosphere-$(AMSVER)/switch
|
||||
mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000036
|
||||
mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000034
|
||||
mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032
|
||||
cp fusee/fusee-primary/fusee-primary.bin atmosphere-$(AMSVER)/atmosphere/reboot_payload.bin
|
||||
cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin
|
||||
cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/sept/payload.bin
|
||||
cp sept/sept-primary/sept-primary.bin atmosphere-$(AMSVER)/sept/sept-primary.bin
|
||||
cp sept/sept-secondary/sept-secondary.bin atmosphere-$(AMSVER)/sept/sept-secondary.bin
|
||||
cp sept/sept-secondary/sept-secondary.enc atmosphere-$(AMSVER)/sept/sept-secondary.enc
|
||||
cp common/defaults/BCT.ini atmosphere-$(AMSVER)/atmosphere/BCT.ini
|
||||
cp common/defaults/loader.ini atmosphere-$(AMSVER)/atmosphere/loader.ini
|
||||
cp common/defaults/system_settings.ini atmosphere-$(AMSVER)/atmosphere/system_settings.ini
|
||||
cp -r common/defaults/kip_patches atmosphere-$(AMSVER)/atmosphere/kip_patches
|
||||
cp stratosphere/creport/creport.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000036/exefs.nsp
|
||||
cp stratosphere/fatal/fatal.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000034/exefs.nsp
|
||||
cp stratosphere/set_mitm/set_mitm.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032/exefs.nsp
|
||||
cp stratosphere/eclct.stub/eclct.stub.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032/exefs.nsp
|
||||
cp troposphere/reboot_to_payload/reboot_to_payload.nro atmosphere-$(AMSVER)/switch/reboot_to_payload.nro
|
||||
mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032/flags
|
||||
touch atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032/flags/boot2.flag
|
||||
@@ -63,6 +73,6 @@ dist: all
|
||||
mkdir out
|
||||
mv atmosphere-$(AMSVER).zip out/atmosphere-$(AMSVER).zip
|
||||
cp fusee/fusee-primary/fusee-primary.bin out/fusee-primary.bin
|
||||
|
||||
|
||||
.PHONY: $(TOPTARGETS) fusee
|
||||
|
||||
.PHONY: $(TOPTARGETS) $(COMPONENTS)
|
||||
|
||||
@@ -13,6 +13,7 @@ Components
|
||||
Atmosphère consists of multiple components, each of which replaces/modifies a different component of the system:
|
||||
|
||||
* Fusée: First-stage Loader, responsible for loading and validating stage 2 (custom TrustZone) plus package2 (Kernel/FIRM sysmodules), and patching them as needed. This replaces all functionality normally in Package1loader/NX Bootloader.
|
||||
* Sept: Payload used to enable support for runtime key derivation on 7.0.0.
|
||||
* Exosphère: Customized TrustZone, to run a customized Secure Monitor
|
||||
* Thermosphère: EL2 EmuNAND support, i.e. backing up and using virtualized/redirected NAND images
|
||||
* Stratosphère: Custom Sysmodule(s), both Rosalina style to extend the kernel/provide new features, and of the loader reimplementation style to hook important system actions
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -3,4 +3,9 @@
|
||||
upload_enabled = u8!0x0
|
||||
; Enable USB 3.0 superspeed for homebrew
|
||||
[usb]
|
||||
usb30_force_enabled = u8!0x1
|
||||
usb30_force_enabled = u8!0x1
|
||||
; Atmosphere custom settings
|
||||
[atmosphere]
|
||||
; Make the power menu's "reboot" button reboot to payload.
|
||||
; Set to "normal" for normal reboot, "rcm" for rcm reboot.
|
||||
power_menu_reboot_function = str!payload
|
||||
@@ -24,11 +24,12 @@
|
||||
#define ATMOSPHERE_TARGET_FIRMWARE_500 5
|
||||
#define ATMOSPHERE_TARGET_FIRMWARE_600 6
|
||||
#define ATMOSPHERE_TARGET_FIRMWARE_620 7
|
||||
#define ATMOSPHERE_TARGET_FIRMWARE_700 8
|
||||
|
||||
#define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_620
|
||||
#define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_700
|
||||
|
||||
#define ATMOSPHERE_TARGET_FIRMWARE_MIN ATMOSPHERE_TARGET_FIRMWARE_100
|
||||
#define ATMOSPHERE_TARGET_FIRMWARE_MAX ATMOSPHERE_TARGET_FIRMWARE_620
|
||||
#define ATMOSPHERE_TARGET_FIRMWARE_MAX ATMOSPHERE_TARGET_FIRMWARE_700
|
||||
|
||||
/* TODO: What should this be, for release? */
|
||||
#define ATMOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG ATMOSPHERE_TARGET_FIRMWARE_CURRENT
|
||||
|
||||
@@ -19,6 +19,6 @@
|
||||
|
||||
#define ATMOSPHERE_RELEASE_VERSION_MAJOR 0
|
||||
#define ATMOSPHERE_RELEASE_VERSION_MINOR 8
|
||||
#define ATMOSPHERE_RELEASE_VERSION_MICRO 3
|
||||
#define ATMOSPHERE_RELEASE_VERSION_MICRO 4
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,19 @@
|
||||
# Changelog
|
||||
## 0.8.4
|
||||
+ Support for 7.0.0/7.0.1 was added.
|
||||
+ This is facilitated through a new payload, `sept`, which can be signed, encrypted, and then loaded by Nintendo's TSEC firmware.
|
||||
+ `sept` will derive the keys needed to boot new firmware, and then load `sept/payload.bin` off the SD card and jump to it.
|
||||
+ Recognition of applications for override/mitm has been improved.
|
||||
+ Nintendo's official Title ID range (`0x0100000000000000`-`0x01FFFFFFFFFFFFFF`) is now enforced.
|
||||
+ A deadlock condition was fixed involving libstratosphere mitm sysmodules.
|
||||
+ Kernel patches for JIT support were added (Thanks, @m4xw!).
|
||||
+ These loosen restrictions on caller process in svcControlCodeMemory.
|
||||
+ `set.mitm` and `fs.mitm` were merged into a single `ams_mitm` sysmodule.
|
||||
+ This saves a process ID, allowing users to run one additional process up to the 0x40 process limit.
|
||||
+ A `bpc.mitm` component was added, performing custom behavior on shutdown/reboot requests from `am` or applications.
|
||||
+ Performing a reboot from the reboot menu now reboots to atmosphere. This can be configured via `system_settings.ini`.
|
||||
+ Performing a shutdown from the reboot menu now works properly with AutoRCM, and does a real shutdown.
|
||||
+ General system stability improvements to enhance the user's experience.
|
||||
## 0.8.3
|
||||
+ A custom warmboot firmware was implemented, which does not perform anti-downgrade fuse checks.
|
||||
+ This fixes sleep mode when using a downgraded NAND.
|
||||
|
||||
15
docs/components/fusee/sept.md
Normal file
15
docs/components/fusee/sept.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# sept
|
||||
Sept is a payload that facilitates booting Atmosphère when targeting firmware version 7.0.0+.
|
||||
|
||||
It consists of a primary and a secondary payload.
|
||||
|
||||
## Sept-Primary
|
||||
Sept-primary is essentially a stand-in for Nintendo's package1ldr, on 7.0.0+. To use it, the caller (normally Fusée-secondary) loads the sept-primary binary to `0x4003F000`,
|
||||
loads the 7.0.0+ TSEC firmware to `0x40010F00`, and loads a signed, encrypted payload to `0x40016FE0`.
|
||||
|
||||
This signed, encrypted payload is normally Sept-secondary.
|
||||
|
||||
## Sept-Secondary
|
||||
Sept-secondary is a payload that performs 7.0.0+ key derivation, and then chainloads to `sept/payload.bin`.
|
||||
|
||||
It is normally stored encrypted/signed; if one wishes to build sept-secondary instead of using release builds, one must bring his/her own keys.
|
||||
169
exosphere/rebootstub/src/i2c.c
Normal file
169
exosphere/rebootstub/src/i2c.c
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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 "max77620.h"
|
||||
#include "i2c.h"
|
||||
#include "timer.h"
|
||||
|
||||
/* Prototypes for internal commands. */
|
||||
void i2c_load_config(void);
|
||||
int i2c_write(unsigned int device, uint32_t val, unsigned int num_bytes);
|
||||
int i2c_read(unsigned int device, void *dst, unsigned num_bytes);
|
||||
int i2c_query(uint8_t device, uint8_t r, void *dst, size_t num_bytes);
|
||||
int i2c_send_byte_command(unsigned int device, unsigned char reg, unsigned char b);
|
||||
|
||||
/* Load hardware config for I2C4. */
|
||||
void i2c_load_config(void) {
|
||||
/* Set MSTR_CONFIG_LOAD, TIMEOUT_CONFIG_LOAD, undocumented bit. */
|
||||
I2C_I2C_CONFIG_LOAD_0 = 0x25;
|
||||
|
||||
/* Wait a bit for master config to be loaded. */
|
||||
for (unsigned int i = 0; i < 20; i++) {
|
||||
timer_wait(1);
|
||||
if (!(I2C_I2C_CONFIG_LOAD_0 & 1)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize I2C4. */
|
||||
void i2c_init(void) {
|
||||
/* Setup divisor, and clear the bus. */
|
||||
I2C_I2C_CLK_DIVISOR_REGISTER_0 = 0x50001;
|
||||
I2C_I2C_BUS_CLEAR_CONFIG_0 = 0x90003;
|
||||
|
||||
/* Load hardware configuration. */
|
||||
i2c_load_config();
|
||||
|
||||
/* Wait a while until BUS_CLEAR_DONE is set. */
|
||||
for (unsigned int i = 0; i < 10; i++) {
|
||||
timer_wait(20000);
|
||||
if (I2C_INTERRUPT_STATUS_REGISTER_0 & 0x800) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the BUS_CLEAR_STATUS. Result doesn't matter. */
|
||||
I2C_I2C_BUS_CLEAR_STATUS_0;
|
||||
|
||||
/* Read and set the Interrupt Status. */
|
||||
uint32_t int_status = I2C_INTERRUPT_STATUS_REGISTER_0;
|
||||
I2C_INTERRUPT_STATUS_REGISTER_0 = int_status;
|
||||
}
|
||||
|
||||
/* Writes a value to an i2c device. */
|
||||
int i2c_write(unsigned int device, uint32_t val, unsigned int num_bytes) {
|
||||
if (num_bytes > 4) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set device for 7-bit mode. */
|
||||
I2C_I2C_CMD_ADDR0_0 = device << 1;
|
||||
|
||||
/* Load in data to write. */
|
||||
I2C_I2C_CMD_DATA1_0 = val;
|
||||
|
||||
/* Set config with LENGTH = num_bytes, NEW_MASTER_FSM, DEBOUNCE_CNT = 4T. */
|
||||
I2C_I2C_CNFG_0 = ((num_bytes << 1) - 2) | 0x2800;
|
||||
|
||||
i2c_load_config();
|
||||
|
||||
/* Config |= SEND; */
|
||||
I2C_I2C_CNFG_0 |= 0x200;
|
||||
|
||||
|
||||
while (I2C_I2C_STATUS_0 & 0x100) {
|
||||
/* Wait until not busy. */
|
||||
}
|
||||
|
||||
/* Return CMD1_STAT == SL1_XFER_SUCCESSFUL. */
|
||||
return (I2C_I2C_STATUS_0 & 0xF) == 0;
|
||||
}
|
||||
|
||||
/* Reads a value from an i2c device. */
|
||||
int i2c_read(unsigned device, void *dst, unsigned num_bytes) {
|
||||
if (num_bytes > 4) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set device for 7-bit read mode. */
|
||||
I2C_I2C_CMD_ADDR0_0 = (device << 1) | 1;
|
||||
|
||||
/* Set config with LENGTH = num_bytes, NEW_MASTER_FSM, DEBOUNCE_CNT = 4T. */
|
||||
I2C_I2C_CNFG_0 = ((num_bytes << 1) - 2) | 0x2840;
|
||||
|
||||
i2c_load_config();
|
||||
|
||||
/* Config |= SEND; */
|
||||
I2C_I2C_CNFG_0 |= 0x200;
|
||||
|
||||
|
||||
while (I2C_I2C_STATUS_0 & 0x100) {
|
||||
/* Wait until not busy. */
|
||||
}
|
||||
|
||||
/* Ensure success. */
|
||||
if ((I2C_I2C_STATUS_0 & 0xF) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t val = I2C_I2C_CMD_DATA1_0;
|
||||
for (size_t i = 0; i < num_bytes; i++) {
|
||||
((uint8_t *)dst)[i] = ((uint8_t *)&val)[i];
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Queries the value of a register. */
|
||||
int i2c_query(uint8_t device, uint8_t r, void *dst, size_t num_bytes) {
|
||||
/* Limit output size to 32-bits. */
|
||||
if (num_bytes > 4) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Write single byte register ID to device. */
|
||||
if (!i2c_write(device, r, 1)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return i2c_read(device, dst, num_bytes);
|
||||
|
||||
}
|
||||
|
||||
/* Writes a byte val to reg for given device. */
|
||||
int i2c_send_byte_command(unsigned int device, unsigned char reg, unsigned char b) {
|
||||
uint32_t val = (reg) | (b << 8);
|
||||
/* Write 1 byte (reg) + 1 byte (value) */
|
||||
return i2c_write(device, val, 2);
|
||||
}
|
||||
|
||||
void i2c_stop_rtc_alarm(void) {
|
||||
i2c_send_byte_command(MAX77620_RTC_I2C_ADDR, MAX77620_REG_RTCUPDATE0, 0x10);
|
||||
|
||||
uint8_t val = 0;
|
||||
for (int i = 0; i < 14; i++) {
|
||||
if (i2c_query(MAX77620_RTC_I2C_ADDR, 0x0E + i, &val, 1)) {
|
||||
val &= 0x7F;
|
||||
i2c_send_byte_command(MAX77620_RTC_I2C_ADDR, 0x0E + i, val);
|
||||
}
|
||||
}
|
||||
|
||||
i2c_send_byte_command(MAX77620_RTC_I2C_ADDR, MAX77620_REG_RTCUPDATE0, 0x01);
|
||||
}
|
||||
|
||||
void i2c_send_shutdown_cmd(void) {
|
||||
i2c_send_byte_command(MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_PWR_OFF);
|
||||
}
|
||||
51
exosphere/rebootstub/src/i2c.h
Normal file
51
exosphere/rebootstub/src/i2c.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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 EXOSPHERE_REBOOTSTUB_I2C_H
|
||||
#define EXOSPHERE_REBOOTSTUB_I2C_H
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
/* I2C_BASE = I2C4. */
|
||||
#define I2C_BASE (0x7000D000)
|
||||
|
||||
#define MAKE_I2C_REG(ofs) (MAKE_REG32(I2C_BASE + ofs))
|
||||
|
||||
#define I2C_I2C_CNFG_0 MAKE_I2C_REG(0x000)
|
||||
|
||||
#define I2C_I2C_CMD_ADDR0_0 MAKE_I2C_REG(0x004)
|
||||
|
||||
#define I2C_I2C_CMD_DATA1_0 MAKE_I2C_REG(0x00C)
|
||||
|
||||
#define I2C_I2C_STATUS_0 MAKE_I2C_REG(0x01C)
|
||||
|
||||
#define I2C_INTERRUPT_STATUS_REGISTER_0 MAKE_I2C_REG(0x068)
|
||||
|
||||
#define I2C_I2C_CLK_DIVISOR_REGISTER_0 MAKE_I2C_REG(0x06C)
|
||||
|
||||
#define I2C_I2C_BUS_CLEAR_CONFIG_0 MAKE_I2C_REG(0x084)
|
||||
|
||||
#define I2C_I2C_BUS_CLEAR_STATUS_0 MAKE_I2C_REG(0x088)
|
||||
|
||||
|
||||
#define I2C_I2C_CONFIG_LOAD_0 MAKE_I2C_REG(0x08C)
|
||||
|
||||
void i2c_init(void);
|
||||
|
||||
void i2c_stop_rtc_alarm(void);
|
||||
void i2c_send_shutdown_cmd(void);
|
||||
|
||||
#endif
|
||||
360
exosphere/rebootstub/src/max77620.h
Normal file
360
exosphere/rebootstub/src/max77620.h
Normal file
@@ -0,0 +1,360 @@
|
||||
/*
|
||||
* Defining registers address and its bit definitions of MAX77620 and MAX20024
|
||||
*
|
||||
* Copyright (C) 2016 NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2018 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.
|
||||
*/
|
||||
|
||||
#ifndef _MFD_MAX77620_H_
|
||||
#define _MFD_MAX77620_H_
|
||||
|
||||
#define MAX77620_I2C_ADDR 0x3C
|
||||
#define MAX77620_RTC_I2C_ADDR 0x68
|
||||
|
||||
/* RTC Registers */
|
||||
#define MAX77620_REG_RTCINT 0x00
|
||||
#define MAX77620_REG_RTCINTM 0x01
|
||||
#define MAX77620_REG_RTCCNTLM 0x02
|
||||
#define MAX77620_REG_RTCCNTL 0x03
|
||||
#define MAX77620_REG_RTCUPDATE0 0x04
|
||||
#define MAX77620_REG_RTCUPDATE1 0x05
|
||||
#define MAX77620_REG_RTCSMPL 0x06
|
||||
#define MAX77620_REG_RTCSEC 0x07
|
||||
#define MAX77620_REG_RTCMIN 0x08
|
||||
#define MAX77620_REG_RTCHOUR 0x09
|
||||
#define MAX77620_REG_RTCDOW 0x0A
|
||||
#define MAX77620_REG_RTCMONTH 0x0B
|
||||
#define MAX77620_REG_RTCYEAR 0x0C
|
||||
#define MAX77620_REG_RTCDOM 0x0D
|
||||
#define MAX77620_REG_RTCSECA1 0x0E
|
||||
#define MAX77620_REG_RTCMINA1 0x0F
|
||||
#define MAX77620_REG_RTCHOURA1 0x10
|
||||
#define MAX77620_REG_RTCDOWA1 0x11
|
||||
#define MAX77620_REG_RTCMONTHA1 0x12
|
||||
#define MAX77620_REG_RTCYEARA1 0x13
|
||||
#define MAX77620_REG_RTCDOMA1 0x14
|
||||
#define MAX77620_REG_RTCSECA2 0x15
|
||||
#define MAX77620_REG_RTCMINA2 0x16
|
||||
#define MAX77620_REG_RTCHOURA2 0x17
|
||||
#define MAX77620_REG_RTCDOWA2 0x18
|
||||
#define MAX77620_REG_RTCMONTHA2 0x19
|
||||
#define MAX77620_REG_RTCYEARA2 0x1A
|
||||
#define MAX77620_REG_RTCDOMA2 0x1B
|
||||
|
||||
/* GLOBAL, PMIC, GPIO, FPS, ONOFFC, CID Registers */
|
||||
#define MAX77620_REG_CNFGGLBL1 0x00
|
||||
#define MAX77620_REG_CNFGGLBL2 0x01
|
||||
#define MAX77620_REG_CNFGGLBL3 0x02
|
||||
#define MAX77620_REG_CNFG1_32K 0x03
|
||||
#define MAX77620_REG_CNFGBBC 0x04
|
||||
#define MAX77620_REG_IRQTOP 0x05
|
||||
#define MAX77620_REG_INTLBT 0x06
|
||||
#define MAX77620_REG_IRQSD 0x07
|
||||
#define MAX77620_REG_IRQ_LVL2_L0_7 0x08
|
||||
#define MAX77620_REG_IRQ_LVL2_L8 0x09
|
||||
#define MAX77620_REG_IRQ_LVL2_GPIO 0x0A
|
||||
#define MAX77620_REG_ONOFFIRQ 0x0B
|
||||
#define MAX77620_REG_NVERC 0x0C
|
||||
#define MAX77620_REG_IRQTOPM 0x0D
|
||||
#define MAX77620_REG_INTENLBT 0x0E
|
||||
#define MAX77620_REG_IRQMASKSD 0x0F
|
||||
#define MAX77620_REG_IRQ_MSK_L0_7 0x10
|
||||
#define MAX77620_REG_IRQ_MSK_L8 0x11
|
||||
#define MAX77620_REG_ONOFFIRQM 0x12
|
||||
#define MAX77620_REG_STATLBT 0x13
|
||||
#define MAX77620_REG_STATSD 0x14
|
||||
#define MAX77620_REG_ONOFFSTAT 0x15
|
||||
|
||||
/* SD and LDO Registers */
|
||||
#define MAX77620_REG_SD0 0x16
|
||||
#define MAX77620_REG_SD1 0x17
|
||||
#define MAX77620_REG_SD2 0x18
|
||||
#define MAX77620_REG_SD3 0x19
|
||||
#define MAX77620_REG_SD4 0x1A
|
||||
#define MAX77620_REG_DVSSD0 0x1B
|
||||
#define MAX77620_REG_DVSSD1 0x1C
|
||||
#define MAX77620_REG_SD0_CFG 0x1D
|
||||
#define MAX77620_REG_SD1_CFG 0x1E
|
||||
#define MAX77620_REG_SD2_CFG 0x1F
|
||||
#define MAX77620_REG_SD3_CFG 0x20
|
||||
#define MAX77620_REG_SD4_CFG 0x21
|
||||
#define MAX77620_REG_SD_CFG2 0x22
|
||||
#define MAX77620_REG_LDO0_CFG 0x23
|
||||
#define MAX77620_REG_LDO0_CFG2 0x24
|
||||
#define MAX77620_REG_LDO1_CFG 0x25
|
||||
#define MAX77620_REG_LDO1_CFG2 0x26
|
||||
#define MAX77620_REG_LDO2_CFG 0x27
|
||||
#define MAX77620_REG_LDO2_CFG2 0x28
|
||||
#define MAX77620_REG_LDO3_CFG 0x29
|
||||
#define MAX77620_REG_LDO3_CFG2 0x2A
|
||||
#define MAX77620_REG_LDO4_CFG 0x2B
|
||||
#define MAX77620_REG_LDO4_CFG2 0x2C
|
||||
#define MAX77620_REG_LDO5_CFG 0x2D
|
||||
#define MAX77620_REG_LDO5_CFG2 0x2E
|
||||
#define MAX77620_REG_LDO6_CFG 0x2F
|
||||
#define MAX77620_REG_LDO6_CFG2 0x30
|
||||
#define MAX77620_REG_LDO7_CFG 0x31
|
||||
#define MAX77620_REG_LDO7_CFG2 0x32
|
||||
#define MAX77620_REG_LDO8_CFG 0x33
|
||||
#define MAX77620_REG_LDO8_CFG2 0x34
|
||||
#define MAX77620_REG_LDO_CFG3 0x35
|
||||
|
||||
#define MAX77620_LDO_SLEW_RATE_MASK 0x1
|
||||
|
||||
/* LDO Configuration 3 */
|
||||
#define MAX77620_TRACK4_MASK (1 << 5)
|
||||
#define MAX77620_TRACK4_SHIFT 5
|
||||
|
||||
/* Voltage */
|
||||
#define MAX77620_SDX_VOLT_MASK 0xFF
|
||||
#define MAX77620_SD0_VOLT_MASK 0x3F
|
||||
#define MAX77620_SD1_VOLT_MASK 0x7F
|
||||
#define MAX77620_LDO_VOLT_MASK 0x3F
|
||||
|
||||
#define MAX77620_REG_GPIO0 0x36
|
||||
#define MAX77620_REG_GPIO1 0x37
|
||||
#define MAX77620_REG_GPIO2 0x38
|
||||
#define MAX77620_REG_GPIO3 0x39
|
||||
#define MAX77620_REG_GPIO4 0x3A
|
||||
#define MAX77620_REG_GPIO5 0x3B
|
||||
#define MAX77620_REG_GPIO6 0x3C
|
||||
#define MAX77620_REG_GPIO7 0x3D
|
||||
#define MAX77620_REG_PUE_GPIO 0x3E
|
||||
#define MAX77620_REG_PDE_GPIO 0x3F
|
||||
#define MAX77620_REG_AME_GPIO 0x40
|
||||
#define MAX77620_REG_ONOFFCNFG1 0x41
|
||||
#define MAX77620_REG_ONOFFCNFG2 0x42
|
||||
|
||||
/* FPS Registers */
|
||||
#define MAX77620_REG_FPS_CFG0 0x43
|
||||
#define MAX77620_REG_FPS_CFG1 0x44
|
||||
#define MAX77620_REG_FPS_CFG2 0x45
|
||||
#define MAX77620_REG_FPS_LDO0 0x46
|
||||
#define MAX77620_REG_FPS_LDO1 0x47
|
||||
#define MAX77620_REG_FPS_LDO2 0x48
|
||||
#define MAX77620_REG_FPS_LDO3 0x49
|
||||
#define MAX77620_REG_FPS_LDO4 0x4A
|
||||
#define MAX77620_REG_FPS_LDO5 0x4B
|
||||
#define MAX77620_REG_FPS_LDO6 0x4C
|
||||
#define MAX77620_REG_FPS_LDO7 0x4D
|
||||
#define MAX77620_REG_FPS_LDO8 0x4E
|
||||
#define MAX77620_REG_FPS_SD0 0x4F
|
||||
#define MAX77620_REG_FPS_SD1 0x50
|
||||
#define MAX77620_REG_FPS_SD2 0x51
|
||||
#define MAX77620_REG_FPS_SD3 0x52
|
||||
#define MAX77620_REG_FPS_SD4 0x53
|
||||
#define MAX77620_REG_FPS_NONE 0
|
||||
|
||||
#define MAX77620_FPS_SRC_MASK 0xC0
|
||||
#define MAX77620_FPS_SRC_SHIFT 6
|
||||
#define MAX77620_FPS_PU_PERIOD_MASK 0x38
|
||||
#define MAX77620_FPS_PU_PERIOD_SHIFT 3
|
||||
#define MAX77620_FPS_PD_PERIOD_MASK 0x07
|
||||
#define MAX77620_FPS_PD_PERIOD_SHIFT 0
|
||||
#define MAX77620_FPS_TIME_PERIOD_MASK 0x38
|
||||
#define MAX77620_FPS_TIME_PERIOD_SHIFT 3
|
||||
#define MAX77620_FPS_EN_SRC_MASK 0x06
|
||||
#define MAX77620_FPS_EN_SRC_SHIFT 1
|
||||
#define MAX77620_FPS_ENFPS_SW_MASK 0x01
|
||||
#define MAX77620_FPS_ENFPS_SW 0x01
|
||||
|
||||
/* Minimum and maximum FPS period time (in microseconds) are
|
||||
* different for MAX77620 and Max20024.
|
||||
*/
|
||||
#define MAX77620_FPS_PERIOD_MIN_US 40
|
||||
#define MAX20024_FPS_PERIOD_MIN_US 20
|
||||
|
||||
#define MAX77620_FPS_PERIOD_MAX_US 2560
|
||||
#define MAX20024_FPS_PERIOD_MAX_US 5120
|
||||
|
||||
#define MAX77620_REG_FPS_GPIO1 0x54
|
||||
#define MAX77620_REG_FPS_GPIO2 0x55
|
||||
#define MAX77620_REG_FPS_GPIO3 0x56
|
||||
#define MAX77620_REG_FPS_RSO 0x57
|
||||
#define MAX77620_REG_CID0 0x58
|
||||
#define MAX77620_REG_CID1 0x59
|
||||
#define MAX77620_REG_CID2 0x5A
|
||||
#define MAX77620_REG_CID3 0x5B
|
||||
#define MAX77620_REG_CID4 0x5C
|
||||
#define MAX77620_REG_CID5 0x5D
|
||||
|
||||
#define MAX77620_REG_DVSSD4 0x5E
|
||||
#define MAX20024_REG_MAX_ADD 0x70
|
||||
|
||||
#define MAX77620_CID_DIDM_MASK 0xF0
|
||||
#define MAX77620_CID_DIDM_SHIFT 4
|
||||
|
||||
/* CNCG2SD */
|
||||
#define MAX77620_SD_CNF2_ROVS_EN_SD1 (1 << 1)
|
||||
#define MAX77620_SD_CNF2_ROVS_EN_SD0 (1 << 2)
|
||||
|
||||
/* Device Identification Metal */
|
||||
#define MAX77620_CID5_DIDM(n) (((n) >> 4) & 0xF)
|
||||
/* Device Indentification OTP */
|
||||
#define MAX77620_CID5_DIDO(n) ((n) & 0xF)
|
||||
|
||||
/* SD CNFG1 */
|
||||
#define MAX77620_SD_SR_MASK 0xC0
|
||||
#define MAX77620_SD_SR_SHIFT 6
|
||||
#define MAX77620_SD_POWER_MODE_MASK 0x30
|
||||
#define MAX77620_SD_POWER_MODE_SHIFT 4
|
||||
#define MAX77620_SD_CFG1_ADE_MASK (1 << 3)
|
||||
#define MAX77620_SD_CFG1_ADE_DISABLE 0
|
||||
#define MAX77620_SD_CFG1_ADE_ENABLE (1 << 3)
|
||||
#define MAX77620_SD_FPWM_MASK 0x04
|
||||
#define MAX77620_SD_FPWM_SHIFT 2
|
||||
#define MAX77620_SD_FSRADE_MASK 0x01
|
||||
#define MAX77620_SD_FSRADE_SHIFT 0
|
||||
#define MAX77620_SD_CFG1_FPWM_SD_MASK (1 << 2)
|
||||
#define MAX77620_SD_CFG1_FPWM_SD_SKIP 0
|
||||
#define MAX77620_SD_CFG1_FPWM_SD_FPWM (1 << 2)
|
||||
#define MAX20024_SD_CFG1_MPOK_MASK (1 << 1)
|
||||
#define MAX77620_SD_CFG1_FSRADE_SD_MASK (1 << 0)
|
||||
#define MAX77620_SD_CFG1_FSRADE_SD_DISABLE 0
|
||||
#define MAX77620_SD_CFG1_FSRADE_SD_ENABLE (1 << 0)
|
||||
|
||||
/* LDO_CNFG2 */
|
||||
#define MAX77620_LDO_POWER_MODE_MASK 0xC0
|
||||
#define MAX77620_LDO_POWER_MODE_SHIFT 6
|
||||
#define MAX20024_LDO_CFG2_MPOK_MASK (1 << 2)
|
||||
#define MAX77620_LDO_CFG2_ADE_MASK (1 << 1)
|
||||
#define MAX77620_LDO_CFG2_ADE_DISABLE 0
|
||||
#define MAX77620_LDO_CFG2_ADE_ENABLE (1 << 1)
|
||||
#define MAX77620_LDO_CFG2_SS_MASK (1 << 0)
|
||||
#define MAX77620_LDO_CFG2_SS_FAST (1 << 0)
|
||||
#define MAX77620_LDO_CFG2_SS_SLOW 0
|
||||
|
||||
#define MAX77620_IRQ_TOP_GLBL_MASK (1 << 7)
|
||||
#define MAX77620_IRQ_TOP_SD_MASK (1 << 6)
|
||||
#define MAX77620_IRQ_TOP_LDO_MASK (1 << 5)
|
||||
#define MAX77620_IRQ_TOP_GPIO_MASK (1 << 4)
|
||||
#define MAX77620_IRQ_TOP_RTC_MASK (1 << 3)
|
||||
#define MAX77620_IRQ_TOP_32K_MASK (1 << 2)
|
||||
#define MAX77620_IRQ_TOP_ONOFF_MASK (1 << 1)
|
||||
|
||||
#define MAX77620_IRQ_LBM_MASK (1 << 3)
|
||||
#define MAX77620_IRQ_TJALRM1_MASK (1 << 2)
|
||||
#define MAX77620_IRQ_TJALRM2_MASK (1 << 1)
|
||||
|
||||
#define MAX77620_CNFG_GPIO_DRV_MASK (1 << 0)
|
||||
#define MAX77620_CNFG_GPIO_DRV_PUSHPULL (1 << 0)
|
||||
#define MAX77620_CNFG_GPIO_DRV_OPENDRAIN 0
|
||||
#define MAX77620_CNFG_GPIO_DIR_MASK (1 << 1)
|
||||
#define MAX77620_CNFG_GPIO_DIR_INPUT (1 << 1)
|
||||
#define MAX77620_CNFG_GPIO_DIR_OUTPUT 0
|
||||
#define MAX77620_CNFG_GPIO_INPUT_VAL_MASK (1 << 2)
|
||||
#define MAX77620_CNFG_GPIO_OUTPUT_VAL_MASK (1 << 3)
|
||||
#define MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH (1 << 3)
|
||||
#define MAX77620_CNFG_GPIO_OUTPUT_VAL_LOW 0
|
||||
#define MAX77620_CNFG_GPIO_INT_MASK (0x3 << 4)
|
||||
#define MAX77620_CNFG_GPIO_INT_FALLING (1 << 4)
|
||||
#define MAX77620_CNFG_GPIO_INT_RISING (1 << 5)
|
||||
#define MAX77620_CNFG_GPIO_DBNC_MASK (0x3 << 6)
|
||||
#define MAX77620_CNFG_GPIO_DBNC_None (0x0 << 6)
|
||||
#define MAX77620_CNFG_GPIO_DBNC_8ms (0x1 << 6)
|
||||
#define MAX77620_CNFG_GPIO_DBNC_16ms (0x2 << 6)
|
||||
#define MAX77620_CNFG_GPIO_DBNC_32ms (0x3 << 6)
|
||||
|
||||
#define MAX77620_IRQ_LVL2_GPIO_EDGE0 (1 << 0)
|
||||
#define MAX77620_IRQ_LVL2_GPIO_EDGE1 (1 << 1)
|
||||
#define MAX77620_IRQ_LVL2_GPIO_EDGE2 (1 << 2)
|
||||
#define MAX77620_IRQ_LVL2_GPIO_EDGE3 (1 << 3)
|
||||
#define MAX77620_IRQ_LVL2_GPIO_EDGE4 (1 << 4)
|
||||
#define MAX77620_IRQ_LVL2_GPIO_EDGE5 (1 << 5)
|
||||
#define MAX77620_IRQ_LVL2_GPIO_EDGE6 (1 << 6)
|
||||
#define MAX77620_IRQ_LVL2_GPIO_EDGE7 (1 << 7)
|
||||
|
||||
#define MAX77620_CNFG1_32K_OUT0_EN (1 << 2)
|
||||
|
||||
#define MAX77620_ONOFFCNFG1_SFT_RST (1 << 7)
|
||||
#define MAX77620_ONOFFCNFG1_MRT_MASK 0x38
|
||||
#define MAX77620_ONOFFCNFG1_MRT_SHIFT 0x3
|
||||
#define MAX77620_ONOFFCNFG1_SLPEN (1 << 2)
|
||||
#define MAX77620_ONOFFCNFG1_PWR_OFF (1 << 1)
|
||||
#define MAX20024_ONOFFCNFG1_CLRSE 0x18
|
||||
|
||||
#define MAX77620_ONOFFCNFG2_SFT_RST_WK (1 << 7)
|
||||
#define MAX77620_ONOFFCNFG2_WD_RST_WK (1 << 6)
|
||||
#define MAX77620_ONOFFCNFG2_SLP_LPM_MSK (1 << 5)
|
||||
#define MAX77620_ONOFFCNFG2_WK_ALARM1 (1 << 2)
|
||||
#define MAX77620_ONOFFCNFG2_WK_EN0 (1 << 0)
|
||||
|
||||
#define MAX77620_GLBLM_MASK (1 << 0)
|
||||
|
||||
#define MAX77620_WDTC_MASK 0x3
|
||||
#define MAX77620_WDTOFFC (1 << 4)
|
||||
#define MAX77620_WDTSLPC (1 << 3)
|
||||
#define MAX77620_WDTEN (1 << 2)
|
||||
|
||||
#define MAX77620_TWD_MASK 0x3
|
||||
#define MAX77620_TWD_2s 0x0
|
||||
#define MAX77620_TWD_16s 0x1
|
||||
#define MAX77620_TWD_64s 0x2
|
||||
#define MAX77620_TWD_128s 0x3
|
||||
|
||||
#define MAX77620_CNFGGLBL1_LBDAC_EN (1 << 7)
|
||||
#define MAX77620_CNFGGLBL1_MPPLD (1 << 6)
|
||||
#define MAX77620_CNFGGLBL1_LBHYST ((1 << 5) | (1 << 4))
|
||||
#define MAX77620_CNFGGLBL1_LBHYST_N (1 << 4)
|
||||
#define MAX77620_CNFGGLBL1_LBDAC 0x0E
|
||||
#define MAX77620_CNFGGLBL1_LBDAC_N (1 << 1)
|
||||
#define MAX77620_CNFGGLBL1_LBRSTEN (1 << 0)
|
||||
|
||||
/* CNFG BBC registers */
|
||||
#define MAX77620_CNFGBBC_ENABLE (1 << 0)
|
||||
#define MAX77620_CNFGBBC_CURRENT_MASK 0x06
|
||||
#define MAX77620_CNFGBBC_CURRENT_SHIFT 1
|
||||
#define MAX77620_CNFGBBC_VOLTAGE_MASK 0x18
|
||||
#define MAX77620_CNFGBBC_VOLTAGE_SHIFT 3
|
||||
#define MAX77620_CNFGBBC_LOW_CURRENT_DISABLE (1 << 5)
|
||||
#define MAX77620_CNFGBBC_RESISTOR_MASK 0xC0
|
||||
#define MAX77620_CNFGBBC_RESISTOR_SHIFT 6
|
||||
|
||||
#define MAX77620_FPS_COUNT 3
|
||||
|
||||
/* Interrupts */
|
||||
enum {
|
||||
MAX77620_IRQ_TOP_GLBL, /* Low-Battery */
|
||||
MAX77620_IRQ_TOP_SD, /* SD power fail */
|
||||
MAX77620_IRQ_TOP_LDO, /* LDO power fail */
|
||||
MAX77620_IRQ_TOP_GPIO, /* TOP GPIO internal int to MAX77620 */
|
||||
MAX77620_IRQ_TOP_RTC, /* RTC */
|
||||
MAX77620_IRQ_TOP_32K, /* 32kHz oscillator */
|
||||
MAX77620_IRQ_TOP_ONOFF, /* ON/OFF oscillator */
|
||||
MAX77620_IRQ_LBT_MBATLOW, /* Thermal alarm status, > 120C */
|
||||
MAX77620_IRQ_LBT_TJALRM1, /* Thermal alarm status, > 120C */
|
||||
MAX77620_IRQ_LBT_TJALRM2, /* Thermal alarm status, > 140C */
|
||||
};
|
||||
|
||||
/* GPIOs */
|
||||
enum {
|
||||
MAX77620_GPIO0,
|
||||
MAX77620_GPIO1,
|
||||
MAX77620_GPIO2,
|
||||
MAX77620_GPIO3,
|
||||
MAX77620_GPIO4,
|
||||
MAX77620_GPIO5,
|
||||
MAX77620_GPIO6,
|
||||
MAX77620_GPIO7,
|
||||
MAX77620_GPIO_NR,
|
||||
};
|
||||
|
||||
/* FPS Source */
|
||||
enum max77620_fps_src {
|
||||
MAX77620_FPS_SRC_0,
|
||||
MAX77620_FPS_SRC_1,
|
||||
MAX77620_FPS_SRC_2,
|
||||
MAX77620_FPS_SRC_NONE,
|
||||
MAX77620_FPS_SRC_DEF,
|
||||
};
|
||||
|
||||
enum max77620_chip_id {
|
||||
MAX77620,
|
||||
MAX20024,
|
||||
};
|
||||
|
||||
#endif /* _MFD_MAX77620_H_ */
|
||||
30
exosphere/rebootstub/src/shutdown.c
Normal file
30
exosphere/rebootstub/src/shutdown.c
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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 "utils.h"
|
||||
#include "i2c.h"
|
||||
#include "timer.h"
|
||||
|
||||
void do_shutdown(void) {
|
||||
/* Initialize i2c. */
|
||||
i2c_init();
|
||||
|
||||
/* Stop alarm, shutdown. */
|
||||
i2c_stop_rtc_alarm();
|
||||
i2c_send_shutdown_cmd();
|
||||
|
||||
while (true) { }
|
||||
}
|
||||
@@ -18,11 +18,16 @@
|
||||
.align 4
|
||||
.global _start
|
||||
_start:
|
||||
b crt0
|
||||
ldr r0, reboot_type
|
||||
cmp r0, #0x0
|
||||
beq do_shutdown
|
||||
b jump_to_reboot_payload
|
||||
reboot_type:
|
||||
.word 0x00000001
|
||||
|
||||
.global crt0
|
||||
.type crt0, %function
|
||||
crt0:
|
||||
.global jump_to_reboot_payload
|
||||
.type jump_to_reboot_payload, %function
|
||||
jump_to_reboot_payload:
|
||||
@ clear all registers
|
||||
ldr r0, =0x52425430 @ RBT0
|
||||
mov r1, #0x0
|
||||
|
||||
33
exosphere/rebootstub/src/timer.h
Normal file
33
exosphere/rebootstub/src/timer.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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 EXOSPHERE_REBOOTSTUB_TIMER_H
|
||||
#define EXOSPHERE_REBOOTSTUB_TIMER_H
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#define TIMERUS_CNTR_1US_0 MAKE_REG32(0x60005010)
|
||||
|
||||
static inline void timer_wait(uint32_t microseconds) {
|
||||
uint32_t old_time = TIMERUS_CNTR_1US_0;
|
||||
while (TIMERUS_CNTR_1US_0 - old_time <= microseconds) {
|
||||
/* Spin-lock. */
|
||||
}
|
||||
}
|
||||
|
||||
void spinlock_wait(uint32_t count);
|
||||
|
||||
#endif
|
||||
38
exosphere/rebootstub/src/utils.h
Normal file
38
exosphere/rebootstub/src/utils.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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 EXOSPHERE_REBOOTSTUB_UTILS_H
|
||||
#define EXOSPHERE_REBOOTSTUB_UTILS_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define BIT(n) (1u << (n))
|
||||
#define BITL(n) (1ull << (n))
|
||||
#define MASK(n) (BIT(n) - 1)
|
||||
#define MASKL(n) (BITL(n) - 1)
|
||||
#define MASK2(a,b) (MASK(a) & ~MASK(b))
|
||||
#define MASK2L(a,b) (MASKL(a) & ~MASKL(b))
|
||||
|
||||
#define MAKE_REG32(a) (*(volatile uint32_t *)(a))
|
||||
|
||||
#define ALIGN(m) __attribute__((aligned(m)))
|
||||
#define PACKED __attribute__((packed))
|
||||
|
||||
#define ALINLINE __attribute__((always_inline))
|
||||
|
||||
#endif
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
#undef MAILBOX_NX_BOOTLOADER_BASE
|
||||
#undef TIMERS_BASE
|
||||
#define MAILBOX_NX_BOOTLOADER_BASE (MMIO_GET_DEVICE_PA(MMIO_DEVID_NXBOOTLOADER_MAILBOX))
|
||||
#define MAILBOX_NX_BOOTLOADER_BASE(targetfw) (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_700) ? (MMIO_GET_DEVICE_7X_PA(MMIO_DEVID_NXBOOTLOADER_MAILBOX)) : (MMIO_GET_DEVICE_PA(MMIO_DEVID_NXBOOTLOADER_MAILBOX))
|
||||
#define TIMERS_BASE (MMIO_GET_DEVICE_PA(MMIO_DEVID_TMRs_WDTs))
|
||||
|
||||
extern const uint8_t __start_cold[];
|
||||
@@ -48,13 +48,16 @@ static void identity_map_all_mappings(uintptr_t *mmu_l1_tbl, uintptr_t *mmu_l3_t
|
||||
}
|
||||
}
|
||||
|
||||
static void mmio_map_all_devices(uintptr_t *mmu_l3_tbl) {
|
||||
static void mmio_map_all_devices(uintptr_t *mmu_l3_tbl, unsigned int target_firmware) {
|
||||
static const uintptr_t pas[] = { TUPLE_FOLD_LEFT_0(EVAL(MMIO_DEVID_MAX), _MMAPDEV, COMMA) };
|
||||
static const size_t sizes[] = { TUPLE_FOLD_LEFT_1(EVAL(MMIO_DEVID_MAX), _MMAPDEV, COMMA) };
|
||||
static const bool is_secure[] = { TUPLE_FOLD_LEFT_2(EVAL(MMIO_DEVID_MAX), _MMAPDEV, COMMA) };
|
||||
|
||||
static const uintptr_t pas_7x[] = { TUPLE_FOLD_LEFT_0(EVAL(MMIO_DEVID_MAX), _MMAPDEV7X, COMMA) };
|
||||
|
||||
for(size_t i = 0, offset = 0; i < MMIO_DEVID_MAX; i++) {
|
||||
mmio_map_device(mmu_l3_tbl, MMIO_BASE + offset, pas[i], sizes[i], is_secure[i]);
|
||||
uintptr_t pa = (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_700) ? pas[i] : pas_7x[i];
|
||||
mmio_map_device(mmu_l3_tbl, MMIO_BASE + offset, pa, sizes[i], is_secure[i]);
|
||||
offset += sizes[i];
|
||||
offset += 0x1000;
|
||||
}
|
||||
@@ -127,7 +130,7 @@ static void configure_ttbls(unsigned int target_firmware) {
|
||||
mmu_map_table(2, mmu_l2_tbl, 0x1F0000000ull, mmu_l3_tbl, 0);
|
||||
|
||||
identity_map_all_mappings(mmu_l1_tbl, mmu_l3_tbl);
|
||||
mmio_map_all_devices(mmu_l3_tbl);
|
||||
mmio_map_all_devices(mmu_l3_tbl, target_firmware);
|
||||
lp0_entry_map_all_ram_segments(mmu_l3_tbl);
|
||||
warmboot_map_all_ram_segments(mmu_l3_tbl);
|
||||
tzram_map_all_segments(mmu_l3_tbl, target_firmware);
|
||||
|
||||
@@ -80,6 +80,34 @@ uint32_t configitem_set(bool privileged, ConfigItem item, uint64_t value) {
|
||||
while (1) { }
|
||||
}
|
||||
break;
|
||||
case CONFIGITEM_NEEDS_SHUTDOWN:
|
||||
/* Force a shutdown, if requested. */
|
||||
{
|
||||
if (value == 0) {
|
||||
return 0;
|
||||
}
|
||||
/* Set reboot kind = warmboot. */
|
||||
MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x450ull) = 0x1;
|
||||
/* Patch SDRAM init to perform an SVC immediately after second write */
|
||||
MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x634ull) = 0x2E38DFFF;
|
||||
MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x638ull) = 0x6001DC28;
|
||||
/* Set SVC handler to jump to reboot stub in IRAM. */
|
||||
MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x520ull) = 0x4003F000;
|
||||
MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x53Cull) = 0x6000F208;
|
||||
|
||||
/* Copy reboot stub payload. */
|
||||
ams_map_irampage(0x4003F000);
|
||||
for (unsigned int i = 0; i < rebootstub_bin_size; i += 4) {
|
||||
MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_AMS_IRAM_PAGE) + i) = read32le(rebootstub_bin, i);
|
||||
}
|
||||
/* Tell rebootstub to shut down. */
|
||||
MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_AMS_IRAM_PAGE) + 0x10) = 0x0;
|
||||
ams_unmap_irampage();
|
||||
|
||||
MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x400ull) = 0x10;
|
||||
while (1) { }
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 2;
|
||||
}
|
||||
@@ -228,6 +256,10 @@ uint32_t configitem_get(bool privileged, ConfigItem item, uint64_t *p_outvalue)
|
||||
/* UNOFFICIAL: The fact that we are executing means we aren't in the process of rebooting. */
|
||||
*p_outvalue = 0;
|
||||
break;
|
||||
case CONFIGITEM_NEEDS_SHUTDOWN:
|
||||
/* UNOFFICIAL: The fact that we are executing means we aren't in the process of shutting down. */
|
||||
*p_outvalue = 0;
|
||||
break;
|
||||
default:
|
||||
result = 2;
|
||||
break;
|
||||
|
||||
@@ -42,6 +42,7 @@ typedef enum {
|
||||
/* These are unofficial, for usage by Exosphere. */
|
||||
CONFIGITEM_EXOSPHERE_VERSION = 65000,
|
||||
CONFIGITEM_NEEDS_REBOOT = 65001,
|
||||
CONFIGITEM_NEEDS_SHUTDOWN = 65002,
|
||||
} ConfigItem;
|
||||
|
||||
#define REBOOT_KIND_NO_REBOOT 0
|
||||
|
||||
@@ -22,12 +22,7 @@
|
||||
#include "mmu.h"
|
||||
#include "memory_map.h"
|
||||
|
||||
#define MAILBOX_BASE (MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_NXBOOTLOADER_MAILBOX))
|
||||
|
||||
/* TODO: Should this be at a non-static location? */
|
||||
#define MAILBOX_EXOSPHERE_CONFIG (*((volatile exosphere_config_t *)(MAILBOX_BASE + 0xE40ULL)))
|
||||
|
||||
static exosphere_config_t g_exosphere_cfg = {MAGIC_EXOSPHERE_BOOTCONFIG, ATMOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG, EXOSPHERE_FLAGS_DEFAULT};
|
||||
static exosphere_config_t g_exosphere_cfg = {MAGIC_EXOSPHERE_CONFIG, ATMOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG, EXOSPHERE_FLAGS_DEFAULT};
|
||||
static bool g_has_loaded_config = false;
|
||||
|
||||
#define EXOSPHERE_CHECK_FLAG(flag) ((g_exosphere_cfg.flags & flag) != 0)
|
||||
@@ -42,11 +37,8 @@ unsigned int exosphere_load_config(void) {
|
||||
|
||||
const unsigned int magic = MAILBOX_EXOSPHERE_CONFIG.magic;
|
||||
|
||||
if (magic == MAGIC_EXOSPHERE_BOOTCONFIG) {
|
||||
if (magic == MAGIC_EXOSPHERE_CONFIG) {
|
||||
g_exosphere_cfg = MAILBOX_EXOSPHERE_CONFIG;
|
||||
} else if (magic == MAGIC_EXOSPHERE_BOOTCONFIG_0) {
|
||||
g_exosphere_cfg = MAILBOX_EXOSPHERE_CONFIG;
|
||||
g_exosphere_cfg.flags = EXOSPHERE_FLAGS_DEFAULT;
|
||||
}
|
||||
|
||||
return g_exosphere_cfg.target_firmware;
|
||||
|
||||
@@ -25,17 +25,15 @@
|
||||
|
||||
/* This serves to set configuration for *exosphere itself*, separate from the SecMon Exosphere mimics. */
|
||||
|
||||
/* "XBC0" */
|
||||
#define MAGIC_EXOSPHERE_BOOTCONFIG_0 (0x30434258)
|
||||
/* "XBC1" */
|
||||
#define MAGIC_EXOSPHERE_BOOTCONFIG (0x31434258)
|
||||
/* "EXO0" */
|
||||
#define MAGIC_EXOSPHERE_CONFIG (0x304F5845)
|
||||
|
||||
#define EXOSPHERE_LOOSEN_PACKAGE2_RESTRICTIONS_FOR_DEBUG 1
|
||||
|
||||
#define MAILBOX_BASE_PHYS (MMIO_GET_DEVICE_PA(MMIO_DEVID_NXBOOTLOADER_MAILBOX))
|
||||
#define MAILBOX_EXOSPHERE_CONFIG (*((volatile exosphere_config_t *)(0x8000F000ull)))
|
||||
|
||||
/* TODO: Should this be at a non-static location? */
|
||||
#define MAILBOX_EXOSPHERE_CONFIG_PHYS (*((volatile exosphere_config_t *)(MAILBOX_BASE_PHYS + 0xE40ULL)))
|
||||
/* Exosphere config in DRAM shares physical/virtual mapping. */
|
||||
#define MAILBOX_EXOSPHERE_CONFIG_PHYS MAILBOX_EXOSPHERE_CONFIG
|
||||
|
||||
#define EXOSPHERE_FLAGS_DEFAULT 0x00000000
|
||||
#define EXOSPHERE_FLAG_PERFORM_620_KEYGEN (1 << 0u)
|
||||
@@ -46,6 +44,7 @@ typedef struct {
|
||||
unsigned int magic;
|
||||
unsigned int target_firmware;
|
||||
unsigned int flags;
|
||||
unsigned int reserved;
|
||||
} exosphere_config_t;
|
||||
|
||||
unsigned int exosphere_load_config(void);
|
||||
@@ -56,7 +55,7 @@ unsigned int exosphere_should_override_debugmode_user(void);
|
||||
|
||||
static inline unsigned int exosphere_get_target_firmware_for_init(void) {
|
||||
const unsigned int magic = MAILBOX_EXOSPHERE_CONFIG_PHYS.magic;
|
||||
if (magic == MAGIC_EXOSPHERE_BOOTCONFIG || magic == MAGIC_EXOSPHERE_BOOTCONFIG_0) {
|
||||
if (magic == MAGIC_EXOSPHERE_CONFIG) {
|
||||
return MAILBOX_EXOSPHERE_CONFIG_PHYS.target_firmware;
|
||||
} else {
|
||||
return ATMOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG;
|
||||
|
||||
@@ -41,6 +41,7 @@ static const uint8_t mkey_vectors_dev[MASTERKEY_REVISION_MAX][0x10] =
|
||||
{0x9B, 0x84, 0x76, 0x14, 0x72, 0x94, 0x52, 0xCB, 0x54, 0x92, 0x9B, 0xC4, 0x8C, 0x5B, 0x0F, 0xBA}, /* Master key 03 encrypted with Master key 04. */
|
||||
{0x78, 0xD5, 0xF1, 0x20, 0x3D, 0x16, 0xE9, 0x30, 0x32, 0x27, 0x34, 0x6F, 0xCF, 0xE0, 0x27, 0xDC}, /* Master key 04 encrypted with Master key 05. */
|
||||
{0x6F, 0xD2, 0x84, 0x1D, 0x05, 0xEC, 0x40, 0x94, 0x5F, 0x18, 0xB3, 0x81, 0x09, 0x98, 0x8D, 0x4E}, /* Master key 05 encrypted with Master key 06. */
|
||||
{0x37, 0xAF, 0xAB, 0x35, 0x79, 0x09, 0xD9, 0x48, 0x29, 0xD2, 0xDB, 0xA5, 0xA5, 0xF5, 0x30, 0x19}, /* Master key 06 encrypted with Master key 07. */
|
||||
};
|
||||
|
||||
/* Retail unit keys. */
|
||||
@@ -53,6 +54,7 @@ static const uint8_t mkey_vectors[MASTERKEY_REVISION_MAX][0x10] =
|
||||
{0x6E, 0x7D, 0x2D, 0xC3, 0x0F, 0x59, 0xC8, 0xFA, 0x87, 0xA8, 0x2E, 0xD5, 0x89, 0x5E, 0xF3, 0xE9}, /* Master key 03 encrypted with Master key 04. */
|
||||
{0xEB, 0xF5, 0x6F, 0x83, 0x61, 0x9E, 0xF8, 0xFA, 0xE0, 0x87, 0xD7, 0xA1, 0x4E, 0x25, 0x36, 0xEE}, /* Master key 04 encrypted with Master key 05. */
|
||||
{0x1E, 0x1E, 0x22, 0xC0, 0x5A, 0x33, 0x3C, 0xB9, 0x0B, 0xA9, 0x03, 0x04, 0xBA, 0xDB, 0x07, 0x57}, /* Master key 05 encrypted with Master key 06. */
|
||||
{0xA4, 0xD4, 0x52, 0x6F, 0xD1, 0xE4, 0x36, 0xAA, 0x9F, 0xCB, 0x61, 0x27, 0x1C, 0x67, 0x65, 0x1F}, /* Master key 06 encrypted with Master key 07. */
|
||||
};
|
||||
|
||||
bool check_mkey_revision(unsigned int revision, bool is_retail) {
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
/* This is glue code to enable master key support across versions. */
|
||||
|
||||
/* TODO: Update to 0x8 on release of new master key. */
|
||||
#define MASTERKEY_REVISION_MAX 0x7
|
||||
/* TODO: Update to 0x9 on release of new master key. */
|
||||
#define MASTERKEY_REVISION_MAX 0x8
|
||||
|
||||
#define MASTERKEY_REVISION_100_230 0x00
|
||||
#define MASTERKEY_REVISION_300 0x01
|
||||
@@ -28,7 +28,8 @@
|
||||
#define MASTERKEY_REVISION_400_410 0x03
|
||||
#define MASTERKEY_REVISION_500_510 0x04
|
||||
#define MASTERKEY_REVISION_600_610 0x05
|
||||
#define MASTERKEY_REVISION_620_CURRENT 0x06
|
||||
#define MASTERKEY_REVISION_620 0x06
|
||||
#define MASTERKEY_REVISION_700_CURRENT 0x07
|
||||
|
||||
#define MASTERKEY_NUM_NEW_DEVICE_KEYS (MASTERKEY_REVISION_MAX - MASTERKEY_REVISION_400_410)
|
||||
|
||||
|
||||
@@ -52,6 +52,29 @@
|
||||
#define _MMAPDEV19 ( 0x00000000ull, 0x1000ull, true ) /* AMS userpage, NOT mapped at startup */
|
||||
#define _MMAPDEV20 ( 0x40038000ull, 0x5000ull, true ) /* DEBUG: IRAM */
|
||||
|
||||
/* MMIO 7.0.0+. (addr). */
|
||||
#define _MMAPDEV7X0 ( 0x50041000ull ) /* ARM Interrupt Distributor */
|
||||
#define _MMAPDEV7X1 ( 0x50042000ull ) /* Interrupt Controller Physical CPU interface */
|
||||
#define _MMAPDEV7X2 ( 0x70006000ull ) /* UART */
|
||||
#define _MMAPDEV7X3 ( 0x60006000ull ) /* Clock and Reset */
|
||||
#define _MMAPDEV7X4 ( 0x7000E000ull ) /* RTC, PMC */
|
||||
#define _MMAPDEV7X5 ( 0x60005000ull ) /* TMRs, WDTs */
|
||||
#define _MMAPDEV7X6 ( 0x6000C000ull ) /* System Registers */
|
||||
#define _MMAPDEV7X7 ( 0x70012000ull ) /* SE */
|
||||
#define _MMAPDEV7X8 ( 0x700F0000ull ) /* SYSCTR0 */
|
||||
#define _MMAPDEV7X9 ( 0x70019000ull ) /* MC */
|
||||
#define _MMAPDEV7X10 ( 0x7000F000ull ) /* FUSE (0x7000F800) */
|
||||
#define _MMAPDEV7X11 ( 0x70000000ull ) /* MISC */
|
||||
#define _MMAPDEV7X12 ( 0x60007000ull ) /* Flow Controller */
|
||||
#define _MMAPDEV7X13 ( 0x40000000ull ) /* NX bootloader mailbox page */
|
||||
#define _MMAPDEV7X14 ( 0x7000D000ull ) /* I2C-5,6 - SPI 2B-1 to 4 */
|
||||
#define _MMAPDEV7X15 ( 0x6000D000ull ) /* GPIO-1 - GPIO-8 */
|
||||
#define _MMAPDEV7X16 ( 0x7000C000ull ) /* I2C-I2C4 */
|
||||
#define _MMAPDEV7X17 ( 0x6000F000ull ) /* Exception vectors */
|
||||
#define _MMAPDEV7X18 ( 0x00000000ull ) /* AMS irampage, NOT mapped at startup */
|
||||
#define _MMAPDEV7X19 ( 0x00000000ull ) /* AMS userpage, NOT mapped at startup */
|
||||
#define _MMAPDEV7X20 ( 0x40038000ull ) /* DEBUG: IRAM */
|
||||
|
||||
/* LP0 entry ram segments (addr, size, additional attributes) */
|
||||
#define _MMAPLP0ES0 ( 0x40020000ull, 0x10000ull, MMU_PTE_BLOCK_NS | ATTRIB_MEMTYPE_DEVICE ) /* Encrypted TZRAM */
|
||||
#define _MMAPLP0ES1 ( 0x40003000ull, 0x01000ull, MMU_PTE_BLOCK_NS | ATTRIB_MEMTYPE_DEVICE ) /* LP0 entry code */
|
||||
@@ -140,6 +163,7 @@
|
||||
#define IDENTITY_IS_MAPPING_BLOCK_RANGE(mapping_id) (TUPLE_ELEM_3(CAT(_MMAPID, EVAL(mapping_id))))
|
||||
|
||||
#define MMIO_GET_DEVICE_PA(device_id) (TUPLE_ELEM_0(CAT(_MMAPDEV, EVAL(device_id))))
|
||||
#define MMIO_GET_DEVICE_7X_PA(device_id) (TUPLE_ELEM_0(CAT(_MMAPDEV, EVAL(device_id))))
|
||||
#define MMIO_GET_DEVICE_ADDRESS(device_id)\
|
||||
(\
|
||||
(TUPLE_FOLD_LEFT_1(EVAL(device_id), _MMAPDEV, PLUS) EVAL(MMIO_BASE)) +\
|
||||
|
||||
@@ -41,25 +41,29 @@ static const uint8_t new_device_key_sources[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10]
|
||||
{0x8B, 0x4E, 0x1C, 0x22, 0x42, 0x07, 0xC8, 0x73, 0x56, 0x94, 0x08, 0x8B, 0xCC, 0x47, 0x0F, 0x5D}, /* 4.x New Device Key Source. */
|
||||
{0x6C, 0xEF, 0xC6, 0x27, 0x8B, 0xEC, 0x8A, 0x91, 0x99, 0xAB, 0x24, 0xAC, 0x4F, 0x1C, 0x8F, 0x1C}, /* 5.x New Device Key Source. */
|
||||
{0x70, 0x08, 0x1B, 0x97, 0x44, 0x64, 0xF8, 0x91, 0x54, 0x9D, 0xC6, 0x84, 0x8F, 0x1A, 0xB2, 0xE4}, /* 6.x New Device Key Source. */
|
||||
{0x8E, 0x09, 0x1F, 0x7A, 0xBB, 0xCA, 0x6A, 0xFB, 0xB8, 0x9B, 0xD5, 0xC1, 0x25, 0x9C, 0xA9, 0x17} /* 6.2.0 New Device Key Source. */
|
||||
{0x8E, 0x09, 0x1F, 0x7A, 0xBB, 0xCA, 0x6A, 0xFB, 0xB8, 0x9B, 0xD5, 0xC1, 0x25, 0x9C, 0xA9, 0x17}, /* 6.2.0 New Device Key Source. */
|
||||
{0x8F, 0x77, 0x5A, 0x96, 0xB0, 0x94, 0xFD, 0x8D, 0x28, 0xE4, 0x19, 0xC8, 0x16, 0x1C, 0xDB, 0x3D}, /* 7.0.0 New Device Key Source. */
|
||||
};
|
||||
|
||||
static const uint8_t new_device_keygen_sources[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = {
|
||||
{0x88, 0x62, 0x34, 0x6E, 0xFA, 0xF7, 0xD8, 0x3F, 0xE1, 0x30, 0x39, 0x50, 0xF0, 0xB7, 0x5D, 0x5D}, /* 4.x New Device Keygen Source. */
|
||||
{0x06, 0x1E, 0x7B, 0xE9, 0x6D, 0x47, 0x8C, 0x77, 0xC5, 0xC8, 0xE7, 0x94, 0x9A, 0xA8, 0x5F, 0x2E}, /* 5.x New Device Keygen Source. */
|
||||
{0x99, 0xFA, 0x98, 0xBD, 0x15, 0x1C, 0x72, 0xFD, 0x7D, 0x9A, 0xD5, 0x41, 0x00, 0xFD, 0xB2, 0xEF}, /* 6.x New Device Keygen Source. */
|
||||
{0x81, 0x3C, 0x6C, 0xBF, 0x5D, 0x21, 0xDE, 0x77, 0x20, 0xD9, 0x6C, 0xE3, 0x22, 0x06, 0xAE, 0xBB} /* 6.2.0 New Device Keygen Source. */
|
||||
{0x81, 0x3C, 0x6C, 0xBF, 0x5D, 0x21, 0xDE, 0x77, 0x20, 0xD9, 0x6C, 0xE3, 0x22, 0x06, 0xAE, 0xBB}, /* 6.2.0 New Device Keygen Source. */
|
||||
{0x86, 0x61, 0xB0, 0x16, 0xFA, 0x7A, 0x9A, 0xEA, 0xF6, 0xF5, 0xBE, 0x1A, 0x13, 0x5B, 0x6D, 0x9E}, /* 7.0.0 New Device Keygen Source. */
|
||||
};
|
||||
|
||||
static const uint8_t new_device_keygen_sources_dev[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = {
|
||||
{0xD6, 0xBD, 0x9F, 0xC6, 0x18, 0x09, 0xE1, 0x96, 0x20, 0x39, 0x60, 0xD2, 0x89, 0x83, 0x31, 0x34}, /* 4.x New Device Keygen Source. */
|
||||
{0x59, 0x2D, 0x20, 0x69, 0x33, 0xB5, 0x17, 0xBA, 0xCF, 0xB1, 0x4E, 0xFD, 0xE4, 0xC2, 0x7B, 0xA8}, /* 5.x New Device Keygen Source. */
|
||||
{0xF6, 0xD8, 0x59, 0x63, 0x8F, 0x47, 0xCB, 0x4A, 0xD8, 0x74, 0x05, 0x7F, 0x88, 0x92, 0x33, 0xA5}, /* 6.x New Device Keygen Source. */
|
||||
{0x20, 0xAB, 0xF2, 0x0F, 0x05, 0xE3, 0xDE, 0x2E, 0xA1, 0xFB, 0x37, 0x5E, 0x8B, 0x22, 0x1A, 0x38} /* 6.2.0 New Device Keygen Source. */
|
||||
{0x20, 0xAB, 0xF2, 0x0F, 0x05, 0xE3, 0xDE, 0x2E, 0xA1, 0xFB, 0x37, 0x5E, 0x8B, 0x22, 0x1A, 0x38}, /* 6.2.0 New Device Keygen Source. */
|
||||
{0x60, 0xAE, 0x56, 0x68, 0x11, 0xE2, 0x0C, 0x99, 0xDE, 0x05, 0xAE, 0x68, 0x78, 0x85, 0x04, 0xAE}, /* 6.2.0 New Device Keygen Source. */
|
||||
};
|
||||
|
||||
static const uint8_t new_master_kek_sources[1][0x10] = {
|
||||
static const uint8_t new_master_kek_sources[MASTERKEY_REVISION_700_CURRENT - MASTERKEY_REVISION_600_610][0x10] = {
|
||||
{0x37, 0x4B, 0x77, 0x29, 0x59, 0xB4, 0x04, 0x30, 0x81, 0xF6, 0xE5, 0x8C, 0x6D, 0x36, 0x17, 0x9A}, /* 6.2.0 Master Kek Source. */
|
||||
{0x9A, 0x3E, 0xA9, 0xAB, 0xFD, 0x56, 0x46, 0x1C, 0x9B, 0xF6, 0x48, 0x7F, 0x5C, 0xFA, 0x09, 0x5C}, /* 7.0.0 Master Kek Source. */
|
||||
};
|
||||
|
||||
static const uint8_t keyblob_key_seed_00[0x10] = {
|
||||
@@ -134,6 +138,18 @@ static void setup_se(void) {
|
||||
}
|
||||
|
||||
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_620 && exosphere_should_perform_620_keygen()) {
|
||||
unsigned int master_kek_source_ind;
|
||||
switch (exosphere_get_target_firmware()) {
|
||||
case ATMOSPHERE_TARGET_FIRMWARE_620:
|
||||
master_kek_source_ind = MASTERKEY_REVISION_620 - MASTERKEY_REVISION_620;
|
||||
break;
|
||||
case ATMOSPHERE_TARGET_FIRMWARE_700:
|
||||
master_kek_source_ind = MASTERKEY_REVISION_700_CURRENT - MASTERKEY_REVISION_620;
|
||||
break;
|
||||
default:
|
||||
generic_panic();
|
||||
break;
|
||||
}
|
||||
/* Start by generating device keys. */
|
||||
se_aes_ecb_decrypt_block(KEYSLOT_SWITCH_6XTSECKEY, work_buffer, 0x10, keyblob_key_seed_00, 0x10);
|
||||
decrypt_data_into_keyslot(KEYSLOT_SWITCH_4XOLDDEVICEKEY, KEYSLOT_SWITCH_6XSBK, work_buffer, 0x10);
|
||||
@@ -141,7 +157,7 @@ static void setup_se(void) {
|
||||
decrypt_data_into_keyslot(KEYSLOT_SWITCH_4XOLDDEVICEKEY, KEYSLOT_SWITCH_4XOLDDEVICEKEY, devicekey_seed, 0x10);
|
||||
|
||||
/* Next, generate the master kek, and from there master key/device kek. We use different keyslots than Nintendo, here. */
|
||||
decrypt_data_into_keyslot(KEYSLOT_SWITCH_6XTSECROOTKEY, KEYSLOT_SWITCH_6XTSECROOTKEY, new_master_kek_sources[0], 0x10);
|
||||
decrypt_data_into_keyslot(KEYSLOT_SWITCH_6XTSECROOTKEY, KEYSLOT_SWITCH_6XTSECROOTKEY, new_master_kek_sources[master_kek_source_ind], 0x10);
|
||||
decrypt_data_into_keyslot(KEYSLOT_SWITCH_MASTERKEY, KEYSLOT_SWITCH_6XTSECROOTKEY, masterkey_seed, 0x10);
|
||||
decrypt_data_into_keyslot(KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY, KEYSLOT_SWITCH_6XTSECROOTKEY, devicekek_4x_seed, 0x10);
|
||||
clear_aes_keyslot(KEYSLOT_SWITCH_6XTSECROOTKEY);
|
||||
@@ -162,6 +178,7 @@ static void setup_se(void) {
|
||||
case ATMOSPHERE_TARGET_FIRMWARE_500:
|
||||
case ATMOSPHERE_TARGET_FIRMWARE_600:
|
||||
case ATMOSPHERE_TARGET_FIRMWARE_620:
|
||||
case ATMOSPHERE_TARGET_FIRMWARE_700:
|
||||
derive_new_device_keys(KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY);
|
||||
break;
|
||||
}
|
||||
@@ -346,7 +363,7 @@ static bool validate_package2_metadata(package2_meta_t *metadata) {
|
||||
|
||||
/* Perform version checks. */
|
||||
/* We will be compatible with all package2s released before current, but not newer ones. */
|
||||
if (metadata->version_max >= PACKAGE2_MINVER_THEORETICAL && metadata->version_min < PACKAGE2_MAXVER_620_CURRENT) {
|
||||
if (metadata->version_max >= PACKAGE2_MINVER_THEORETICAL && metadata->version_min < PACKAGE2_MAXVER_700_CURRENT) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -469,6 +486,9 @@ static void copy_warmboot_bin_to_dram() {
|
||||
case ATMOSPHERE_TARGET_FIRMWARE_620:
|
||||
warmboot_src = (uint8_t *)0x4003D800;
|
||||
break;
|
||||
case ATMOSPHERE_TARGET_FIRMWARE_700:
|
||||
warmboot_src = (uint8_t *)0x4003E000;
|
||||
break;
|
||||
}
|
||||
uint8_t *warmboot_dst = (uint8_t *)0x8000D000;
|
||||
const size_t warmboot_size = 0x2000;
|
||||
@@ -488,7 +508,7 @@ static void copy_warmboot_bin_to_dram() {
|
||||
}
|
||||
|
||||
static void sync_with_nx_bootloader(int state) {
|
||||
while (MAILBOX_NX_BOOTLOADER_SETUP_STATE < state) {
|
||||
while (MAILBOX_NX_BOOTLOADER_SETUP_STATE(exosphere_get_target_firmware()) < state) {
|
||||
wait(100);
|
||||
}
|
||||
}
|
||||
@@ -533,6 +553,9 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) {
|
||||
case ATMOSPHERE_TARGET_FIRMWARE_620:
|
||||
MAKE_REG32(PMC_BASE + 0x360) = 0xA8;
|
||||
break;
|
||||
case ATMOSPHERE_TARGET_FIRMWARE_700:
|
||||
MAKE_REG32(PMC_BASE + 0x360) = 0x129;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -543,7 +566,7 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) {
|
||||
setup_current_core_state();
|
||||
|
||||
/* Save boot reason to global. */
|
||||
bootconfig_load_boot_reason((volatile boot_reason_t *)(MAILBOX_NX_BOOTLOADER_BOOT_REASON));
|
||||
bootconfig_load_boot_reason((volatile boot_reason_t *)(MAILBOX_NX_BOOTLOADER_BOOT_REASON(exosphere_get_target_firmware())));
|
||||
|
||||
/* Initialize cache'd random bytes for kernel. */
|
||||
randomcache_init();
|
||||
@@ -552,7 +575,7 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) {
|
||||
/* memset((void *)reloc_list->reloc_base, 0, reloc_list->loaded_bin_size); */
|
||||
|
||||
/* Let NX Bootloader know that we're running. */
|
||||
MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE = 1;
|
||||
MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE(exosphere_get_target_firmware()) = 1;
|
||||
|
||||
/* Wait for 1 second, to allow time for NX_BOOTLOADER to draw to the screen. This is useful for debugging. */
|
||||
/* wait(1000000); */
|
||||
|
||||
@@ -21,18 +21,19 @@
|
||||
|
||||
#include "utils.h"
|
||||
#include "bootconfig.h"
|
||||
#include "exocfg.h"
|
||||
#include "memory_map.h"
|
||||
|
||||
/* Physaddr 0x40002EF8 */
|
||||
static inline uintptr_t get_nx_bootloader_mailbox_base(void) {
|
||||
return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_NXBOOTLOADER_MAILBOX);
|
||||
static inline uintptr_t get_nx_bootloader_mailbox_base(unsigned int targetfw) {
|
||||
return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_NXBOOTLOADER_MAILBOX) + ((targetfw >= ATMOSPHERE_TARGET_FIRMWARE_700) ? (0x000ull) : (0xE00ull));
|
||||
}
|
||||
|
||||
#define MAILBOX_NX_BOOTLOADER_BASE (get_nx_bootloader_mailbox_base())
|
||||
#define MAILBOX_NX_BOOTLOADER_BASE(targetfw) (get_nx_bootloader_mailbox_base(targetfw))
|
||||
|
||||
#define MAILBOX_NX_SECMON_BOOT_TIME MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE + 0xE08ull)
|
||||
#define MAILBOX_NX_SECMON_BOOT_TIME(targetfw) MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE(targetfw) + 0x08ull)
|
||||
|
||||
#define MAILBOX_NX_BOOTLOADER_SETUP_STATE MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE + 0xEF8ull)
|
||||
#define MAILBOX_NX_BOOTLOADER_SETUP_STATE(targetfw) MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE(targetfw) + 0xF8ull)
|
||||
|
||||
#define NX_BOOTLOADER_STATE_INIT 0
|
||||
#define NX_BOOTLOADER_STATE_MOVED_BOOTCONFIG 1
|
||||
@@ -45,9 +46,9 @@ static inline uintptr_t get_nx_bootloader_mailbox_base(void) {
|
||||
#define NX_BOOTLOADER_STATE_FINISHED_4X 4
|
||||
|
||||
/* Physaddr 0x40002EFC */
|
||||
#define MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE + 0xEFCULL)
|
||||
#define MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE(targetfw) MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE(targetfw) + 0xFCULL)
|
||||
|
||||
#define MAILBOX_NX_BOOTLOADER_BOOT_REASON (MAILBOX_NX_BOOTLOADER_BASE + 0xE10ULL)
|
||||
#define MAILBOX_NX_BOOTLOADER_BOOT_REASON(targetfw) (MAILBOX_NX_BOOTLOADER_BASE(targetfw) + 0x10ULL)
|
||||
|
||||
#define NX_BOOTLOADER_BOOTCONFIG_POINTER ((void *)(0x4003D000ull))
|
||||
#define NX_BOOTLOADER_BOOTCONFIG_POINTER_6X ((void *)(0x4003F800ull))
|
||||
@@ -68,7 +69,8 @@ static inline uintptr_t get_nx_bootloader_mailbox_base(void) {
|
||||
#define PACKAGE2_MAXVER_400_410 0x6
|
||||
#define PACKAGE2_MAXVER_500_510 0x7
|
||||
#define PACKAGE2_MAXVER_600_610 0x8
|
||||
#define PACKAGE2_MAXVER_620_CURRENT 0x9
|
||||
#define PACKAGE2_MAXVER_620 0x9
|
||||
#define PACKAGE2_MAXVER_700_CURRENT 0xA
|
||||
|
||||
#define PACKAGE2_MINVER_100 0x3
|
||||
#define PACKAGE2_MINVER_200 0x4
|
||||
@@ -77,7 +79,8 @@ static inline uintptr_t get_nx_bootloader_mailbox_base(void) {
|
||||
#define PACKAGE2_MINVER_400_410 0x7
|
||||
#define PACKAGE2_MINVER_500_510 0x8
|
||||
#define PACKAGE2_MINVER_600_610 0x9
|
||||
#define PACKAGE2_MINVER_620_CURRENT 0xA
|
||||
#define PACKAGE2_MINVER_620 0xA
|
||||
#define PACKAGE2_MINVER_700_CURRENT 0xB
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
|
||||
@@ -176,6 +176,7 @@ void set_version_specific_smcs(void) {
|
||||
case ATMOSPHERE_TARGET_FIRMWARE_500:
|
||||
case ATMOSPHERE_TARGET_FIRMWARE_600:
|
||||
case ATMOSPHERE_TARGET_FIRMWARE_620:
|
||||
case ATMOSPHERE_TARGET_FIRMWARE_700:
|
||||
/* No more LoadSecureExpModKey. */
|
||||
g_smc_user_table[0xE].handler = NULL;
|
||||
g_smc_user_table[0xC].id = 0xC300D60C;
|
||||
|
||||
@@ -50,6 +50,7 @@ static bool is_user_keyslot_valid(unsigned int keyslot) {
|
||||
return keyslot <= 3;
|
||||
case ATMOSPHERE_TARGET_FIRMWARE_600:
|
||||
case ATMOSPHERE_TARGET_FIRMWARE_620:
|
||||
case ATMOSPHERE_TARGET_FIRMWARE_700:
|
||||
default:
|
||||
return keyslot <= 5;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ $(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>dev
|
||||
endif
|
||||
|
||||
TOPDIR ?= $(CURDIR)
|
||||
|
||||
AMS := $(TOPDIR)/../../
|
||||
include $(DEVKITARM)/base_rules
|
||||
|
||||
AMSBRANCH := $(shell git symbolic-ref --short HEAD)
|
||||
@@ -74,14 +76,15 @@ export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
export TOPDIR := $(CURDIR)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
|
||||
$(AMS)/exosphere/rebootstub
|
||||
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) rebootstub.bin
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
@@ -108,10 +111,13 @@ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
|
||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
|
||||
.PHONY: $(BUILD) clean all
|
||||
.PHONY: $(BUILD) clean all check_rebootstub
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
all: $(BUILD)
|
||||
all: check_rebootstub $(BUILD)
|
||||
|
||||
check_rebootstub:
|
||||
@$(MAKE) -C $(AMS)/exosphere/rebootstub all
|
||||
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@@ -120,6 +126,7 @@ $(BUILD):
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@$(MAKE) -C $(AMS)/exosphere/rebootstub clean
|
||||
@rm -fr $(BUILD) $(TARGET).bin $(TARGET).elf
|
||||
|
||||
|
||||
@@ -150,7 +157,7 @@ $(OFILES_SRC) : $(HFILES_BIN)
|
||||
#---------------------------------------------------------------------------------
|
||||
# you need a rule like this for each extension you use as binary data
|
||||
#---------------------------------------------------------------------------------
|
||||
%.bin.o : %.bin
|
||||
%.bin.o %_bin.h: %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
@@ -249,7 +249,7 @@ void nx_hwinit()
|
||||
/* Configure the PMIC. */
|
||||
uint8_t val = 0x40;
|
||||
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_CNFGBBC, &val, 1);
|
||||
val = 0x78;
|
||||
val = 0x60;
|
||||
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, &val, 1);
|
||||
val = 0x38;
|
||||
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_CFG0, &val, 1);
|
||||
|
||||
@@ -149,7 +149,7 @@ int main(void) {
|
||||
|
||||
/* Say hello. */
|
||||
print(SCREEN_LOG_LEVEL_MANDATORY, "Welcome to Atmosph\xe8re Fus\xe9" "e!\n");
|
||||
print(SCREEN_LOG_LEVEL_DEBUG, "Using color linear framebuffer at 0x%p!\n", g_framebuffer);
|
||||
print(SCREEN_LOG_LEVEL_DEBUG, "Using color linear framebuffer at 0x%p!\n", g_framebuffer);
|
||||
|
||||
/* Load the loader payload into DRAM. */
|
||||
load_stage2(bct0);
|
||||
@@ -163,7 +163,7 @@ int main(void) {
|
||||
stage2_args->display_initialized = false;
|
||||
strcpy(stage2_args->bct0, bct0);
|
||||
g_chainloader_argc = 2;
|
||||
|
||||
|
||||
/* Wait a while. */
|
||||
mdelay(1000);
|
||||
|
||||
|
||||
@@ -61,6 +61,11 @@
|
||||
#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;
|
||||
|
||||
@@ -29,6 +29,12 @@
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#define u8 uint8_t
|
||||
#define u32 uint32_t
|
||||
#include "rebootstub_bin.h"
|
||||
#undef u8
|
||||
#undef u32
|
||||
|
||||
void wait(uint32_t microseconds) {
|
||||
uint32_t old_time = TIMERUS_CNTR_1US_0;
|
||||
while (TIMERUS_CNTR_1US_0 - old_time <= microseconds) {
|
||||
@@ -59,12 +65,29 @@ __attribute__((noreturn)) void pmc_reboot(uint32_t scratch0) {
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) void reboot_to_self(void) {
|
||||
/* Patch SDRAM init to perform an SVC immediately after second write */
|
||||
APBDEV_PMC_SCRATCH45_0 = 0x2E38DFFF;
|
||||
APBDEV_PMC_SCRATCH46_0 = 0x6001DC28;
|
||||
/* Set SVC handler to jump to reboot stub in IRAM. */
|
||||
APBDEV_PMC_SCRATCH33_0 = 0x4003F000;
|
||||
APBDEV_PMC_SCRATCH40_0 = 0x6000F208;
|
||||
|
||||
/* Copy reboot stub into IRAM high. */
|
||||
for (size_t i = 0; i < rebootstub_bin_size; i += sizeof(uint32_t)) {
|
||||
write32le((void *)0x4003F000, i, read32le(rebootstub_bin, i));
|
||||
}
|
||||
|
||||
/* Trigger warm reboot. */
|
||||
pmc_reboot(1 << 0);
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) void wait_for_button_and_reboot(void) {
|
||||
uint32_t button;
|
||||
while (true) {
|
||||
button = btn_read();
|
||||
if (button & BTN_POWER) {
|
||||
pmc_reboot(1 << 1);
|
||||
reboot_to_self();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,6 +121,7 @@ void hexdump(const void* data, size_t size, uintptr_t addrbase);
|
||||
|
||||
__attribute__((noreturn)) void watchdog_reboot(void);
|
||||
__attribute__((noreturn)) void pmc_reboot(uint32_t scratch0);
|
||||
__attribute__((noreturn)) void reboot_to_self(void);
|
||||
__attribute__((noreturn)) void wait_for_button_and_reboot(void);
|
||||
|
||||
__attribute__((noreturn)) void generic_panic(void);
|
||||
|
||||
@@ -19,6 +19,13 @@ ifneq (, $(strip $(shell git status --porcelain 2>/dev/null)))
|
||||
AMSREV := $(AMSREV)-dirty
|
||||
endif
|
||||
|
||||
define _bin2o
|
||||
bin2s $< | $(AS) -o $(@)
|
||||
echo "extern const u8" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _ | tr - _)`"_end[];" > `(echo $(<F) | tr . _ | tr - _)`.h
|
||||
echo "extern const u8" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _ | tr - _)`"[];" >> `(echo $(<F) | tr . _ | tr - _)`.h
|
||||
echo "extern const u32" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _ | tr - _)`_size";" >> `(echo $(<F) | tr . _ | tr - _)`.h
|
||||
endef
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
@@ -76,18 +83,23 @@ ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
export TOPDIR := $(CURDIR)
|
||||
|
||||
export KIPDIRS := $(AMS)/stratosphere/loader $(AMS)/stratosphere/pm $(AMS)/stratosphere/sm $(AMS)/stratosphere/boot $(AMS)/stratosphere/fs_mitm
|
||||
export KIPDIRS := $(AMS)/stratosphere/loader $(AMS)/stratosphere/pm $(AMS)/stratosphere/sm $(AMS)/stratosphere/boot $(AMS)/stratosphere/ams_mitm
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
|
||||
$(AMS)/exosphere $(AMS)/exosphere/lp0fw $(AMS)/thermosphere $(KIPDIRS)
|
||||
$(AMS)/exosphere $(AMS)/exosphere/lp0fw $(AMS)/exosphere/rebootstub \
|
||||
$(AMS)/thermosphere $(AMS)/fusee/fusee-primary $(AMS)/sept/sept-primary \
|
||||
$(AMS)/sept/sept-secondary $(KIPDIRS)
|
||||
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
KIPFILES := loader.kip pm.kip sm.kip fs_mitm.kip boot_100.kip boot_200.kip
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) exosphere.bin lp0fw.bin thermosphere.bin splash_screen.bmp $(KIPFILES)
|
||||
KIPFILES := loader.kip pm.kip sm.kip ams_mitm.kip boot_100.kip boot_200.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.enc \
|
||||
$(KIPFILES)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
@@ -103,10 +115,10 @@ else
|
||||
endif
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
|
||||
export OFILES_BIN := $(addsuffix .o,$(subst -,_,$(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 HFILES_BIN := $(addsuffix .h,$(subst .,_,$(subst -,_,$(BINFILES))))
|
||||
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
@@ -115,14 +127,20 @@ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
|
||||
.PHONY: $(BUILD) clean all
|
||||
.PHONY: check_exosphere check_thermosphere check_stratosphere
|
||||
.PHONY: check_fusee_primary check_exosphere check_sept check_thermosphere check_stratosphere
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
all: $(BUILD)
|
||||
|
||||
check_fusee_primary:
|
||||
@$(MAKE) -C $(AMS)/fusee/fusee-primary all
|
||||
|
||||
check_exosphere:
|
||||
@$(MAKE) -C $(AMS)/exosphere all
|
||||
|
||||
check_sept:
|
||||
@$(MAKE) -C $(AMS)/sept all
|
||||
|
||||
check_thermosphere:
|
||||
@$(MAKE) -C $(AMS)/thermosphere all
|
||||
|
||||
@@ -130,13 +148,14 @@ check_stratosphere:
|
||||
@$(MAKE) -C $(AMS)/stratosphere all
|
||||
|
||||
|
||||
$(BUILD): check_exosphere check_thermosphere check_stratosphere
|
||||
$(BUILD): check_fusee_primary check_exosphere check_sept check_thermosphere check_stratosphere
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@$(MAKE) -C $(AMS)/fusee/fusee-primary clean
|
||||
@$(MAKE) -C $(AMS)/exosphere clean
|
||||
@$(MAKE) -C $(AMS)/thermosphere clean
|
||||
@$(MAKE) -C $(AMS)/stratosphere clean
|
||||
@@ -169,6 +188,21 @@ $(OFILES_SRC) : $(HFILES_BIN)
|
||||
#---------------------------------------------------------------------------------
|
||||
# you need a rule like this for each extension you use as binary data
|
||||
#---------------------------------------------------------------------------------
|
||||
fusee_primary.bin.o fusee_primary_bin.h: fusee-primary.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(_bin2o)
|
||||
|
||||
sept_primary.bin.o sept_primary_bin.h: sept-primary.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(_bin2o)
|
||||
|
||||
sept_secondary.enc.o sept_secondary_enc.h: sept-secondary.enc
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(_bin2o)
|
||||
|
||||
%.bin.o %_bin.h: %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
|
||||
@@ -21,11 +21,8 @@
|
||||
|
||||
/* This serves to set configuration for *exosphere itself*, separate from the SecMon Exosphere mimics. */
|
||||
|
||||
/* "XBC0" */
|
||||
#define MAGIC_EXOSPHERE_BOOTCONFIG_0 (0x30434258)
|
||||
/* "XBC1" */
|
||||
#define MAGIC_EXOSPHERE_BOOTCONFIG (0x31434258)
|
||||
|
||||
/* "EXO0" */
|
||||
#define MAGIC_EXOSPHERE_CONFIG (0x304F5845)
|
||||
|
||||
#define EXOSPHERE_FLAGS_DEFAULT 0x00000000
|
||||
#define EXOSPHERE_FLAG_PERFORM_620_KEYGEN (1 << 0u)
|
||||
@@ -36,9 +33,10 @@ typedef struct {
|
||||
unsigned int magic;
|
||||
unsigned int target_firmware;
|
||||
unsigned int flags;
|
||||
unsigned int reserved;
|
||||
} exosphere_config_t;
|
||||
|
||||
#define MAILBOX_EXOSPHERE_CONFIGURATION ((volatile exosphere_config_t *)(0x40002E40))
|
||||
#define MAILBOX_EXOSPHERE_CONFIGURATION ((volatile exosphere_config_t *)(0x8000F000ull))
|
||||
|
||||
#define EXOSPHERE_TARGETFW_KEY "target_firmware"
|
||||
#define EXOSPHERE_DEBUGMODE_PRIV_KEY "debugmode"
|
||||
|
||||
@@ -197,18 +197,19 @@ void extkeys_initialize_keyset(fusee_extkeys_t *keyset, FILE *f) {
|
||||
continue;
|
||||
}
|
||||
int matched_key = 0;
|
||||
if (strcmp(key, "tsec_root_key") == 0 || strcmp(key, "tsec_root_key_00") == 0) {
|
||||
parse_hex_key(keyset->tsec_root_key, value, sizeof(keyset->tsec_root_key));
|
||||
matched_key = 1;
|
||||
} else {
|
||||
char test_name[0x100] = {0};
|
||||
for (unsigned int i = 0; i < 0x20 && !matched_key; i++) {
|
||||
snprintf(test_name, sizeof(test_name), "master_kek_%02x", i);
|
||||
if (strcmp(key, test_name) == 0) {
|
||||
parse_hex_key(keyset->master_keks[i], value, sizeof(keyset->master_keks[i]));
|
||||
matched_key = 1;
|
||||
break;
|
||||
}
|
||||
char test_name[0x100] = {0};
|
||||
for (unsigned int i = 0; i < 0x20 && !matched_key; i++) {
|
||||
snprintf(test_name, sizeof(test_name), "tsec_root_key_%02x", i);
|
||||
if (strcmp(key, test_name) == 0) {
|
||||
parse_hex_key(keyset->tsec_root_keys[i], value, sizeof(keyset->tsec_root_keys[i]));
|
||||
matched_key = 1;
|
||||
break;
|
||||
}
|
||||
snprintf(test_name, sizeof(test_name), "master_kek_%02x", i);
|
||||
if (strcmp(key, test_name) == 0) {
|
||||
parse_hex_key(keyset->master_keks[i], value, sizeof(keyset->master_keks[i]));
|
||||
matched_key = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "masterkey.h"
|
||||
|
||||
typedef struct {
|
||||
unsigned char tsec_root_key[0x10];
|
||||
unsigned char tsec_root_keys[0x20][0x10];
|
||||
unsigned char master_keks[0x20][0x10];
|
||||
} fusee_extkeys_t;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Atmosphère-NX
|
||||
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -21,9 +22,10 @@
|
||||
#include "ips.h"
|
||||
|
||||
#define MAKE_BRANCH(a, o) 0x14000000 | ((((o) - (a)) >> 2) & 0x3FFFFFF)
|
||||
#define MAKE_NOP 0xD503201F
|
||||
|
||||
#define MAKE_KERNEL_PATTERN_NAME(vers, name) g_kernel_patch_##vers##_##name
|
||||
#define MAKE_KERNEL_HOOK_NAME(vers, name) g_kernel_hook_##vers##_##name
|
||||
#define MAKE_KERNEL_PATTERN_NAME(vers, name) g_kernel_pattern_##vers##_##name
|
||||
#define MAKE_KERNEL_PATCH_NAME(vers, name) g_kernel_patch_##vers##_##name
|
||||
|
||||
typedef uint32_t instruction_t;
|
||||
|
||||
@@ -33,14 +35,15 @@ typedef struct {
|
||||
size_t pattern_hook_offset;
|
||||
size_t payload_num_instructions;
|
||||
size_t branch_back_offset;
|
||||
size_t patch_offset;
|
||||
const instruction_t *payload;
|
||||
} kernel_hook_t;
|
||||
} kernel_patch_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t hash[0x20]; /* TODO: Come up with a better way to identify kernels, that doesn't rely on hashing them. */
|
||||
size_t free_code_space_offset;
|
||||
unsigned int num_hooks;
|
||||
const kernel_hook_t *hooks;
|
||||
unsigned int num_patches;
|
||||
const kernel_patch_t *patches;
|
||||
} kernel_info_t;
|
||||
|
||||
/* Patch definitions. */
|
||||
@@ -60,7 +63,7 @@ typedef struct {
|
||||
ldp x10, x11, [sp],#0x10
|
||||
*/
|
||||
static const uint8_t MAKE_KERNEL_PATTERN_NAME(100, proc_id_send)[] = {0x48, 0x29, 0x41, 0xF9, 0xC9, 0xF5, 0x7E, 0xD3, 0xCE, 0x09, 0x00, 0x11, 0x48, 0x6A, 0x29, 0xF8};
|
||||
static const instruction_t MAKE_KERNEL_HOOK_NAME(100, proc_id_send)[] = {0xA9BF2FEA, 0x2A0E03EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B, 0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9412948, 0xA8C12FEA};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(100, proc_id_send)[] = {0xA9BF2FEA, 0x2A0E03EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B, 0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9412948, 0xA8C12FEA};
|
||||
/*
|
||||
stp x10, x11, [sp, #-0x10]!
|
||||
mov w10, w28
|
||||
@@ -77,7 +80,7 @@ static const instruction_t MAKE_KERNEL_HOOK_NAME(100, proc_id_send)[] = {0xA9BF2
|
||||
ldp x10, x11, [sp],#0x10
|
||||
*/
|
||||
static const uint8_t MAKE_KERNEL_PATTERN_NAME(100, proc_id_recv)[] = {0x68, 0x29, 0x41, 0xF9, 0x89, 0xF7, 0x7E, 0xD3, 0x9C, 0x0B, 0x00, 0x11, 0x48, 0x69, 0x29, 0xF8};
|
||||
static const instruction_t MAKE_KERNEL_HOOK_NAME(100, proc_id_recv)[] = {0xA9BF2FEA, 0x2A1C03EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9412968, 0xA8C12FEA};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(100, proc_id_recv)[] = {0xA9BF2FEA, 0x2A1C03EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9412968, 0xA8C12FEA};
|
||||
/*
|
||||
stp x10, x11, [sp, #-0x10]!
|
||||
mov w11, w24
|
||||
@@ -94,7 +97,7 @@ static const instruction_t MAKE_KERNEL_HOOK_NAME(100, proc_id_recv)[] = {0xA9BF2
|
||||
ldp x10, x11, [sp],#0x10
|
||||
*/
|
||||
static const uint8_t MAKE_KERNEL_PATTERN_NAME(200, proc_id_send)[] = {0x48, 0x31, 0x41, 0xF9, 0xE9, 0x03, 0x18, 0x2A, 0x29, 0xF5, 0x7E, 0xD3, 0xC8, 0x6A, 0x29, 0xF8};
|
||||
static const instruction_t MAKE_KERNEL_HOOK_NAME(200, proc_id_send)[] = {0xA9BF2FEA, 0x2A1803EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B, 0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9413148, 0xA8C12FEA};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(200, proc_id_send)[] = {0xA9BF2FEA, 0x2A1803EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B, 0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9413148, 0xA8C12FEA};
|
||||
/*
|
||||
stp x10, x11, [sp, #-0x10]!
|
||||
mov w10, w15
|
||||
@@ -113,7 +116,7 @@ static const instruction_t MAKE_KERNEL_HOOK_NAME(200, proc_id_send)[] = {0xA9BF2
|
||||
ldp x10, x11, [sp],#0x10
|
||||
*/
|
||||
static const uint8_t MAKE_KERNEL_PATTERN_NAME(200, proc_id_recv)[] = {0x08, 0x31, 0x41, 0xF9, 0xE9, 0x03, 0x0F, 0x2A, 0x29, 0xF5, 0x7E, 0xD3, 0x48, 0x6B, 0x29, 0xF8};
|
||||
static const instruction_t MAKE_KERNEL_HOOK_NAME(200, proc_id_recv)[] = {0xA9BF2FEA, 0x2A0F03EA, 0xD37EF54A, 0xF9405FEB, 0xF86A696A, 0xF9407BEB, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9413168, 0xA8C12FEA};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(200, proc_id_recv)[] = {0xA9BF2FEA, 0x2A0F03EA, 0xD37EF54A, 0xF9405FEB, 0xF86A696A, 0xF9407BEB, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9413168, 0xA8C12FEA};
|
||||
/*
|
||||
stp x10, x11, [sp, #-0x10]!
|
||||
mov w11, w24
|
||||
@@ -130,7 +133,7 @@ static const instruction_t MAKE_KERNEL_HOOK_NAME(200, proc_id_recv)[] = {0xA9BF2
|
||||
ldp x10, x11, [sp],#0x10
|
||||
*/
|
||||
static const uint8_t MAKE_KERNEL_PATTERN_NAME(300, proc_id_send)[] = {0x48, 0x55, 0x41, 0xF9, 0xE9, 0x03, 0x18, 0x2A, 0x29, 0xF5, 0x7E, 0xD3, 0xC8, 0x6A, 0x29, 0xF8};
|
||||
static const instruction_t MAKE_KERNEL_HOOK_NAME(300, proc_id_send)[] = {0xA9BF2FEA, 0x2A1803EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B, 0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9415548, 0xA8C12FEA};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(300, proc_id_send)[] = {0xA9BF2FEA, 0x2A1803EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B, 0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9415548, 0xA8C12FEA};
|
||||
/*
|
||||
stp x10, x11, [sp, #-0x10]!
|
||||
mov w10, w15
|
||||
@@ -149,7 +152,7 @@ static const instruction_t MAKE_KERNEL_HOOK_NAME(300, proc_id_send)[] = {0xA9BF2
|
||||
ldp x10, x11, [sp],#0x10
|
||||
*/
|
||||
static const uint8_t MAKE_KERNEL_PATTERN_NAME(300, proc_id_recv)[] = {0x08, 0x55, 0x41, 0xF9, 0xE9, 0x03, 0x0F, 0x2A, 0x29, 0xF5, 0x7E, 0xD3, 0x48, 0x6B, 0x29, 0xF8};
|
||||
static const instruction_t MAKE_KERNEL_HOOK_NAME(300, proc_id_recv)[] = {0xA9BF2FEA, 0x2A0F03EA, 0xD37EF54A, 0xF9405FEB, 0xF86A696A, 0xF9407BEB, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415568, 0xA8C12FEA};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(300, proc_id_recv)[] = {0xA9BF2FEA, 0x2A0F03EA, 0xD37EF54A, 0xF9405FEB, 0xF86A696A, 0xF9407BEB, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415568, 0xA8C12FEA};
|
||||
/*
|
||||
stp x10, x11, [sp, #-0x10]!
|
||||
mov w11, w24
|
||||
@@ -166,7 +169,7 @@ static const instruction_t MAKE_KERNEL_HOOK_NAME(300, proc_id_recv)[] = {0xA9BF2
|
||||
ldp x10, x11, [sp],#0x10
|
||||
*/
|
||||
static const uint8_t MAKE_KERNEL_PATTERN_NAME(302, proc_id_send)[] = {0x48, 0x55, 0x41, 0xF9, 0xE9, 0x03, 0x18, 0x2A, 0x29, 0xF5, 0x7E, 0xD3, 0xC8, 0x6A, 0x29, 0xF8};
|
||||
static const instruction_t MAKE_KERNEL_HOOK_NAME(302, proc_id_send)[] = {0xA9BF2FEA, 0x2A1803EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B, 0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9415548, 0xA8C12FEA};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(302, proc_id_send)[] = {0xA9BF2FEA, 0x2A1803EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B, 0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9415548, 0xA8C12FEA};
|
||||
/*
|
||||
stp x10, x11, [sp, #-0x10]!
|
||||
mov w10, w15
|
||||
@@ -185,7 +188,7 @@ static const instruction_t MAKE_KERNEL_HOOK_NAME(302, proc_id_send)[] = {0xA9BF2
|
||||
ldp x10, x11, [sp],#0x10
|
||||
*/
|
||||
static const uint8_t MAKE_KERNEL_PATTERN_NAME(302, proc_id_recv)[] = {0x08, 0x55, 0x41, 0xF9, 0xE9, 0x03, 0x0F, 0x2A, 0x29, 0xF5, 0x7E, 0xD3, 0x48, 0x6B, 0x29, 0xF8};
|
||||
static const instruction_t MAKE_KERNEL_HOOK_NAME(302, proc_id_recv)[] = {0xA9BF2FEA, 0x2A0F03EA, 0xD37EF54A, 0xF9405FEB, 0xF86A696A, 0xF9407BEB, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415568, 0xA8C12FEA};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(302, proc_id_recv)[] = {0xA9BF2FEA, 0x2A0F03EA, 0xD37EF54A, 0xF9405FEB, 0xF86A696A, 0xF9407BEB, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415568, 0xA8C12FEA};
|
||||
/*
|
||||
mov w10, w23
|
||||
lsl x10, x10, #2
|
||||
@@ -202,7 +205,7 @@ static const instruction_t MAKE_KERNEL_HOOK_NAME(302, proc_id_recv)[] = {0xA9BF2
|
||||
ldr x10, [sp,#0xa0]
|
||||
*/
|
||||
static const uint8_t MAKE_KERNEL_PATTERN_NAME(400, proc_id_send)[] = {0xEA, 0x53, 0x40, 0xF9, 0x48, 0x59, 0x41, 0xF9, 0xE9, 0x03, 0x17, 0x2A, 0x29, 0xF5, 0x7E, 0xD3};
|
||||
static const instruction_t MAKE_KERNEL_HOOK_NAME(400, proc_id_send)[] = {0x2A1703EA, 0xD37EF54A, 0xF86A6B8A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000060, 0xF94053EA, 0xF9415948, 0xF94053EA};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(400, proc_id_send)[] = {0x2A1703EA, 0xD37EF54A, 0xF86A6B8A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000060, 0xF94053EA, 0xF9415948, 0xF94053EA};
|
||||
/*
|
||||
ldr x13, [sp,#0x70]
|
||||
mov w10, w14
|
||||
@@ -219,7 +222,7 @@ static const instruction_t MAKE_KERNEL_HOOK_NAME(400, proc_id_send)[] = {0x2A170
|
||||
nop
|
||||
*/
|
||||
static const uint8_t MAKE_KERNEL_PATTERN_NAME(400, proc_id_recv)[] = {0x28, 0x5B, 0x41, 0xF9, 0xE9, 0x03, 0x0E, 0x2A, 0xCE, 0x09, 0x00, 0x11, 0x29, 0xF5, 0x7E, 0xD3};
|
||||
static const instruction_t MAKE_KERNEL_HOOK_NAME(400, proc_id_recv)[] = {0xF9403BED, 0x2A0E03EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415B28, 0xD503201F};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(400, proc_id_recv)[] = {0xF9403BED, 0x2A0E03EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415B28, 0xD503201F};
|
||||
/*
|
||||
mov w10, w23
|
||||
lsl x10, x10, #2
|
||||
@@ -236,7 +239,7 @@ static const instruction_t MAKE_KERNEL_HOOK_NAME(400, proc_id_recv)[] = {0xF9403
|
||||
ldr x10, [sp,#0x80]
|
||||
*/
|
||||
static const uint8_t MAKE_KERNEL_PATTERN_NAME(500, proc_id_send)[] = {0xEA, 0x43, 0x40, 0xF9, 0x48, 0x59, 0x41, 0xF9, 0xE9, 0x03, 0x17, 0x2A, 0x29, 0xF5, 0x7E, 0xD3};
|
||||
static const instruction_t MAKE_KERNEL_HOOK_NAME(500, proc_id_send)[] = {0x2A1703EA, 0xD37EF54A, 0xF86A6B6A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000060, 0xF94043EA, 0xF9415948, 0xF94043EA};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(500, proc_id_send)[] = {0x2A1703EA, 0xD37EF54A, 0xF86A6B6A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000060, 0xF94043EA, 0xF9415948, 0xF94043EA};
|
||||
/*
|
||||
ldr x13, [sp, #0x70]
|
||||
mov w10, w21
|
||||
@@ -253,7 +256,7 @@ static const instruction_t MAKE_KERNEL_HOOK_NAME(500, proc_id_send)[] = {0x2A170
|
||||
ldr x10, [sp,#0xd8]
|
||||
*/
|
||||
static const uint8_t MAKE_KERNEL_PATTERN_NAME(500, proc_id_recv)[] = {0x08, 0x5B, 0x41, 0xF9, 0xEA, 0x6F, 0x40, 0xF9, 0xE9, 0x03, 0x15, 0x2A, 0x29, 0xF5, 0x7E, 0xD3};
|
||||
static const instruction_t MAKE_KERNEL_HOOK_NAME(500, proc_id_recv)[] = {0xF9403BED, 0x2A1503EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415B08, 0xF9406FEA};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(500, proc_id_recv)[] = {0xF9403BED, 0x2A1503EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415B08, 0xF9406FEA};
|
||||
/*
|
||||
stp x10, x11, [sp, #-0x10]!
|
||||
ldr x11, [sp, #0x68]
|
||||
@@ -280,7 +283,7 @@ static const instruction_t MAKE_KERNEL_HOOK_NAME(500, proc_id_recv)[] = {0xF9403
|
||||
mov x0, x8
|
||||
*/
|
||||
static const uint8_t MAKE_KERNEL_PATTERN_NAME(600, proc_id_send)[] = {0x08, 0x03, 0x40, 0xF9, 0x08, 0x1D, 0x40, 0xF9, 0xE0, 0x03, 0x18, 0xAA, 0x00, 0x01, 0x3F, 0xD6, 0xE8, 0x03, 0x15, 0x2A, 0xB5, 0x0A, 0x00, 0x11, 0x08, 0xF5, 0x7E, 0xD3};
|
||||
static const instruction_t MAKE_KERNEL_HOOK_NAME(600, proc_id_send)[] = {0xA9BF2FEA, 0xF94037EB, 0x2A1503EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400308, 0xF9401D08, 0xAA1803E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(600, proc_id_send)[] = {0xA9BF2FEA, 0xF94037EB, 0x2A1503EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400308, 0xF9401D08, 0xAA1803E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0};
|
||||
/*
|
||||
stp x10, x11, [sp, #-0x10]!
|
||||
ldr x11, [sp, #0x80]
|
||||
@@ -307,180 +310,277 @@ static const instruction_t MAKE_KERNEL_HOOK_NAME(600, proc_id_send)[] = {0xA9BF2
|
||||
mov x0, x8
|
||||
*/
|
||||
static const uint8_t MAKE_KERNEL_PATTERN_NAME(600, proc_id_recv)[] = {0x08, 0x03, 0x40, 0xF9, 0x08, 0x1D, 0x40, 0xF9, 0xE0, 0x03, 0x18, 0xAA, 0x00, 0x01, 0x3F, 0xD6, 0xE9, 0x6F, 0x40, 0xF9, 0xE8, 0x03, 0x15, 0x2A, 0xB5, 0x0A, 0x00, 0x11};
|
||||
static const instruction_t MAKE_KERNEL_HOOK_NAME(600, proc_id_recv)[] = {0xA9BF2FEA, 0xF94043EB, 0x2A1503EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400308, 0xF9401D08, 0xAA1803E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(600, proc_id_recv)[] = {0xA9BF2FEA, 0xF94043EB, 0x2A1503EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400308, 0xF9401D08, 0xAA1803E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0};
|
||||
/*
|
||||
stp x10, x11, [sp, #-0x10]!
|
||||
ldr x11, [sp, #0x70]
|
||||
mov w10, w25
|
||||
lsl x10, x10, #2
|
||||
ldr x10, [x11, x10]
|
||||
mov x9, #0x0000ffffffffffff
|
||||
and x8, x10, x9
|
||||
mov x9, #0xffff000000000000
|
||||
and x10, x10, x9
|
||||
mov x9, #0xfffe000000000000
|
||||
cmp x10, x9
|
||||
beq #0x20
|
||||
|
||||
stp x8, x9, [sp, #-0x10]!
|
||||
ldr x8, [x21]
|
||||
ldr x8, [x8, #0x38]
|
||||
mov x0, x21
|
||||
blr x8
|
||||
ldp x8, x9, [sp],#0x10
|
||||
mov x8, x0
|
||||
|
||||
ldp x10, x11, [sp],#0x10
|
||||
mov x0, x8
|
||||
*/
|
||||
static const uint8_t MAKE_KERNEL_PATTERN_NAME(700, proc_id_send)[] = {0xA8, 0x02, 0x40, 0xF9, 0x08, 0x1D, 0x40, 0xF9, 0xE0, 0x03, 0x15, 0xAA, 0x00, 0x01, 0x3F, 0xD6, 0xE8, 0x03, 0x19, 0x2A, 0x39, 0x0B, 0x00, 0x11, 0x08, 0xF5, 0x7E, 0xD3};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(700, proc_id_send)[] = {0xA9BF2FEA, 0xF9403BEB, 0x2A1903EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF94002A8, 0xF9401D08, 0xAA1503E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0};
|
||||
/*
|
||||
stp x10, x11, [sp, #-0x10]!
|
||||
ldr x11, [sp, #0x98]
|
||||
mov w10, w22
|
||||
lsl x10, x10, #2
|
||||
ldr x10, [x11, x10]
|
||||
mov x9, #0x0000ffffffffffff
|
||||
and x8, x10, x9
|
||||
mov x9, #0xffff000000000000
|
||||
and x10, x10, x9
|
||||
mov x9, #0xfffe000000000000
|
||||
cmp x10, x9
|
||||
beq #0x20
|
||||
|
||||
stp x8, x9, [sp, #-0x10]!
|
||||
ldr x8, [x27]
|
||||
ldr x8, [x8, #0x38]
|
||||
mov x0, x27
|
||||
blr x8
|
||||
ldp x8, x9, [sp],#0x10
|
||||
mov x8, x0
|
||||
|
||||
ldp x10, x11, [sp],#0x10
|
||||
mov x0, x8
|
||||
*/
|
||||
static const uint8_t MAKE_KERNEL_PATTERN_NAME(700, proc_id_recv)[] = {0x68, 0x03, 0x40, 0xF9, 0x08, 0x1D, 0x40, 0xF9, 0xE0, 0x03, 0x1B, 0xAA, 0x00, 0x01, 0x3F, 0xD6, 0xA9, 0x83, 0x50, 0xF8, 0xE8, 0x03, 0x16, 0x2A, 0xD6, 0x0A, 0x00, 0x11};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(700, proc_id_recv)[] = {0xA9BF2FEA, 0xF9404FEB, 0x2A1603EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400368, 0xF9401D08, 0xAA1B03E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0};
|
||||
|
||||
/* svcControlCodeMemory Patches */
|
||||
/* b.eq -> nop */
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(500, svc_control_codememory)[] = {MAKE_NOP};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(600, svc_control_codememory)[] = {MAKE_NOP};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(700, svc_control_codememory)[] = {MAKE_NOP};
|
||||
|
||||
/* Hook Definitions. */
|
||||
static const kernel_hook_t g_kernel_hooks_100[] = {
|
||||
static const kernel_patch_t g_kernel_patches_100[] = {
|
||||
{ /* Send Message Process ID Patch. */
|
||||
.pattern_size = 0x10,
|
||||
.pattern = MAKE_KERNEL_PATTERN_NAME(100, proc_id_send),
|
||||
.pattern_hook_offset = 0x0,
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(100, proc_id_send))/sizeof(instruction_t),
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(100, proc_id_send))/sizeof(instruction_t),
|
||||
.branch_back_offset = 0x4,
|
||||
.payload = MAKE_KERNEL_HOOK_NAME(100, proc_id_send)
|
||||
.payload = MAKE_KERNEL_PATCH_NAME(100, proc_id_send)
|
||||
},
|
||||
{ /* Receive Message Process ID Patch. */
|
||||
.pattern_size = 0x10,
|
||||
.pattern = MAKE_KERNEL_PATTERN_NAME(100, proc_id_recv),
|
||||
.pattern_hook_offset = 0x0,
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(100, proc_id_recv))/sizeof(instruction_t),
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(100, proc_id_recv))/sizeof(instruction_t),
|
||||
.branch_back_offset = 0x4,
|
||||
.payload = MAKE_KERNEL_HOOK_NAME(100, proc_id_recv)
|
||||
.payload = MAKE_KERNEL_PATCH_NAME(100, proc_id_recv)
|
||||
}
|
||||
};
|
||||
static const kernel_hook_t g_kernel_hooks_200[] = {
|
||||
static const kernel_patch_t g_kernel_patches_200[] = {
|
||||
{ /* Send Message Process ID Patch. */
|
||||
.pattern_size = 0x10,
|
||||
.pattern = MAKE_KERNEL_PATTERN_NAME(200, proc_id_send),
|
||||
.pattern_hook_offset = 0x0,
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(200, proc_id_send))/sizeof(instruction_t),
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(200, proc_id_send))/sizeof(instruction_t),
|
||||
.branch_back_offset = 0x4,
|
||||
.payload = MAKE_KERNEL_HOOK_NAME(200, proc_id_send)
|
||||
.payload = MAKE_KERNEL_PATCH_NAME(200, proc_id_send)
|
||||
},
|
||||
{ /* Receive Message Process ID Patch. */
|
||||
.pattern_size = 0x10,
|
||||
.pattern = MAKE_KERNEL_PATTERN_NAME(200, proc_id_recv),
|
||||
.pattern_hook_offset = 0x0,
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(200, proc_id_recv))/sizeof(instruction_t),
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(200, proc_id_recv))/sizeof(instruction_t),
|
||||
.branch_back_offset = 0x4,
|
||||
.payload = MAKE_KERNEL_HOOK_NAME(200, proc_id_recv)
|
||||
.payload = MAKE_KERNEL_PATCH_NAME(200, proc_id_recv)
|
||||
}
|
||||
};
|
||||
static const kernel_hook_t g_kernel_hooks_300[] = {
|
||||
static const kernel_patch_t g_kernel_patches_300[] = {
|
||||
{ /* Send Message Process ID Patch. */
|
||||
.pattern_size = 0x10,
|
||||
.pattern = MAKE_KERNEL_PATTERN_NAME(300, proc_id_send),
|
||||
.pattern_hook_offset = 0x0,
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(300, proc_id_send))/sizeof(instruction_t),
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(300, proc_id_send))/sizeof(instruction_t),
|
||||
.branch_back_offset = 0x4,
|
||||
.payload = MAKE_KERNEL_HOOK_NAME(300, proc_id_send)
|
||||
.payload = MAKE_KERNEL_PATCH_NAME(300, proc_id_send)
|
||||
},
|
||||
{ /* Receive Message Process ID Patch. */
|
||||
.pattern_size = 0x10,
|
||||
.pattern = MAKE_KERNEL_PATTERN_NAME(300, proc_id_recv),
|
||||
.pattern_hook_offset = 0x0,
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(300, proc_id_recv))/sizeof(instruction_t),
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(300, proc_id_recv))/sizeof(instruction_t),
|
||||
.branch_back_offset = 0x4,
|
||||
.payload = MAKE_KERNEL_HOOK_NAME(300, proc_id_recv)
|
||||
.payload = MAKE_KERNEL_PATCH_NAME(300, proc_id_recv)
|
||||
}
|
||||
};
|
||||
static const kernel_hook_t g_kernel_hooks_302[] = {
|
||||
static const kernel_patch_t g_kernel_patches_302[] = {
|
||||
{ /* Send Message Process ID Patch. */
|
||||
.pattern_size = 0x10,
|
||||
.pattern = MAKE_KERNEL_PATTERN_NAME(302, proc_id_send),
|
||||
.pattern_hook_offset = 0x0,
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(302, proc_id_send))/sizeof(instruction_t),
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(302, proc_id_send))/sizeof(instruction_t),
|
||||
.branch_back_offset = 0x4,
|
||||
.payload = MAKE_KERNEL_HOOK_NAME(302, proc_id_send)
|
||||
.payload = MAKE_KERNEL_PATCH_NAME(302, proc_id_send)
|
||||
},
|
||||
{ /* Receive Message Process ID Patch. */
|
||||
.pattern_size = 0x10,
|
||||
.pattern = MAKE_KERNEL_PATTERN_NAME(302, proc_id_recv),
|
||||
.pattern_hook_offset = 0x0,
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(302, proc_id_recv))/sizeof(instruction_t),
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(302, proc_id_recv))/sizeof(instruction_t),
|
||||
.branch_back_offset = 0x4,
|
||||
.payload = MAKE_KERNEL_HOOK_NAME(302, proc_id_recv)
|
||||
.payload = MAKE_KERNEL_PATCH_NAME(302, proc_id_recv)
|
||||
}
|
||||
};
|
||||
static const kernel_hook_t g_kernel_hooks_400[] = {
|
||||
static const kernel_patch_t g_kernel_patches_400[] = {
|
||||
{ /* Send Message Process ID Patch. */
|
||||
.pattern_size = 0x10,
|
||||
.pattern = MAKE_KERNEL_PATTERN_NAME(400, proc_id_send),
|
||||
.pattern_hook_offset = 0x0,
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(400, proc_id_send))/sizeof(instruction_t),
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(400, proc_id_send))/sizeof(instruction_t),
|
||||
.branch_back_offset = 0x8,
|
||||
.payload = MAKE_KERNEL_HOOK_NAME(400, proc_id_send)
|
||||
.payload = MAKE_KERNEL_PATCH_NAME(400, proc_id_send)
|
||||
},
|
||||
{ /* Receive Message Process ID Patch. */
|
||||
.pattern_size = 0x10,
|
||||
.pattern = MAKE_KERNEL_PATTERN_NAME(400, proc_id_recv),
|
||||
.pattern_hook_offset = 0x0,
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(400, proc_id_recv))/sizeof(instruction_t),
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(400, proc_id_recv))/sizeof(instruction_t),
|
||||
.branch_back_offset = 0x4,
|
||||
.payload = MAKE_KERNEL_HOOK_NAME(400, proc_id_recv)
|
||||
.payload = MAKE_KERNEL_PATCH_NAME(400, proc_id_recv)
|
||||
}
|
||||
};
|
||||
static const kernel_hook_t g_kernel_hooks_500[] = {
|
||||
static const kernel_patch_t g_kernel_patches_500[] = {
|
||||
{ /* Send Message Process ID Patch. */
|
||||
.pattern_size = 0x10,
|
||||
.pattern = MAKE_KERNEL_PATTERN_NAME(500, proc_id_send),
|
||||
.pattern_hook_offset = 0x0,
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(500, proc_id_send))/sizeof(instruction_t),
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(500, proc_id_send))/sizeof(instruction_t),
|
||||
.branch_back_offset = 0x8,
|
||||
.payload = MAKE_KERNEL_HOOK_NAME(500, proc_id_send)
|
||||
.payload = MAKE_KERNEL_PATCH_NAME(500, proc_id_send)
|
||||
},
|
||||
{ /* Receive Message Process ID Patch. */
|
||||
.pattern_size = 0x10,
|
||||
.pattern = MAKE_KERNEL_PATTERN_NAME(500, proc_id_recv),
|
||||
.pattern_hook_offset = 0x0,
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(500, proc_id_recv))/sizeof(instruction_t),
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(500, proc_id_recv))/sizeof(instruction_t),
|
||||
.branch_back_offset = 0x8,
|
||||
.payload = MAKE_KERNEL_HOOK_NAME(500, proc_id_recv)
|
||||
.payload = MAKE_KERNEL_PATCH_NAME(500, proc_id_recv)
|
||||
},
|
||||
{ /* svcControlCodeMemory Patch. */
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(500, svc_control_codememory))/sizeof(instruction_t),
|
||||
.payload = MAKE_KERNEL_PATCH_NAME(500, svc_control_codememory),
|
||||
.patch_offset = 0x38C2C,
|
||||
}
|
||||
};
|
||||
static const kernel_hook_t g_kernel_hooks_600[] = {
|
||||
static const kernel_patch_t g_kernel_patches_600[] = {
|
||||
{ /* Send Message Process ID Patch. */
|
||||
.pattern_size = 0x1C,
|
||||
.pattern = MAKE_KERNEL_PATTERN_NAME(600, proc_id_send),
|
||||
.pattern_hook_offset = 0x0,
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(600, proc_id_send))/sizeof(instruction_t),
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(600, proc_id_send))/sizeof(instruction_t),
|
||||
.branch_back_offset = 0x10,
|
||||
.payload = MAKE_KERNEL_HOOK_NAME(600, proc_id_send)
|
||||
.payload = MAKE_KERNEL_PATCH_NAME(600, proc_id_send)
|
||||
},
|
||||
{ /* Receive Message Process ID Patch. */
|
||||
.pattern_size = 0x1C,
|
||||
.pattern = MAKE_KERNEL_PATTERN_NAME(600, proc_id_recv),
|
||||
.pattern_hook_offset = 0x0,
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(600, proc_id_recv))/sizeof(instruction_t),
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(600, proc_id_recv))/sizeof(instruction_t),
|
||||
.branch_back_offset = 0x10,
|
||||
.payload = MAKE_KERNEL_HOOK_NAME(600, proc_id_recv)
|
||||
.payload = MAKE_KERNEL_PATCH_NAME(600, proc_id_recv)
|
||||
},
|
||||
{ /* svcControlCodeMemory Patch. */
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(600, svc_control_codememory))/sizeof(instruction_t),
|
||||
.payload = MAKE_KERNEL_PATCH_NAME(600, svc_control_codememory),
|
||||
.patch_offset = 0x3A8CC,
|
||||
}
|
||||
};
|
||||
static const kernel_patch_t g_kernel_patches_700[] = {
|
||||
{ /* Send Message Process ID Patch. */
|
||||
.pattern_size = 0x1C,
|
||||
.pattern = MAKE_KERNEL_PATTERN_NAME(700, proc_id_send),
|
||||
.pattern_hook_offset = 0x0,
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(700, proc_id_send))/sizeof(instruction_t),
|
||||
.branch_back_offset = 0x10,
|
||||
.payload = MAKE_KERNEL_PATCH_NAME(700, proc_id_send)
|
||||
},
|
||||
{ /* Receive Message Process ID Patch. */
|
||||
.pattern_size = 0x1C,
|
||||
.pattern = MAKE_KERNEL_PATTERN_NAME(700, proc_id_recv),
|
||||
.pattern_hook_offset = 0x0,
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(700, proc_id_recv))/sizeof(instruction_t),
|
||||
.branch_back_offset = 0x10,
|
||||
.payload = MAKE_KERNEL_PATCH_NAME(700, proc_id_recv)
|
||||
},
|
||||
{ /* svcControlCodeMemory Patch. */
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(700, svc_control_codememory))/sizeof(instruction_t),
|
||||
.payload = MAKE_KERNEL_PATCH_NAME(700, svc_control_codememory),
|
||||
.patch_offset = 0x3C6E0,
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#define KERNEL_HOOKS(vers) .num_hooks = sizeof(g_kernel_hooks_##vers)/sizeof(kernel_hook_t), .hooks = g_kernel_hooks_##vers,
|
||||
#define KERNEL_PATCHES(vers) .num_patches = sizeof(g_kernel_patches_##vers)/sizeof(kernel_patch_t), .patches = g_kernel_patches_##vers,
|
||||
|
||||
/* Kernel Infos. */
|
||||
static const kernel_info_t g_kernel_infos[] = {
|
||||
{ /* 1.0.0-7. */
|
||||
.hash = {0x64, 0x44, 0x07, 0x2F, 0x56, 0x44, 0x73, 0xDD, 0xD5, 0x46, 0x1B, 0x8C, 0xDC, 0xEF, 0x54, 0x98, 0x16, 0xDA, 0x81, 0xDE, 0x5B, 0x1C, 0x9D, 0xD7, 0x5A, 0x13, 0x91, 0xD9, 0x53, 0xAB, 0x8D, 0x8D},
|
||||
.free_code_space_offset = 0x4797C,
|
||||
KERNEL_HOOKS(100)
|
||||
KERNEL_PATCHES(100)
|
||||
},
|
||||
{ /* 1.0.0. */
|
||||
.hash = {0xB8, 0xC5, 0x0C, 0x68, 0x25, 0xA9, 0xB9, 0x5B, 0xD2, 0x4D, 0x2C, 0x7C, 0x81, 0x7F, 0xE6, 0x96, 0xF2, 0x42, 0x4E, 0x1D, 0x78, 0xDF, 0x3B, 0xCA, 0x3D, 0x6B, 0x68, 0x12, 0xDD, 0xA9, 0xCB, 0x9C},
|
||||
.free_code_space_offset = 0x4797C,
|
||||
KERNEL_HOOKS(100)
|
||||
KERNEL_PATCHES(100)
|
||||
},
|
||||
{ /* 2.0.0. */
|
||||
.hash = {0x64, 0x0B, 0x51, 0xFF, 0x28, 0x01, 0xB8, 0x30, 0xA7, 0xA3, 0x60, 0x47, 0x86, 0x0D, 0x68, 0xAA, 0x9A, 0x92, 0x10, 0x0D, 0xB9, 0xCC, 0xEC, 0x8B, 0x05, 0x80, 0x73, 0xBD, 0x33, 0xB4, 0x2C, 0x6C},
|
||||
.free_code_space_offset = 0x6486C,
|
||||
KERNEL_HOOKS(200)
|
||||
KERNEL_PATCHES(200)
|
||||
},
|
||||
{ /* 3.0.0. */
|
||||
.hash = {0x50, 0x84, 0x23, 0xAC, 0x6F, 0xA1, 0x5D, 0x3B, 0x56, 0xC2, 0xFC, 0x95, 0x22, 0xCC, 0xD5, 0xA8, 0x15, 0xD3, 0xB4, 0x6B, 0xA1, 0x2C, 0xF2, 0x93, 0xD3, 0x02, 0x05, 0xAB, 0x52, 0xEF, 0x73, 0xC5},
|
||||
.free_code_space_offset = 0x494A4,
|
||||
KERNEL_HOOKS(300)
|
||||
KERNEL_PATCHES(300)
|
||||
},
|
||||
{ /* 3.0.2. */
|
||||
.hash = {0x81, 0x9D, 0x08, 0xBE, 0xE4, 0x5E, 0x1F, 0xBB, 0x45, 0x5A, 0x6D, 0x70, 0x4B, 0xB2, 0x17, 0xA6, 0x12, 0x69, 0xF8, 0xB8, 0x75, 0x1C, 0x71, 0x16, 0xF0, 0xE9, 0x79, 0x7F, 0xB0, 0xD1, 0x78, 0xB2},
|
||||
.free_code_space_offset = 0x494BC,
|
||||
KERNEL_HOOKS(302)
|
||||
KERNEL_PATCHES(302)
|
||||
},
|
||||
{ /* 4.0.0. */
|
||||
.hash = {0xE6, 0xC0, 0xB7, 0xE3, 0x2F, 0xF9, 0x44, 0x51, 0xEC, 0xD5, 0x95, 0x79, 0xE3, 0x46, 0xB1, 0xDA, 0x2E, 0xD9, 0x28, 0xC6, 0xF2, 0x31, 0x4F, 0x95, 0xD8, 0xC7, 0xD5, 0xBD, 0x15, 0xD5, 0xE2, 0x5A},
|
||||
.free_code_space_offset = 0x52890,
|
||||
KERNEL_HOOKS(400)
|
||||
KERNEL_PATCHES(400)
|
||||
},
|
||||
{ /* 5.0.0. */
|
||||
.hash = {0xB2, 0x38, 0x61, 0xA8, 0xE1, 0xE2, 0xE4, 0xE4, 0x17, 0x28, 0xED, 0xA9, 0xF6, 0xF6, 0xBD, 0xD2, 0x59, 0xDB, 0x1F, 0xEF, 0x4A, 0x8B, 0x2F, 0x1C, 0x64, 0x46, 0x06, 0x40, 0xF5, 0x05, 0x9C, 0x43},
|
||||
.free_code_space_offset = 0x5C020,
|
||||
KERNEL_HOOKS(500)
|
||||
KERNEL_PATCHES(500)
|
||||
},
|
||||
{ /* 6.0.0. */
|
||||
.hash = {0x85, 0x97, 0x40, 0xF6, 0xC0, 0x3E, 0x3D, 0x44, 0xDE, 0xA4, 0xA0, 0x35, 0xFD, 0x12, 0x9C, 0xD4, 0x4F, 0x9C, 0x36, 0x53, 0x74, 0x54, 0x2C, 0x9C, 0x55, 0x47, 0xC4, 0x25, 0xF1, 0x42, 0xFB, 0x97},
|
||||
.free_code_space_offset = 0x5EE00,
|
||||
KERNEL_HOOKS(600)
|
||||
KERNEL_PATCHES(600)
|
||||
},
|
||||
{ /* 7.0.0. */
|
||||
.hash = {0xA2, 0x5E, 0x47, 0x0C, 0x8E, 0x6D, 0x2F, 0xD7, 0x5D, 0xAD, 0x24, 0xD7, 0xD8, 0x24, 0x34, 0xFB, 0xCD, 0x77, 0xBB, 0xE6, 0x66, 0x03, 0xCB, 0xAF, 0xAB, 0x85, 0x45, 0xA0, 0x91, 0xAF, 0x34, 0x25},
|
||||
.free_code_space_offset = 0x5FEC0,
|
||||
KERNEL_PATCHES(700)
|
||||
}
|
||||
};
|
||||
|
||||
@@ -531,13 +631,21 @@ void package2_patch_kernel(void *_kernel, size_t size, bool is_sd_kernel) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Apply hooks. */
|
||||
/* Apply hooks and patches. */
|
||||
uint8_t *kernel = (uint8_t *)_kernel;
|
||||
size_t free_space_offset = kernel_info->free_code_space_offset;
|
||||
size_t free_space_size = ((free_space_offset + 0xFFFULL) & ~0xFFFULL) - free_space_offset;
|
||||
for (unsigned int i = 0; i < kernel_info->num_hooks; i++) {
|
||||
size_t hook_size = sizeof(instruction_t) * kernel_info->hooks[i].payload_num_instructions;
|
||||
if (kernel_info->hooks[i].branch_back_offset) {
|
||||
for (unsigned int i = 0; i < kernel_info->num_patches; i++) {
|
||||
if (kernel_info->patches[i].patch_offset) {
|
||||
for (unsigned int p = 0; p < kernel_info->patches[i].payload_num_instructions; p++) {
|
||||
*(volatile instruction_t*)(_kernel + kernel_info->patches[i].patch_offset) = kernel_info->patches[i].payload[p];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t hook_size = sizeof(instruction_t) * kernel_info->patches[i].payload_num_instructions;
|
||||
|
||||
if (kernel_info->patches[i].branch_back_offset) {
|
||||
hook_size += sizeof(instruction_t);
|
||||
}
|
||||
if (free_space_size < hook_size) {
|
||||
@@ -545,22 +653,22 @@ void package2_patch_kernel(void *_kernel, size_t size, bool is_sd_kernel) {
|
||||
fatal_error("kernel_patcher: insufficient space to apply patches!\n");
|
||||
}
|
||||
|
||||
uint8_t *pattern_loc = search_pattern(kernel, size, kernel_info->hooks[i].pattern, kernel_info->hooks[i].pattern_size);
|
||||
uint8_t *pattern_loc = search_pattern(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;
|
||||
}
|
||||
/* Patch kernel to branch to our hook at the desired place. */
|
||||
instruction_t *hook_start = (instruction_t *)(pattern_loc + kernel_info->hooks[i].pattern_hook_offset);
|
||||
volatile instruction_t *hook_start = (instruction_t *)(pattern_loc + kernel_info->patches[i].pattern_hook_offset);
|
||||
*hook_start = MAKE_BRANCH((uint32_t)((uintptr_t)hook_start - (uintptr_t)kernel), free_space_offset);
|
||||
|
||||
/* Insert hook into free space. */
|
||||
instruction_t *payload = (instruction_t *)(kernel + free_space_offset);
|
||||
for (unsigned int p = 0; p < kernel_info->hooks[i].payload_num_instructions; p++) {
|
||||
payload[p] = kernel_info->hooks[i].payload[p];
|
||||
volatile instruction_t *payload = (instruction_t *)(kernel + free_space_offset);
|
||||
for (unsigned int p = 0; p < kernel_info->patches[i].payload_num_instructions; p++) {
|
||||
payload[p] = kernel_info->patches[i].payload[p];
|
||||
}
|
||||
if (kernel_info->hooks[i].branch_back_offset) {
|
||||
payload[kernel_info->hooks[i].payload_num_instructions] = MAKE_BRANCH(free_space_offset + sizeof(instruction_t) * kernel_info->hooks[i].payload_num_instructions, (uint32_t)(kernel_info->hooks[i].branch_back_offset + (uintptr_t)hook_start - (uintptr_t)kernel));
|
||||
if (kernel_info->patches[i].branch_back_offset) {
|
||||
payload[kernel_info->patches[i].payload_num_instructions] = MAKE_BRANCH(free_space_offset + sizeof(instruction_t) * kernel_info->patches[i].payload_num_instructions, (uint32_t)(kernel_info->patches[i].branch_back_offset + (uintptr_t)hook_start - (uintptr_t)kernel));
|
||||
}
|
||||
|
||||
free_space_offset += hook_size;
|
||||
|
||||
@@ -54,8 +54,9 @@ static const uint8_t AL16 masterkey_4x_seed[0x10] = {
|
||||
0x2D, 0xC1, 0xF4, 0x8D, 0xF3, 0x5B, 0x69, 0x33, 0x42, 0x10, 0xAC, 0x65, 0xDA, 0x90, 0x46, 0x66
|
||||
};
|
||||
|
||||
static const uint8_t AL16 new_master_kek_seeds[1][0x10] = {
|
||||
static const uint8_t AL16 new_master_kek_seeds[MASTERKEY_REVISION_700_CURRENT - MASTERKEY_REVISION_600_610][0x10] = {
|
||||
{0x37, 0x4B, 0x77, 0x29, 0x59, 0xB4, 0x04, 0x30, 0x81, 0xF6, 0xE5, 0x8C, 0x6D, 0x36, 0x17, 0x9A}, /* MasterKek seed 06. */
|
||||
{0x9A, 0x3E, 0xA9, 0xAB, 0xFD, 0x56, 0x46, 0x1C, 0x9B, 0xF6, 0x48, 0x7F, 0x5C, 0xFA, 0x09, 0x5C}, /* MasterKek seed 07. */
|
||||
};
|
||||
|
||||
static nx_dec_keyblob_t AL16 g_dec_keyblobs[32];
|
||||
@@ -118,7 +119,7 @@ int load_package1_key(uint32_t revision) {
|
||||
}
|
||||
|
||||
/* Derive all Switch keys. */
|
||||
int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, uint32_t available_revision, const void *tsec_key, void *tsec_root_key, unsigned int *out_keygen_type) {
|
||||
int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, uint32_t available_revision, const void *tsec_key, void *tsec_root_keys, unsigned int *out_keygen_type) {
|
||||
uint8_t AL16 work_buffer[0x10];
|
||||
uint8_t AL16 zeroes[0x10] = {0};
|
||||
|
||||
@@ -142,14 +143,31 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui
|
||||
|
||||
/* Do 6.2.0+ keygen. */
|
||||
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_620) {
|
||||
if (memcmp(tsec_root_key, zeroes, 0x10) != 0) {
|
||||
/* We got a valid key from emulation. */
|
||||
set_aes_keyslot(0xC, tsec_root_key, 0x10);
|
||||
for (unsigned int rev = MASTERKEY_REVISION_620_CURRENT; rev < MASTERKEY_REVISION_MAX; rev++) {
|
||||
se_aes_ecb_decrypt_block(0xC, work_buffer, 0x10, new_master_kek_seeds[rev - MASTERKEY_REVISION_620_CURRENT], 0x10);
|
||||
uint32_t desired_keyblob;
|
||||
switch (target_firmware) {
|
||||
case ATMOSPHERE_TARGET_FIRMWARE_620:
|
||||
desired_keyblob = MASTERKEY_REVISION_620;
|
||||
break;
|
||||
case ATMOSPHERE_TARGET_FIRMWARE_700:
|
||||
desired_keyblob = MASTERKEY_REVISION_700_CURRENT;
|
||||
break;
|
||||
default:
|
||||
fatal_error("Unknown target firmware: %02x!", target_firmware);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Try emulation result. */
|
||||
for (unsigned int rev = MASTERKEY_REVISION_620; rev < MASTERKEY_REVISION_MAX; rev++) {
|
||||
void *tsec_root_key = (void *)((uintptr_t)tsec_root_keys + 0x10 * (rev - MASTERKEY_REVISION_620));
|
||||
if (memcmp(tsec_root_key, zeroes, 0x10) != 0) {
|
||||
/* We got a valid key from emulation. */
|
||||
set_aes_keyslot(0xC, tsec_root_key, 0x10);
|
||||
se_aes_ecb_decrypt_block(0xC, work_buffer, 0x10, new_master_kek_seeds[rev - MASTERKEY_REVISION_620], 0x10);
|
||||
memcpy(g_dec_keyblobs[rev].master_kek, work_buffer, 0x10);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
if (memcmp(g_dec_keyblobs[desired_keyblob].master_kek, zeroes, 0x10) == 0) {
|
||||
/* Try reading the keys from a file. */
|
||||
const char *keyfile = fuse_get_retail_type() != 0 ? "atmosphere/prod.keys" : "atmosphere/dev.keys";
|
||||
FILE *extkey_file = fopen(keyfile, "r");
|
||||
@@ -159,20 +177,18 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui
|
||||
}
|
||||
extkeys_initialize_keyset(&extkeys, extkey_file);
|
||||
fclose(extkey_file);
|
||||
|
||||
if (memcmp(extkeys.tsec_root_key, zeroes, 0x10) != 0) {
|
||||
set_aes_keyslot(0xC, extkeys.tsec_root_key, 0x10);
|
||||
for (unsigned int rev = MASTERKEY_REVISION_620_CURRENT; rev < MASTERKEY_REVISION_MAX; rev++) {
|
||||
se_aes_ecb_decrypt_block(0xC, work_buffer, 0x10, new_master_kek_seeds[rev - MASTERKEY_REVISION_620_CURRENT], 0x10);
|
||||
for (unsigned int rev = MASTERKEY_REVISION_620; rev < MASTERKEY_REVISION_MAX; rev++) {
|
||||
if (memcmp(extkeys.tsec_root_keys[rev - MASTERKEY_REVISION_620], zeroes, 0x10) != 0) {
|
||||
set_aes_keyslot(0xC, extkeys.tsec_root_keys[rev - MASTERKEY_REVISION_620], 0x10);
|
||||
se_aes_ecb_decrypt_block(0xC, work_buffer, 0x10, new_master_kek_seeds[rev - MASTERKEY_REVISION_620], 0x10);
|
||||
memcpy(g_dec_keyblobs[rev].master_kek, work_buffer, 0x10);
|
||||
}
|
||||
} else {
|
||||
for (unsigned int rev = MASTERKEY_REVISION_620_CURRENT; rev < MASTERKEY_REVISION_MAX; rev++) {
|
||||
} else {
|
||||
memcpy(g_dec_keyblobs[rev].master_kek, extkeys.master_keks[rev], 0x10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (memcmp(g_dec_keyblobs[available_revision].master_kek, zeroes, 0x10) == 0) {
|
||||
fatal_error("Error: failed to derive master_kek_%02x!", available_revision);
|
||||
}
|
||||
@@ -206,6 +222,7 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui
|
||||
case ATMOSPHERE_TARGET_FIRMWARE_500:
|
||||
case ATMOSPHERE_TARGET_FIRMWARE_600:
|
||||
case ATMOSPHERE_TARGET_FIRMWARE_620:
|
||||
case ATMOSPHERE_TARGET_FIRMWARE_700:
|
||||
decrypt_data_into_keyslot(0xA, 0xF, devicekey_4x_seed, 0x10);
|
||||
decrypt_data_into_keyslot(0xF, 0xF, devicekey_seed, 0x10);
|
||||
decrypt_data_into_keyslot(0xE, 0xC, masterkey_4x_seed, 0x10);
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include "log.h"
|
||||
#include "../console.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -100,7 +101,10 @@ void print(ScreenLogLevel screen_log_level, const char * fmt, ...)
|
||||
char buf[PRINT_MESSAGE_MAX_LENGTH] = {};
|
||||
char message[PRINT_MESSAGE_MAX_LENGTH] = {};
|
||||
|
||||
/* TODO: make splash disappear if level > MANDATORY */
|
||||
/* Make splash disappear if level is ERROR or WARNING */
|
||||
if (screen_log_level < SCREEN_LOG_LEVEL_MANDATORY) {
|
||||
console_resume();
|
||||
}
|
||||
|
||||
/* make prefix free messages with log_level possible */
|
||||
if(screen_log_level & SCREEN_LOG_LEVEL_NO_PREFIX) {
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "fs_utils.h"
|
||||
#include "nxfs.h"
|
||||
#include "gpt.h"
|
||||
#include "splash_screen.h"
|
||||
#include "display/video_fb.h"
|
||||
#include "sdmmc/sdmmc.h"
|
||||
#include "lib/log.h"
|
||||
@@ -95,8 +96,16 @@ int main(int argc, void **argv) {
|
||||
/* Initialize the display, console, FS, etc. */
|
||||
setup_env();
|
||||
|
||||
print(SCREEN_LOG_LEVEL_MANDATORY, u8"Welcome to Atmosphère Fusée Stage 2!\n");
|
||||
print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, u8"Welcome to Atmosphère Fusée Stage 2!\n");
|
||||
print(SCREEN_LOG_LEVEL_DEBUG, "Stage 2 executing from: %s\n", (const char *)argv[STAGE2_ARGV_PROGRAM_PATH]);
|
||||
|
||||
/* Load BCT0 from SD if needed. */
|
||||
if (strcmp(g_stage2_args->bct0, "") == 0) {
|
||||
read_from_file(g_stage2_args->bct0, sizeof(g_stage2_args->bct0) - 1, "atmosphere/BCT.ini");
|
||||
if (!read_from_file(g_stage2_args->bct0, sizeof(g_stage2_args->bct0) - 1, "atmosphere/BCT.ini")) {
|
||||
fatal_error("Failed to read BCT0 from SD!\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* This will load all remaining binaries off of the SD. */
|
||||
load_payload(g_stage2_args->bct0);
|
||||
@@ -105,8 +114,11 @@ int main(int argc, void **argv) {
|
||||
|
||||
g_do_nxboot = loader_ctx->chainload_entrypoint == 0;
|
||||
if (g_do_nxboot) {
|
||||
print(SCREEN_LOG_LEVEL_MANDATORY, "Now performing nxboot.\n");
|
||||
print(SCREEN_LOG_LEVEL_INFO, "Now performing nxboot.\n");
|
||||
uint32_t boot_memaddr = nxboot_main();
|
||||
/* Wait for the splash screen to have been displayed as long as it should be. */
|
||||
splash_screen_wait_delay();
|
||||
/* Finish boot. */
|
||||
nxboot_finish(boot_memaddr);
|
||||
} else {
|
||||
/* TODO: What else do we want to do in terms of argc/argv? */
|
||||
|
||||
@@ -38,6 +38,7 @@ static const uint8_t mkey_vectors_dev[MASTERKEY_REVISION_MAX][0x10] =
|
||||
{0x9B, 0x84, 0x76, 0x14, 0x72, 0x94, 0x52, 0xCB, 0x54, 0x92, 0x9B, 0xC4, 0x8C, 0x5B, 0x0F, 0xBA}, /* Master key 03 encrypted with Master key 04. */
|
||||
{0x78, 0xD5, 0xF1, 0x20, 0x3D, 0x16, 0xE9, 0x30, 0x32, 0x27, 0x34, 0x6F, 0xCF, 0xE0, 0x27, 0xDC}, /* Master key 04 encrypted with Master key 05. */
|
||||
{0x6F, 0xD2, 0x84, 0x1D, 0x05, 0xEC, 0x40, 0x94, 0x5F, 0x18, 0xB3, 0x81, 0x09, 0x98, 0x8D, 0x4E}, /* Master key 05 encrypted with Master key 06. */
|
||||
{0x37, 0xAF, 0xAB, 0x35, 0x79, 0x09, 0xD9, 0x48, 0x29, 0xD2, 0xDB, 0xA5, 0xA5, 0xF5, 0x30, 0x19}, /* Master key 06 encrypted with Master key 07. */
|
||||
};
|
||||
|
||||
/* Retail unit keys. */
|
||||
@@ -50,6 +51,7 @@ static const uint8_t mkey_vectors[MASTERKEY_REVISION_MAX][0x10] =
|
||||
{0x6E, 0x7D, 0x2D, 0xC3, 0x0F, 0x59, 0xC8, 0xFA, 0x87, 0xA8, 0x2E, 0xD5, 0x89, 0x5E, 0xF3, 0xE9}, /* Master key 03 encrypted with Master key 04. */
|
||||
{0xEB, 0xF5, 0x6F, 0x83, 0x61, 0x9E, 0xF8, 0xFA, 0xE0, 0x87, 0xD7, 0xA1, 0x4E, 0x25, 0x36, 0xEE}, /* Master key 04 encrypted with Master key 05. */
|
||||
{0x1E, 0x1E, 0x22, 0xC0, 0x5A, 0x33, 0x3C, 0xB9, 0x0B, 0xA9, 0x03, 0x04, 0xBA, 0xDB, 0x07, 0x57}, /* Master key 05 encrypted with Master key 06. */
|
||||
{0xA4, 0xD4, 0x52, 0x6F, 0xD1, 0xE4, 0x36, 0xAA, 0x9F, 0xCB, 0x61, 0x27, 0x1C, 0x67, 0x65, 0x1F}, /* Master key 06 encrypted with Master key 07. */
|
||||
};
|
||||
|
||||
static bool check_mkey_revision(unsigned int revision, bool is_retail) {
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
/* This is glue code to enable master key support across versions. */
|
||||
|
||||
/* TODO: Update to 0x8 on release of new master key. */
|
||||
#define MASTERKEY_REVISION_MAX 0x7
|
||||
#define MASTERKEY_REVISION_MAX 0x8
|
||||
|
||||
#define MASTERKEY_REVISION_100_230 0x00
|
||||
#define MASTERKEY_REVISION_300 0x01
|
||||
@@ -28,7 +28,8 @@
|
||||
#define MASTERKEY_REVISION_400_410 0x03
|
||||
#define MASTERKEY_REVISION_500_510 0x04
|
||||
#define MASTERKEY_REVISION_600_610 0x05
|
||||
#define MASTERKEY_REVISION_620_CURRENT 0x06
|
||||
#define MASTERKEY_REVISION_620 0x06
|
||||
#define MASTERKEY_REVISION_700_CURRENT 0x07
|
||||
|
||||
#define MASTERKEY_NUM_NEW_DEVICE_KEYS (MASTERKEY_REVISION_MAX - MASTERKEY_REVISION_400_410)
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "mc.h"
|
||||
#include "se.h"
|
||||
#include "pmc.h"
|
||||
#include "emc.h"
|
||||
#include "fuse.h"
|
||||
#include "i2c.h"
|
||||
#include "ips.h"
|
||||
@@ -37,20 +38,22 @@
|
||||
#include "flow.h"
|
||||
#include "timers.h"
|
||||
#include "key_derivation.h"
|
||||
#include "masterkey.h"
|
||||
#include "package1.h"
|
||||
#include "package2.h"
|
||||
#include "smmu.h"
|
||||
#include "tsec.h"
|
||||
#include "lp0.h"
|
||||
#include "loader.h"
|
||||
#include "splash_screen.h"
|
||||
#include "exocfg.h"
|
||||
#include "display/video_fb.h"
|
||||
#include "lib/ini.h"
|
||||
#include "splash_screen.h"
|
||||
|
||||
#define u8 uint8_t
|
||||
#define u32 uint32_t
|
||||
#include "exosphere_bin.h"
|
||||
#include "sept_secondary_enc.h"
|
||||
#include "lp0fw_bin.h"
|
||||
#include "lib/log.h"
|
||||
#undef u8
|
||||
@@ -167,15 +170,17 @@ static uint32_t nxboot_get_target_firmware(const void *package1loader) {
|
||||
fatal_error("[NXBOOT]: Unable to identify package1!\n");
|
||||
}
|
||||
}
|
||||
case 0x0F:
|
||||
return ATMOSPHERE_TARGET_FIRMWARE_700;
|
||||
default:
|
||||
return 0;
|
||||
fatal_error("[NXBOOT]: Unable to identify package1!\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void nxboot_configure_exosphere(uint32_t target_firmware, unsigned int keygen_type) {
|
||||
exosphere_config_t exo_cfg = {0};
|
||||
|
||||
exo_cfg.magic = MAGIC_EXOSPHERE_BOOTCONFIG;
|
||||
exo_cfg.magic = MAGIC_EXOSPHERE_CONFIG;
|
||||
exo_cfg.target_firmware = target_firmware;
|
||||
if (keygen_type) {
|
||||
exo_cfg.flags = EXOSPHERE_FLAGS_DEFAULT | EXOSPHERE_FLAG_PERFORM_620_KEYGEN;
|
||||
@@ -213,7 +218,7 @@ static void nxboot_configure_stratosphere(uint32_t target_firmware) {
|
||||
}
|
||||
}
|
||||
|
||||
static void nxboot_set_bootreason() {
|
||||
static void nxboot_set_bootreason(void *bootreason_base) {
|
||||
boot_reason_t boot_reason = {0};
|
||||
FILE *boot0;
|
||||
nvboot_config_table *bct;
|
||||
@@ -265,7 +270,7 @@ static void nxboot_set_bootreason() {
|
||||
boot_reason.boot_reason_state = 0x04;
|
||||
|
||||
/* Set in memory. */
|
||||
memcpy((void *)MAILBOX_NX_BOOTLOADER_BOOT_REASON_BASE, &boot_reason, sizeof(boot_reason));
|
||||
memcpy(bootreason_base, &boot_reason, sizeof(boot_reason));
|
||||
|
||||
/* Clean up. */
|
||||
free(bct);
|
||||
@@ -306,6 +311,12 @@ static void nxboot_move_bootconfig() {
|
||||
free(bootconfig);
|
||||
}
|
||||
|
||||
static bool get_and_clear_has_run_sept(void) {
|
||||
bool has_run_sept = (MAKE_EMC_REG(EMC_SCRATCH0) & 0x80000000) != 0;
|
||||
MAKE_EMC_REG(EMC_SCRATCH0) &= ~0x80000000;
|
||||
return has_run_sept;
|
||||
}
|
||||
|
||||
/* This is the main function responsible for booting Horizon. */
|
||||
static nx_keyblob_t __attribute__((aligned(16))) g_keyblobs[32];
|
||||
uint32_t nxboot_main(void) {
|
||||
@@ -382,7 +393,7 @@ uint32_t nxboot_main(void) {
|
||||
/* Read the TSEC firmware from a file, otherwise from PK1L. */
|
||||
if (loader_ctx->tsecfw_path[0] != '\0') {
|
||||
tsec_fw_size = get_file_size(loader_ctx->tsecfw_path);
|
||||
if ((tsec_fw_size != 0) && (tsec_fw_size != 0xF00 && tsec_fw_size != 0x2900)) {
|
||||
if ((tsec_fw_size != 0) && (tsec_fw_size != 0xF00 && tsec_fw_size != 0x2900 && tsec_fw_size != 0x3000)) {
|
||||
fatal_error("[NXBOOT]: TSEC firmware from %s has a wrong size!\n", loader_ctx->tsecfw_path);
|
||||
} else if (tsec_fw_size == 0) {
|
||||
fatal_error("[NXBOOT]: Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path);
|
||||
@@ -401,19 +412,31 @@ uint32_t nxboot_main(void) {
|
||||
if (!package1_get_tsec_fw(&tsec_fw, package1loader, package1loader_size)) {
|
||||
fatal_error("[NXBOOT]: Failed to read the TSEC firmware from Package1loader!\n");
|
||||
}
|
||||
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_620) {
|
||||
if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_700) {
|
||||
tsec_fw_size = 0x3000;
|
||||
} else if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_620) {
|
||||
tsec_fw_size = 0x2900;
|
||||
} else {
|
||||
tsec_fw_size = 0xF00;
|
||||
}
|
||||
}
|
||||
|
||||
print(SCREEN_LOG_LEVEL_MANDATORY, "[NXBOOT]: Loaded firmware from eMMC...\n");
|
||||
|
||||
print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Loaded firmware from eMMC...\n");
|
||||
|
||||
/* Get the TSEC keys. */
|
||||
uint8_t tsec_key[0x10] = {0};
|
||||
uint8_t tsec_root_key[0x10] = {0};
|
||||
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_620) {
|
||||
uint8_t tsec_root_keys[0x20][0x10] = {0};
|
||||
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_700) {
|
||||
/* Detect whether we need to run sept-secondary in order to derive keys. */
|
||||
if (!get_and_clear_has_run_sept()) {
|
||||
reboot_to_sept(tsec_fw, tsec_fw_size, sept_secondary_enc, sept_secondary_enc_size);
|
||||
} else {
|
||||
if (mkey_detect_revision(fuse_get_retail_type() != 0) != 0) {
|
||||
fatal_error("[NXBOOT]: Sept derived incorrect keys!\n");
|
||||
}
|
||||
}
|
||||
get_and_clear_has_run_sept();
|
||||
} else if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_620) {
|
||||
uint8_t tsec_keys[0x20] = {0};
|
||||
|
||||
/* Emulate the TSEC payload on 6.2.0+. */
|
||||
@@ -421,7 +444,7 @@ uint32_t nxboot_main(void) {
|
||||
|
||||
/* Copy back the keys. */
|
||||
memcpy((void *)tsec_key, (void *)tsec_keys, 0x10);
|
||||
memcpy((void *)tsec_root_key, (void *)tsec_keys + 0x10, 0x10);
|
||||
memcpy((void *)tsec_root_keys, (void *)tsec_keys + 0x10, 0x10);
|
||||
} else {
|
||||
/* Run the TSEC payload and get the key. */
|
||||
if (tsec_get_key(tsec_key, 1, tsec_fw, tsec_fw_size) != 0) {
|
||||
@@ -429,19 +452,25 @@ uint32_t nxboot_main(void) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Derive keydata. */
|
||||
//fatal_error("Ran sept!");
|
||||
/* Display splash screen. */
|
||||
display_splash_screen_bmp(loader_ctx->custom_splash_path, (void *)0xC0000000);
|
||||
|
||||
/* Derive keydata. If on 7.0.0+, sept has already derived keys for us. */
|
||||
unsigned int keygen_type = 0;
|
||||
if (derive_nx_keydata(target_firmware, g_keyblobs, available_revision, tsec_key, tsec_root_key, &keygen_type) != 0) {
|
||||
fatal_error("[NXBOOT]: Key derivation failed!\n");
|
||||
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_700) {
|
||||
if (derive_nx_keydata(target_firmware, g_keyblobs, available_revision, tsec_key, tsec_root_keys, &keygen_type) != 0) {
|
||||
fatal_error("[NXBOOT]: Key derivation failed!\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup boot configuration for Exosphère. */
|
||||
nxboot_configure_exosphere(target_firmware, keygen_type);
|
||||
|
||||
/* Initialize Boot Reason on older firmware versions. */
|
||||
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) {
|
||||
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) {
|
||||
print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Initializing Boot Reason...\n");
|
||||
nxboot_set_bootreason();
|
||||
nxboot_set_bootreason((void *)MAILBOX_NX_BOOTLOADER_BOOT_REASON_BASE(target_firmware));
|
||||
}
|
||||
|
||||
/* Read the warmboot firmware from a file, otherwise from Atmosphere's implementation. */
|
||||
@@ -495,8 +524,10 @@ uint32_t nxboot_main(void) {
|
||||
warmboot_memaddr = (void *)0x8000D000;
|
||||
} else if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_600) {
|
||||
warmboot_memaddr = (void *)0x4003B000;
|
||||
} else {
|
||||
} else if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_700) {
|
||||
warmboot_memaddr = (void *)0x4003D800;
|
||||
} else {
|
||||
warmboot_memaddr = (void *)0x4003E000;
|
||||
}
|
||||
|
||||
print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Copying warmboot firmware...\n");
|
||||
@@ -508,11 +539,13 @@ uint32_t nxboot_main(void) {
|
||||
pmc->scratch1 = (uint32_t)warmboot_memaddr;
|
||||
}
|
||||
|
||||
print(SCREEN_LOG_LEVEL_MANDATORY, "[NXBOOT]: Rebuilding package2...\n");
|
||||
print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Rebuilding package2...\n");
|
||||
|
||||
/* Parse stratosphere config. */
|
||||
nxboot_configure_stratosphere(MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware);
|
||||
|
||||
print(SCREEN_LOG_LEVEL_INFO, u8"[NXBOOT]: Configured Stratosphere...\n");
|
||||
|
||||
/* Patch package2, adding Thermosphère + custom KIPs. */
|
||||
package2_rebuild_and_copy(package2, MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware);
|
||||
|
||||
@@ -567,9 +600,6 @@ uint32_t nxboot_main(void) {
|
||||
|
||||
print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Powering on the CCPLEX...\n");
|
||||
|
||||
/* Display splash screen. */
|
||||
display_splash_screen_bmp(loader_ctx->custom_splash_path, (void *)0xC0000000);
|
||||
|
||||
/* Unmount everything. */
|
||||
nxfs_unmount_all();
|
||||
|
||||
|
||||
@@ -19,12 +19,14 @@
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#define MAILBOX_NX_BOOTLOADER_BASE 0x40002000
|
||||
#define MAILBOX_NX_BOOTLOADER_BOOT_REASON_BASE (MAILBOX_NX_BOOTLOADER_BASE + 0xE10)
|
||||
#define MAKE_MAILBOX_NX_BOOTLOADER_REG(n) MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE + n)
|
||||
#define MAILBOX_NX_BOOTLOADER_BASE_100_620 0x40002E00
|
||||
#define MAILBOX_NX_BOOTLOADER_BASE_700 0x40000000
|
||||
#define MAILBOX_NX_BOOTLOADER_BASE(targetfw) ((targetfw >= ATMOSPHERE_TARGET_FIRMWARE_700) ? (MAILBOX_NX_BOOTLOADER_BASE_700) : (MAILBOX_NX_BOOTLOADER_BASE_100_620))
|
||||
#define MAKE_MAILBOX_NX_BOOTLOADER_REG(targetfw, n) MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE(targetfw) + n)
|
||||
|
||||
#define MAILBOX_NX_BOOTLOADER_SETUP_STATE MAKE_MAILBOX_NX_BOOTLOADER_REG(0xEF8)
|
||||
#define MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE MAKE_MAILBOX_NX_BOOTLOADER_REG(0xEFC)
|
||||
#define MAILBOX_NX_BOOTLOADER_BOOT_REASON_BASE(targetfw) (MAILBOX_NX_BOOTLOADER_BASE(targetfw) + 0x10)
|
||||
#define MAILBOX_NX_BOOTLOADER_SETUP_STATE(targetfw) MAKE_MAILBOX_NX_BOOTLOADER_REG(targetfw, 0xF8)
|
||||
#define MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE(targetfw) MAKE_MAILBOX_NX_BOOTLOADER_REG(targetfw, 0xFC)
|
||||
|
||||
#define NX_BOOTLOADER_STATE_INIT 0
|
||||
#define NX_BOOTLOADER_STATE_MOVED_BOOTCONFIG 1
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "sysreg.h"
|
||||
|
||||
void nxboot_finish(uint32_t boot_memaddr) {
|
||||
uint32_t target_firmware = MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware;
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
|
||||
/* Clear used keyslots. */
|
||||
@@ -36,7 +37,7 @@ void nxboot_finish(uint32_t boot_memaddr) {
|
||||
|
||||
/* Lock keyslots. */
|
||||
set_aes_keyslot_flags(KEYSLOT_SWITCH_MASTERKEY, 0xFF);
|
||||
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) {
|
||||
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) {
|
||||
set_aes_keyslot_flags(KEYSLOT_SWITCH_DEVICEKEY, 0xFF);
|
||||
} else {
|
||||
set_aes_keyslot_flags(KEYSLOT_SWITCH_4XOLDDEVICEKEY, 0xFF);
|
||||
@@ -61,11 +62,11 @@ void nxboot_finish(uint32_t boot_memaddr) {
|
||||
se->_0x0 &= 0xFFFFFFFB;
|
||||
|
||||
/* Boot up Exosphère. */
|
||||
MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE = 0;
|
||||
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) {
|
||||
MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_LOADED_PACKAGE2;
|
||||
MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE(target_firmware) = 0;
|
||||
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) {
|
||||
MAILBOX_NX_BOOTLOADER_SETUP_STATE(target_firmware) = NX_BOOTLOADER_STATE_LOADED_PACKAGE2;
|
||||
} else {
|
||||
MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X;
|
||||
MAILBOX_NX_BOOTLOADER_SETUP_STATE(target_firmware) = NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X;
|
||||
}
|
||||
|
||||
/* Terminate the display. */
|
||||
@@ -88,15 +89,15 @@ void nxboot_finish(uint32_t boot_memaddr) {
|
||||
}
|
||||
|
||||
/* Wait for Exosphère to wake up. */
|
||||
while (MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE == 0) {
|
||||
while (MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE(target_firmware) == 0) {
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
/* Signal Exosphère. */
|
||||
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) {
|
||||
MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_FINISHED;
|
||||
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) {
|
||||
MAILBOX_NX_BOOTLOADER_SETUP_STATE(target_firmware) = NX_BOOTLOADER_STATE_FINISHED;
|
||||
} else {
|
||||
MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_FINISHED_4X;
|
||||
MAILBOX_NX_BOOTLOADER_SETUP_STATE(target_firmware) = NX_BOOTLOADER_STATE_FINISHED_4X;
|
||||
}
|
||||
|
||||
/* Halt ourselves in waitevent state. */
|
||||
|
||||
@@ -214,7 +214,7 @@ static bool package2_validate_metadata(package2_meta_t *metadata, uint8_t data[]
|
||||
|
||||
/* Perform version checks. */
|
||||
/* We will be compatible with all package2s released before current, but not newer ones. */
|
||||
if (metadata->version_max >= PACKAGE2_MINVER_THEORETICAL && metadata->version_min < PACKAGE2_MAXVER_620_CURRENT) {
|
||||
if (metadata->version_max >= PACKAGE2_MINVER_THEORETICAL && metadata->version_min < PACKAGE2_MAXVER_700_CURRENT) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,8 @@
|
||||
#define PACKAGE2_MAXVER_400_410 0x6
|
||||
#define PACKAGE2_MAXVER_500_510 0x7
|
||||
#define PACKAGE2_MAXVER_600_610 0x8
|
||||
#define PACKAGE2_MAXVER_620_CURRENT 0x9
|
||||
#define PACKAGE2_MAXVER_620 0x9
|
||||
#define PACKAGE2_MAXVER_700_CURRENT 0xA
|
||||
|
||||
#define PACKAGE2_MINVER_100 0x3
|
||||
#define PACKAGE2_MINVER_200 0x4
|
||||
@@ -44,7 +45,8 @@
|
||||
#define PACKAGE2_MINVER_400_410 0x7
|
||||
#define PACKAGE2_MINVER_500_510 0x8
|
||||
#define PACKAGE2_MINVER_600_610 0x9
|
||||
#define PACKAGE2_MINVER_620_CURRENT 0xA
|
||||
#define PACKAGE2_MINVER_620 0xA
|
||||
#define PACKAGE2_MINVER_700_CURRENT 0xB
|
||||
|
||||
#define NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS ((void *)(0xA9800000ull))
|
||||
|
||||
|
||||
@@ -61,6 +61,11 @@
|
||||
#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;
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
#undef u8
|
||||
#undef u32
|
||||
|
||||
static uint32_t g_splash_start_time = 0;
|
||||
|
||||
static void render_bmp(const uint32_t *bmp_data, uint32_t *framebuffer, uint32_t bmp_width, uint32_t bmp_height, uint32_t bmp_pos_x, uint32_t bmp_pos_y) {
|
||||
/* Render the BMP. */
|
||||
for (uint32_t y = bmp_pos_y; y < (bmp_pos_y + bmp_height); y++) {
|
||||
@@ -39,6 +41,11 @@ static void render_bmp(const uint32_t *bmp_data, uint32_t *framebuffer, uint32_t
|
||||
console_display(framebuffer);
|
||||
}
|
||||
|
||||
void splash_screen_wait_delay(void) {
|
||||
/* Ensure the splash screen is displayed for at least three seconds. */
|
||||
udelay_absolute(g_splash_start_time, 3000000);
|
||||
}
|
||||
|
||||
void display_splash_screen_bmp(const char *custom_splash_path, void *fb_address) {
|
||||
uint8_t *splash_screen = (uint8_t *)splash_screen_bmp;
|
||||
|
||||
@@ -84,7 +91,7 @@ void display_splash_screen_bmp(const char *custom_splash_path, void *fb_address)
|
||||
} else {
|
||||
fatal_error("Invalid splash screen format!\n");
|
||||
}
|
||||
|
||||
/* Display the splash screen for three seconds. */
|
||||
udelay(3000000);
|
||||
|
||||
/* Note the time we started displaying the splash. */
|
||||
g_splash_start_time = get_time_us();
|
||||
}
|
||||
|
||||
@@ -26,5 +26,6 @@
|
||||
#define SPLASH_SCREEN_SIZE_MAX (SPLASH_SCREEN_HEIGHT_MAX * SPLASH_SCREEN_STRIDE * 4)
|
||||
|
||||
void display_splash_screen_bmp(const char *custom_splash_path, void *fb_address);
|
||||
void splash_screen_wait_delay(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "loader_kip.h"
|
||||
#include "pm_kip.h"
|
||||
#include "sm_kip.h"
|
||||
#include "ams_mitm_kip.h"
|
||||
#include "boot_100_kip.h"
|
||||
#include "boot_200_kip.h"
|
||||
#undef u8
|
||||
@@ -43,13 +44,13 @@ static ini1_header_t *g_sd_files_ini1 = NULL;
|
||||
static bool g_stratosphere_loader_enabled = true;
|
||||
static bool g_stratosphere_sm_enabled = true;
|
||||
static bool g_stratosphere_pm_enabled = true;
|
||||
static bool g_stratosphere_fs_mitm_enabled = true;
|
||||
static bool g_stratosphere_ams_mitm_enabled = true;
|
||||
static bool g_stratosphere_boot_enabled = false;
|
||||
|
||||
extern const uint8_t boot_100_kip[], boot_200_kip[];
|
||||
extern const uint8_t loader_kip[], pm_kip[], sm_kip[], fs_mitm_kip[];
|
||||
extern const uint8_t loader_kip[], pm_kip[], sm_kip[], ams_mitm_kip[];
|
||||
extern const uint32_t boot_100_kip_size, boot_200_kip_size;
|
||||
extern const uint32_t loader_kip_size, pm_kip_size, sm_kip_size, fs_mitm_kip_size;
|
||||
extern const uint32_t loader_kip_size, pm_kip_size, sm_kip_size, ams_mitm_kip_size;
|
||||
|
||||
/* GCC doesn't consider the size as const... we have to write it ourselves. */
|
||||
|
||||
@@ -89,8 +90,8 @@ ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware) {
|
||||
num_processes++;
|
||||
}
|
||||
|
||||
if (g_stratosphere_fs_mitm_enabled) {
|
||||
size += fs_mitm_kip_size;
|
||||
if (g_stratosphere_ams_mitm_enabled) {
|
||||
size += ams_mitm_kip_size;
|
||||
num_processes++;
|
||||
}
|
||||
|
||||
@@ -128,9 +129,9 @@ ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware) {
|
||||
data += sm_kip_size;
|
||||
}
|
||||
|
||||
if (g_stratosphere_fs_mitm_enabled) {
|
||||
memcpy(data, fs_mitm_kip, fs_mitm_kip_size);
|
||||
data += fs_mitm_kip_size;
|
||||
if (g_stratosphere_ams_mitm_enabled) {
|
||||
memcpy(data, ams_mitm_kip, ams_mitm_kip_size);
|
||||
data += ams_mitm_kip_size;
|
||||
}
|
||||
|
||||
if (g_stratosphere_boot_enabled) {
|
||||
|
||||
@@ -81,6 +81,13 @@ static inline void udelay(uint32_t usecs) {
|
||||
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.
|
||||
*/
|
||||
|
||||
@@ -29,6 +29,14 @@
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#define u8 uint8_t
|
||||
#define u32 uint32_t
|
||||
#include "fusee_primary_bin.h"
|
||||
#include "sept_primary_bin.h"
|
||||
#include "rebootstub_bin.h"
|
||||
#undef u8
|
||||
#undef u32
|
||||
|
||||
void wait(uint32_t microseconds) {
|
||||
uint32_t old_time = TIMERUS_CNTR_1US_0;
|
||||
while (TIMERUS_CNTR_1US_0 - old_time <= microseconds) {
|
||||
@@ -58,12 +66,78 @@ __attribute__((noreturn)) void pmc_reboot(uint32_t scratch0) {
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) static void reboot_to_payload(void) {
|
||||
/* Patch SDRAM init to perform an SVC immediately after second write */
|
||||
APBDEV_PMC_SCRATCH45_0 = 0x2E38DFFF;
|
||||
APBDEV_PMC_SCRATCH46_0 = 0x6001DC28;
|
||||
/* Set SVC handler to jump to reboot stub in IRAM. */
|
||||
APBDEV_PMC_SCRATCH33_0 = 0x4003F000;
|
||||
APBDEV_PMC_SCRATCH40_0 = 0x6000F208;
|
||||
|
||||
/* Copy reboot stub into IRAM high. */
|
||||
for (size_t i = 0; i < rebootstub_bin_size; i += sizeof(uint32_t)) {
|
||||
write32le((void *)0x4003F000, i, read32le(rebootstub_bin, i));
|
||||
}
|
||||
|
||||
/* Trigger warm reboot. */
|
||||
pmc_reboot(1 << 0);
|
||||
while (true) { }
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) void reboot_to_fusee_primary(void) {
|
||||
/* Copy fusee-primary into IRAM low. */
|
||||
for (size_t i = 0; i < fusee_primary_bin_size; i += sizeof(uint32_t)) {
|
||||
write32le((void *)0x40010000, i, read32le(fusee_primary_bin, i));
|
||||
}
|
||||
|
||||
reboot_to_payload();
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) void reboot_to_sept(const void *tsec_fw, size_t tsec_fw_length, const void *stage2, size_t stage2_size) {
|
||||
|
||||
/* Copy tsec firmware. */
|
||||
for (size_t i = 0; i < tsec_fw_length; i += sizeof(uint32_t)) {
|
||||
write32le((void *)0x40010F00, i, read32le(tsec_fw, i));
|
||||
}
|
||||
MAKE_REG32(0x40010EFC) = tsec_fw_length;
|
||||
|
||||
/* Copy stage 2. */
|
||||
for (size_t i = 0; i < stage2_size; i += sizeof(uint32_t)) {
|
||||
write32le((void *)0x40016FE0, i, read32le(stage2, i));
|
||||
}
|
||||
|
||||
/* Copy sept into IRAM low. */
|
||||
for (size_t i = 0; i < sept_primary_bin_size; i += sizeof(uint32_t)) {
|
||||
write32le((void *)0x4003F000, i, read32le(sept_primary_bin, i));
|
||||
}
|
||||
|
||||
/* Patch SDRAM init to perform an SVC immediately after second write */
|
||||
APBDEV_PMC_SCRATCH45_0 = 0x2E38DFFF;
|
||||
APBDEV_PMC_SCRATCH46_0 = 0x6001DC28;
|
||||
/* Set SVC handler to jump to reboot stub in IRAM. */
|
||||
APBDEV_PMC_SCRATCH33_0 = 0x4003F000;
|
||||
APBDEV_PMC_SCRATCH40_0 = 0x6000F208;
|
||||
|
||||
/* Trigger warm reboot. */
|
||||
pmc_reboot(1 << 0);
|
||||
while (true) { }
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) void reboot_to_iram_payload(void *payload, size_t payload_size) {
|
||||
/* Copy sept into IRAM low. */
|
||||
for (size_t i = 0; i < payload_size; i += sizeof(uint32_t)) {
|
||||
write32le((void *)0x40010000, i, read32le(payload, i));
|
||||
}
|
||||
|
||||
reboot_to_payload();
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) void wait_for_button_and_reboot(void) {
|
||||
uint32_t button;
|
||||
while (true) {
|
||||
button = btn_read();
|
||||
if (button & BTN_POWER) {
|
||||
pmc_reboot(1 << 1);
|
||||
reboot_to_fusee_primary();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,6 +122,9 @@ void hexdump(const void* data, size_t size, uintptr_t addrbase);
|
||||
|
||||
__attribute__((noreturn)) void watchdog_reboot(void);
|
||||
__attribute__((noreturn)) void pmc_reboot(uint32_t scratch0);
|
||||
__attribute__((noreturn)) void reboot_to_fusee_primary(void);
|
||||
__attribute__((noreturn)) void reboot_to_sept(const void *tsec_fw, size_t tsec_fw_length, const void *stage2, size_t stage2_size);
|
||||
__attribute__((noreturn)) void reboot_to_iram_payload(void *payload, size_t payload_size);
|
||||
__attribute__((noreturn)) void wait_for_button_and_reboot(void);
|
||||
void wait_for_button(void);
|
||||
|
||||
|
||||
10
sept/Makefile
Normal file
10
sept/Makefile
Normal file
@@ -0,0 +1,10 @@
|
||||
SUBFOLDERS := sept-primary sept-secondary
|
||||
|
||||
TOPTARGETS := all clean
|
||||
|
||||
$(TOPTARGETS): $(SUBFOLDERS)
|
||||
|
||||
$(SUBFOLDERS):
|
||||
$(MAKE) -C $@ $(MAKECMDGOALS)
|
||||
|
||||
.PHONY: $(TOPTARGETS) $(SUBFOLDERS)
|
||||
169
sept/sept-primary/Makefile
Normal file
169
sept/sept-primary/Makefile
Normal file
@@ -0,0 +1,169 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
TOPDIR ?= $(CURDIR)
|
||||
|
||||
AMS := $(TOPDIR)/../../
|
||||
include $(DEVKITARM)/base_rules
|
||||
|
||||
AMSBRANCH := $(shell git symbolic-ref --short HEAD)
|
||||
AMSREV := $(AMSBRANCH)-$(shell git rev-parse --short HEAD)
|
||||
|
||||
ifneq (, $(strip $(shell git status --porcelain 2>/dev/null)))
|
||||
AMSREV := $(AMSREV)-dirty
|
||||
endif
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# 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
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := $(notdir $(CURDIR))
|
||||
BUILD := build
|
||||
SOURCES := src src/sdmmc src/lib src/lib/fatfs src/display
|
||||
DATA := data
|
||||
INCLUDES := include ../../common/include
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork
|
||||
DEFINES := -D__BPMP__ -DFUSEE_STAGE1_SRC -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\"
|
||||
|
||||
CFLAGS := \
|
||||
-g \
|
||||
-O2 \
|
||||
-fomit-frame-pointer \
|
||||
-ffunction-sections \
|
||||
-fdata-sections \
|
||||
-std=gnu11 \
|
||||
-Werror \
|
||||
-Wall \
|
||||
-fstrict-volatile-bitfields \
|
||||
$(ARCH) $(DEFINES)
|
||||
|
||||
CFLAGS += $(INCLUDE)
|
||||
|
||||
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
|
||||
|
||||
ASFLAGS := -g $(ARCH)
|
||||
LDFLAGS = -specs=$(TOPDIR)/linker.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||
|
||||
LIBS :=
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS :=
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# 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 OUTPUT := $(CURDIR)/$(TARGET)
|
||||
export TOPDIR := $(CURDIR)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
|
||||
$(AMS)/exosphere/rebootstub
|
||||
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) rebootstub.bin
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# 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$(CURDIR)/$(BUILD)
|
||||
|
||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
|
||||
.PHONY: $(BUILD) clean all check_rebootstub
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
all: check_rebootstub $(BUILD)
|
||||
|
||||
check_rebootstub:
|
||||
@$(MAKE) -C $(AMS)/exosphere/rebootstub all
|
||||
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@$(MAKE) -C $(AMS)/exosphere/rebootstub clean
|
||||
@rm -fr $(BUILD) $(TARGET).bin $(TARGET).elf
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
.PHONY: all
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
all : $(OUTPUT).bin
|
||||
|
||||
$(OUTPUT).bin : $(OUTPUT).elf
|
||||
$(OBJCOPY) -S -O binary $< $@
|
||||
@echo built ... $(notdir $@)
|
||||
|
||||
$(OUTPUT).elf : $(OFILES)
|
||||
|
||||
%.elf: $(OFILES)
|
||||
@echo linking $(notdir $@)
|
||||
@$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
|
||||
@$(NM) -CSn $@ > $(notdir $*.lst)
|
||||
|
||||
$(OFILES_SRC) : $(HFILES_BIN)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# you need a rule like this for each extension you use as binary data
|
||||
#---------------------------------------------------------------------------------
|
||||
%.bin.o %_bin.h: %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
||||
168
sept/sept-primary/linker.ld
Normal file
168
sept/sept-primary/linker.ld
Normal file
@@ -0,0 +1,168 @@
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
ENTRY(_start)
|
||||
|
||||
PHDRS
|
||||
{
|
||||
crt0 PT_LOAD;
|
||||
main PT_LOAD;
|
||||
}
|
||||
|
||||
/* Mostly copied from https://github.com/devkitPro/buildscripts/blob/master/dkarm-eabi/crtls/3dsx.ld */
|
||||
MEMORY
|
||||
{
|
||||
NULL : ORIGIN = 0x00000000, LENGTH = 0x1000
|
||||
main : ORIGIN = 0x40010040, LENGTH = 0x1000
|
||||
high_iram : ORIGIN = 0x4003F000, LENGTH = 0x1000
|
||||
low_iram : ORIGIN = 0x40003000, LENGTH = 0x8000
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
PROVIDE(__crt0_start__ = 0x4003F000);
|
||||
PROVIDE(__main_start__ = 0x40010040);
|
||||
PROVIDE(__stack_top__ = 0x40010000);
|
||||
PROVIDE(__stack_bottom__ = 0x4000C000);
|
||||
PROVIDE(__heap_start__ = 0);
|
||||
PROVIDE(__heap_end__ = 0);
|
||||
|
||||
. = __crt0_start__;
|
||||
|
||||
.crt0 :
|
||||
{
|
||||
KEEP( *(.text.start) )
|
||||
KEEP( *(.text.ipatch_word) )
|
||||
KEEP( *(.init) )
|
||||
. = ALIGN(32);
|
||||
} >high_iram AT>high_iram :crt0
|
||||
|
||||
__main_phys_start__ = ABSOLUTE(.) ;
|
||||
|
||||
.text :
|
||||
{
|
||||
/* .text */
|
||||
KEEP( *(.text.jump_to_main) )
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
*(.glue_7)
|
||||
*(.glue_7t)
|
||||
*(.stub)
|
||||
*(.gnu.warning)
|
||||
*(.gnu.linkonce.t*)
|
||||
|
||||
/* .fini */
|
||||
KEEP( *(.fini) )
|
||||
. = ALIGN(8);
|
||||
} >main AT>high_iram :main
|
||||
|
||||
.rodata :
|
||||
{
|
||||
*(.rodata)
|
||||
*(.roda)
|
||||
*(.rodata.*)
|
||||
*all.rodata*(*)
|
||||
*(.gnu.linkonce.r*)
|
||||
SORT(CONSTRUCTORS)
|
||||
. = ALIGN(8);
|
||||
} >main AT>high_iram
|
||||
|
||||
.preinit_array :
|
||||
{
|
||||
PROVIDE (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE (__preinit_array_end = .);
|
||||
} >main AT>high_iram
|
||||
|
||||
.init_array ALIGN(4) :
|
||||
{
|
||||
PROVIDE (__init_array_start = .);
|
||||
KEEP (*(SORT(.init_array.*)))
|
||||
KEEP (*(.init_array))
|
||||
PROVIDE (__init_array_end = .);
|
||||
} >main AT>high_iram
|
||||
|
||||
.fini_array ALIGN(4) :
|
||||
{
|
||||
PROVIDE (__fini_array_start = .);
|
||||
KEEP (*(.fini_array))
|
||||
KEEP (*(SORT(.fini_array.*)))
|
||||
PROVIDE (__fini_array_end = .);
|
||||
} >main AT>high_iram
|
||||
|
||||
.ctors ALIGN(4) :
|
||||
{
|
||||
KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||
} >main AT>high_iram
|
||||
|
||||
.dtors ALIGN(4) :
|
||||
{
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||
} >main AT>high_iram
|
||||
|
||||
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) __exidx_start = ABSOLUTE(.);} >main AT>high_iram
|
||||
ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) __exidx_end = ABSOLUTE(.);} >main AT>high_iram
|
||||
|
||||
.bss (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(32);
|
||||
PROVIDE (__bss_start__ = ABSOLUTE(.));
|
||||
*(.dynbss)
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
*(.gnu.linkonce.b*)
|
||||
*(COMMON)
|
||||
. = ALIGN(32);
|
||||
PROVIDE (__bss_end__ = ABSOLUTE(.));
|
||||
} >main AT>high_iram :NONE
|
||||
__main_end__ = ABSOLUTE(.) ;
|
||||
|
||||
PROVIDE(__main_size__ = (__main_end__ - __main_start__));
|
||||
|
||||
/* ==================
|
||||
==== Metadata ====
|
||||
================== */
|
||||
|
||||
/* Discard sections that difficult post-processing */
|
||||
/DISCARD/ : { *(.group .comment .note) }
|
||||
|
||||
/* Stabs debugging sections. */
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
|
||||
/* DWARF debug sections.
|
||||
Symbols in the DWARF debugging sections are relative to the beginning
|
||||
of the section so we begin them at 0. */
|
||||
|
||||
/* DWARF 1 */
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
|
||||
/* GNU DWARF 1 extensions */
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
|
||||
/* DWARF 1.1 and DWARF 2 */
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
|
||||
/* DWARF 2 */
|
||||
.debug_info 0 : { *(.debug_info) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
}
|
||||
7
sept/sept-primary/linker.specs
Normal file
7
sept/sept-primary/linker.specs
Normal file
@@ -0,0 +1,7 @@
|
||||
%rename link old_link
|
||||
|
||||
*link:
|
||||
%(old_link) -T %:getenv(TOPDIR /linker.ld) --nmagic --gc-sections
|
||||
|
||||
*startfile:
|
||||
crti%O%s crtbegin%O%s
|
||||
81
sept/sept-primary/src/apb_misc.h
Normal file
81
sept/sept-primary/src/apb_misc.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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_APB_MISC_H
|
||||
#define FUSEE_APB_MISC_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define APB_MISC_BASE 0x70000000
|
||||
#define APB_PADCTL_BASE 0x70000810
|
||||
#define MAKE_APB_MISC_REG(n) MAKE_REG32(APB_MISC_BASE + n)
|
||||
#define MAKE_APB_PADCTL_REG(n) MAKE_REG32(APB_PADCTL_BASE + n)
|
||||
|
||||
#define APB_MISC_PP_PINMUX_GLOBAL_0 MAKE_APB_MISC_REG(0x40)
|
||||
#define APB_MISC_GP_WIFI_EN_CFGPADCTRL_0 MAKE_APB_MISC_REG(0xB64)
|
||||
#define APB_MISC_GP_WIFI_RST_CFGPADCTRL_0 MAKE_APB_MISC_REG(0xB68)
|
||||
|
||||
#define SDMMC1_PAD_CAL_DRVUP_SHIFT (20)
|
||||
#define SDMMC1_PAD_CAL_DRVDN_SHIFT (12)
|
||||
#define SDMMC1_PAD_CAL_DRVUP_MASK (0x7Fu << SDMMC1_PAD_CAL_DRVUP_SHIFT)
|
||||
#define SDMMC1_PAD_CAL_DRVDN_MASK (0x7Fu << SDMMC1_PAD_CAL_DRVDN_SHIFT)
|
||||
|
||||
#define CFG2TMC_EMMC4_PAD_DRVUP_COMP_SHIFT (8)
|
||||
#define CFG2TMC_EMMC4_PAD_DRVDN_COMP_SHIFT (2)
|
||||
#define CFG2TMC_EMMC4_PAD_DRVUP_COMP_MASK (0x3Fu << CFG2TMC_EMMC4_PAD_DRVUP_COMP_SHIFT)
|
||||
#define CFG2TMC_EMMC4_PAD_DRVDN_COMP_MASK (0x3Fu << CFG2TMC_EMMC4_PAD_DRVDN_COMP_SHIFT)
|
||||
|
||||
#define PADCTL_SDMMC1_DEEP_LOOPBACK (1 << 0)
|
||||
#define PADCTL_SDMMC3_DEEP_LOOPBACK (1 << 0)
|
||||
#define PADCTL_SDMMC2_ENABLE_DATA_IN (0xFF << 8)
|
||||
#define PADCTL_SDMMC2_ENABLE_CLK_IN (0x3 << 4)
|
||||
#define PADCTL_SDMMC2_DEEP_LOOPBACK (1 << 0)
|
||||
#define PADCTL_SDMMC4_ENABLE_DATA_IN (0xFF << 8)
|
||||
#define PADCTL_SDMMC4_ENABLE_CLK_IN (0x3 << 4)
|
||||
#define PADCTL_SDMMC4_DEEP_LOOPBACK (1 << 0)
|
||||
#define PADCTL_SDMMC1_CD_SOURCE (1 << 0)
|
||||
#define PADCTL_SDMMC1_WP_SOURCE (1 << 1)
|
||||
#define PADCTL_SDMMC3_CD_SOURCE (1 << 2)
|
||||
#define PADCTL_SDMMC3_WP_SOURCE (1 << 3)
|
||||
|
||||
typedef struct {
|
||||
uint32_t asdbgreg; /* 0x810 */
|
||||
uint32_t reserved0[0x31];
|
||||
uint32_t sdmmc1_clk_lpbk_control; /* 0x8D4 */
|
||||
uint32_t sdmmc3_clk_lpbk_control; /* 0x8D8 */
|
||||
uint32_t emmc2_pad_cfg_control; /* 0x8DC */
|
||||
uint32_t emmc4_pad_cfg_control; /* 0x8E0 */
|
||||
uint32_t _todo0[0x6E];
|
||||
uint32_t sdmmc1_pad_cfgpadctrl; /* 0xA98 */
|
||||
uint32_t emmc2_pad_cfgpadctrl; /* 0xA9C */
|
||||
uint32_t emmc2_pad_drv_type_cfgpadctrl; /* 0xAA0 */
|
||||
uint32_t emmc2_pad_pupd_cfgpadctrl; /* 0xAA4 */
|
||||
uint32_t _todo1[0x03];
|
||||
uint32_t sdmmc3_pad_cfgpadctrl; /* 0xAB0 */
|
||||
uint32_t emmc4_pad_cfgpadctrl; /* 0xAB4 */
|
||||
uint32_t emmc4_pad_drv_type_cfgpadctrl; /* 0xAB8 */
|
||||
uint32_t emmc4_pad_pupd_cfgpadctrl; /* 0xABC */
|
||||
uint32_t _todo2[0x2E];
|
||||
uint32_t vgpio_gpio_mux_sel; /* 0xB74 */
|
||||
uint32_t qspi_sck_lpbk_control; /* 0xB78 */
|
||||
} tegra_padctl_t;
|
||||
|
||||
static inline volatile tegra_padctl_t *padctl_get_regs(void)
|
||||
{
|
||||
return (volatile tegra_padctl_t *)APB_PADCTL_BASE;
|
||||
}
|
||||
|
||||
#endif
|
||||
82
sept/sept-primary/src/btn.c
Normal file
82
sept/sept-primary/src/btn.c
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 CTCaer
|
||||
* Copyright (c) 2018 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 <stdint.h>
|
||||
|
||||
#include "btn.h"
|
||||
#include "i2c.h"
|
||||
#include "gpio.h"
|
||||
#include "timers.h"
|
||||
|
||||
uint32_t btn_read()
|
||||
{
|
||||
uint32_t res = 0;
|
||||
|
||||
if (!gpio_read(GPIO_BUTTON_VOL_DOWN))
|
||||
res |= BTN_VOL_DOWN;
|
||||
|
||||
if (!gpio_read(GPIO_BUTTON_VOL_UP))
|
||||
res |= BTN_VOL_UP;
|
||||
|
||||
uint32_t val = 0;
|
||||
if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, 0x15, &val, 1))
|
||||
{
|
||||
if (val & 0x4)
|
||||
res |= BTN_POWER;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
uint32_t btn_wait()
|
||||
{
|
||||
uint32_t res = 0, btn = btn_read();
|
||||
int pwr = 0;
|
||||
|
||||
if (btn & BTN_POWER)
|
||||
{
|
||||
pwr = 1;
|
||||
btn &= ~BTN_POWER;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
res = btn_read();
|
||||
|
||||
if (!(res & BTN_POWER) && pwr)
|
||||
pwr = 0;
|
||||
else if (pwr)
|
||||
res &= ~BTN_POWER;
|
||||
} while (btn == res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
uint32_t btn_wait_timeout(uint32_t time_ms, uint32_t mask)
|
||||
{
|
||||
uint32_t timeout = get_time_us() + time_ms * 1000;
|
||||
uint32_t res = btn_read() & mask;
|
||||
|
||||
do
|
||||
{
|
||||
if (!(res & mask))
|
||||
res = btn_read() & mask;
|
||||
} while (get_time_us() < timeout);
|
||||
|
||||
return res;
|
||||
}
|
||||
30
sept/sept-primary/src/btn.h
Normal file
30
sept/sept-primary/src/btn.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 CTCaer
|
||||
* Copyright (c) 2018 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_BTN_H_
|
||||
#define FUSEE_BTN_H_
|
||||
|
||||
#define BTN_POWER 0x1
|
||||
#define BTN_VOL_DOWN 0x2
|
||||
#define BTN_VOL_UP 0x4
|
||||
|
||||
uint32_t btn_read();
|
||||
uint32_t btn_wait();
|
||||
uint32_t btn_wait_timeout(uint32_t time_ms, uint32_t mask);
|
||||
|
||||
#endif
|
||||
139
sept/sept-primary/src/car.c
Normal file
139
sept/sept-primary/src/car.c
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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 "car.h"
|
||||
#include "utils.h"
|
||||
#include "timers.h"
|
||||
|
||||
static inline uint32_t get_clk_source_reg(CarDevice dev) {
|
||||
switch (dev) {
|
||||
case CARDEVICE_UARTA: return 0x178;
|
||||
case CARDEVICE_UARTB: return 0x17C;
|
||||
case CARDEVICE_UARTC: return 0x1A0;
|
||||
case CARDEVICE_I2C1: return 0x124;
|
||||
case CARDEVICE_I2C5: return 0x128;
|
||||
case CARDEVICE_UNK: return 0;
|
||||
case CARDEVICE_SE: return 0x42C;
|
||||
case CARDEVICE_HOST1X: return 0x180;
|
||||
case CARDEVICE_TSEC: return 0x1F4;
|
||||
case CARDEVICE_SOR_SAFE: return 0;
|
||||
case CARDEVICE_SOR0: return 0;
|
||||
case CARDEVICE_SOR1: return 0x410;
|
||||
case CARDEVICE_KFUSE: return 0;
|
||||
case CARDEVICE_CL_DVFS: return 0;
|
||||
case CARDEVICE_CORESIGHT: return 0x1D4;
|
||||
case CARDEVICE_ACTMON: return 0x3E8;
|
||||
case CARDEVICE_BPMP: return 0;
|
||||
default: generic_panic();
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t get_clk_source_val(CarDevice dev) {
|
||||
switch (dev) {
|
||||
case CARDEVICE_UARTA: return 0;
|
||||
case CARDEVICE_UARTB: return 0;
|
||||
case CARDEVICE_UARTC: return 0;
|
||||
case CARDEVICE_I2C1: return 6;
|
||||
case CARDEVICE_I2C5: return 6;
|
||||
case CARDEVICE_UNK: return 0;
|
||||
case CARDEVICE_SE: return 0;
|
||||
case CARDEVICE_HOST1X: return 4;
|
||||
case CARDEVICE_TSEC: return 0;
|
||||
case CARDEVICE_SOR_SAFE: return 0;
|
||||
case CARDEVICE_SOR0: return 0;
|
||||
case CARDEVICE_SOR1: return 0;
|
||||
case CARDEVICE_KFUSE: return 0;
|
||||
case CARDEVICE_CL_DVFS: return 0;
|
||||
case CARDEVICE_CORESIGHT: return 0;
|
||||
case CARDEVICE_ACTMON: return 6;
|
||||
case CARDEVICE_BPMP: return 0;
|
||||
default: generic_panic();
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t get_clk_source_div(CarDevice dev) {
|
||||
switch (dev) {
|
||||
case CARDEVICE_UARTA: return 0;
|
||||
case CARDEVICE_UARTB: return 0;
|
||||
case CARDEVICE_UARTC: return 0;
|
||||
case CARDEVICE_I2C1: return 0;
|
||||
case CARDEVICE_I2C5: return 0;
|
||||
case CARDEVICE_UNK: return 0;
|
||||
case CARDEVICE_SE: return 0;
|
||||
case CARDEVICE_HOST1X: return 3;
|
||||
case CARDEVICE_TSEC: return 2;
|
||||
case CARDEVICE_SOR_SAFE: return 0;
|
||||
case CARDEVICE_SOR0: return 0;
|
||||
case CARDEVICE_SOR1: return 2;
|
||||
case CARDEVICE_KFUSE: return 0;
|
||||
case CARDEVICE_CL_DVFS: return 0;
|
||||
case CARDEVICE_CORESIGHT: return 4;
|
||||
case CARDEVICE_ACTMON: return 0;
|
||||
case CARDEVICE_BPMP: return 0;
|
||||
default: generic_panic();
|
||||
}
|
||||
}
|
||||
|
||||
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};
|
||||
|
||||
void clk_enable(CarDevice dev) {
|
||||
uint32_t clk_source_reg;
|
||||
if ((clk_source_reg = get_clk_source_reg(dev))) {
|
||||
MAKE_CAR_REG(clk_source_reg) = (get_clk_source_val(dev) << 29) | get_clk_source_div(dev);
|
||||
}
|
||||
MAKE_CAR_REG(g_clk_reg_offsets[dev >> 5]) |= BIT(dev & 0x1F);
|
||||
}
|
||||
|
||||
void clk_disable(CarDevice dev) {
|
||||
MAKE_CAR_REG(g_clk_reg_offsets[dev >> 5]) &= ~(BIT(dev & 0x1F));
|
||||
}
|
||||
|
||||
void rst_enable(CarDevice dev) {
|
||||
MAKE_CAR_REG(g_rst_reg_offsets[dev >> 5]) |= BIT(dev & 0x1F);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void clkrst_disable(CarDevice dev) {
|
||||
rst_enable(dev);
|
||||
clk_disable(dev);
|
||||
}
|
||||
|
||||
void clkrst_reboot(CarDevice dev) {
|
||||
clkrst_disable(dev);
|
||||
if (dev == CARDEVICE_KFUSE) {
|
||||
/* Workaround for KFUSE clock. */
|
||||
clk_enable(dev);
|
||||
udelay(100);
|
||||
rst_disable(dev);
|
||||
udelay(200);
|
||||
} else {
|
||||
clkrst_enable(dev);
|
||||
}
|
||||
}
|
||||
|
||||
void clkrst_enable_fuse_regs(bool enable) {
|
||||
volatile tegra_car_t *car = car_get_regs();
|
||||
car->misc_clk_enb = ((car->misc_clk_enb & 0xEFFFFFFF) | ((enable & 1) << 28));
|
||||
}
|
||||
505
sept/sept-primary/src/car.h
Normal file
505
sept/sept-primary/src/car.h
Normal file
@@ -0,0 +1,505 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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_CAR_H
|
||||
#define FUSEE_CAR_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define CAR_BASE 0x60006000
|
||||
#define MAKE_CAR_REG(n) MAKE_REG32(CAR_BASE + n)
|
||||
|
||||
#define CLK_L_SDMMC1 (1 << 14)
|
||||
#define CLK_L_SDMMC2 (1 << 9)
|
||||
#define CLK_U_SDMMC3 (1 << 5)
|
||||
#define CLK_L_SDMMC4 (1 << 15)
|
||||
|
||||
#define CLK_SOURCE_MASK (0b111 << 29)
|
||||
#define CLK_SOURCE_FIRST (0b000 << 29)
|
||||
#define CLK_DIVIDER_MASK (0xff << 0)
|
||||
#define CLK_DIVIDER_UNITY (0x00 << 0)
|
||||
|
||||
#define NUM_CAR_BANKS 7
|
||||
|
||||
/* Clock and reset devices. */
|
||||
typedef enum {
|
||||
CARDEVICE_UARTA = ((0 << 5) | 0x6),
|
||||
CARDEVICE_UARTB = ((0 << 5) | 0x7),
|
||||
CARDEVICE_UARTC = ((1 << 5) | 0x17),
|
||||
CARDEVICE_I2C1 = ((0 << 5) | 0xC),
|
||||
CARDEVICE_I2C5 = ((1 << 5) | 0xF),
|
||||
CARDEVICE_UNK = ((3 << 5) | 0x1E),
|
||||
CARDEVICE_SE = ((3 << 5) | 0x1F),
|
||||
CARDEVICE_HOST1X = ((0 << 5) | 0x1C),
|
||||
CARDEVICE_TSEC = ((2 << 5) | 0x13),
|
||||
CARDEVICE_SOR_SAFE = ((6 << 5) | 0x1E),
|
||||
CARDEVICE_SOR0 = ((5 << 5) | 0x16),
|
||||
CARDEVICE_SOR1 = ((5 << 5) | 0x17),
|
||||
CARDEVICE_KFUSE = ((1 << 5) | 0x8),
|
||||
CARDEVICE_CL_DVFS = ((4 << 5) | 0x1B),
|
||||
CARDEVICE_CORESIGHT = ((2 << 5) | 0x9),
|
||||
CARDEVICE_ACTMON = ((3 << 5) | 0x17),
|
||||
CARDEVICE_BPMP = ((0 << 5) | 0x1)
|
||||
} CarDevice;
|
||||
|
||||
/* Clock/Reset Controller (CLK_RST_CONTROLLER_) regs */
|
||||
typedef struct {
|
||||
uint32_t rst_src; /* _RST_SOURCE_0, 0x00 */
|
||||
|
||||
/* _RST_DEVICES_L/H/U_0 0x4-0xc */
|
||||
uint32_t rst_dev_l;
|
||||
uint32_t rst_dev_h;
|
||||
uint32_t rst_dev_u;
|
||||
|
||||
/* _CLK_OUT_ENB_L/H/U_0 0x10-0x18 */
|
||||
uint32_t clk_out_enb_l;
|
||||
uint32_t clk_out_enb_h;
|
||||
uint32_t clk_out_enb_u;
|
||||
|
||||
uint32_t _0x1C;
|
||||
uint32_t cclk_brst_pol; /* _CCLK_BURST_POLICY_0, 0x20 */
|
||||
uint32_t super_cclk_div; /* _SUPER_CCLK_DIVIDER_0, 0x24 */
|
||||
uint32_t sclk_brst_pol; /* _SCLK_BURST_POLICY_0, 0x28 */
|
||||
uint32_t super_sclk_div; /* _SUPER_SCLK_DIVIDER_0, 0x2c */
|
||||
uint32_t clk_sys_rate; /* _CLK_SYSTEM_RATE_0, 0x30 */
|
||||
uint32_t prog_dly_clk; /* _PROG_DLY_CLK_0, 0x34 */
|
||||
uint32_t aud_sync_clk_rate; /* _AUDIO_SYNC_CLK_RATE_0, 0x38 */
|
||||
uint32_t _0x3C;
|
||||
uint32_t cop_clk_skip_plcy; /* _COP_CLK_SKIP_POLICY_0, 0x40 */
|
||||
uint32_t clk_mask_arm; /* _CLK_MASK_ARM_0, 0x44 */
|
||||
uint32_t misc_clk_enb; /* _MISC_CLK_ENB_0, 0x48 */
|
||||
uint32_t clk_cpu_cmplx; /* _CLK_CPU_CMPLX_0, 0x4c */
|
||||
uint32_t osc_ctrl; /* _OSC_CTRL_0, 0x50 */
|
||||
uint32_t pll_lfsr; /* _PLL_LFSR_0, 0x54 */
|
||||
uint32_t osc_freq_det; /* _OSC_FREQ_DET_0, 0x58 */
|
||||
uint32_t osc_freq_det_stat; /* _OSC_FREQ_DET_STATUS_0, 0x5c */
|
||||
uint32_t _0x60[2];
|
||||
uint32_t plle_ss_cntl; /* _PLLE_SS_CNTL_0, 0x68 */
|
||||
uint32_t plle_misc1; /* _PLLE_MISC1_0, 0x6c */
|
||||
uint32_t _0x70[4];
|
||||
|
||||
/* PLLC 0x80-0x8c */
|
||||
uint32_t pllc_base;
|
||||
uint32_t pllc_out;
|
||||
uint32_t pllc_misc0;
|
||||
uint32_t pllc_misc1;
|
||||
|
||||
/* PLLM 0x90-0x9c */
|
||||
uint32_t pllm_base;
|
||||
uint32_t pllm_out;
|
||||
uint32_t pllm_misc1;
|
||||
uint32_t pllm_misc2;
|
||||
|
||||
/* PLLP 0xa0-0xac */
|
||||
uint32_t pllp_base;
|
||||
uint32_t pllp_outa;
|
||||
uint32_t pllp_outb;
|
||||
uint32_t pllp_misc;
|
||||
|
||||
/* PLLA 0xb0-0xbc */
|
||||
uint32_t plla_base;
|
||||
uint32_t plla_out;
|
||||
uint32_t plla_misc0;
|
||||
uint32_t plla_misc1;
|
||||
|
||||
/* PLLU 0xc0-0xcc */
|
||||
uint32_t pllu_base;
|
||||
uint32_t pllu_out;
|
||||
uint32_t pllu_misc1;
|
||||
uint32_t pllu_misc2;
|
||||
|
||||
/* PLLD 0xd0-0xdc */
|
||||
uint32_t plld_base;
|
||||
uint32_t plld_out;
|
||||
uint32_t plld_misc1;
|
||||
uint32_t plld_misc2;
|
||||
|
||||
/* PLLX 0xe0-0xe4 */
|
||||
uint32_t pllx_base;
|
||||
uint32_t pllx_misc;
|
||||
|
||||
/* PLLE 0xe8-0xf4 */
|
||||
uint32_t plle_base;
|
||||
uint32_t plle_misc;
|
||||
uint32_t plle_ss_cntl1;
|
||||
uint32_t plle_ss_cntl2;
|
||||
|
||||
uint32_t lvl2_clk_gate_ovra; /* _LVL2_CLK_GATE_OVRA_0, 0xf8 */
|
||||
uint32_t lvl2_clk_gate_ovrb; /* _LVL2_CLK_GATE_OVRB_0, 0xfc */
|
||||
|
||||
uint32_t clk_source_i2s2; /* _CLK_SOURCE_I2S2_0, 0x100 */
|
||||
uint32_t clk_source_i2s3; /* _CLK_SOURCE_I2S3_0, 0x104 */
|
||||
uint32_t clk_source_spdif_out; /* _CLK_SOURCE_SPDIF_OUT_0, 0x108 */
|
||||
uint32_t clk_source_spdif_in; /* _CLK_SOURCE_SPDIF_IN_0, 0x10c */
|
||||
uint32_t clk_source_pwm; /* _CLK_SOURCE_PWM_0, 0x110 */
|
||||
uint32_t _0x114;
|
||||
uint32_t clk_source_spi2; /* _CLK_SOURCE_SPI2_0, 0x118 */
|
||||
uint32_t clk_source_spi3; /* _CLK_SOURCE_SPI3_0, 0x11c */
|
||||
uint32_t _0x120;
|
||||
uint32_t clk_source_i2c1; /* _CLK_SOURCE_I2C1_0, 0x124 */
|
||||
uint32_t clk_source_i2c5; /* _CLK_SOURCE_I2C5_0, 0x128 */
|
||||
uint32_t _0x12c[2];
|
||||
uint32_t clk_source_spi1; /* _CLK_SOURCE_SPI1_0, 0x134 */
|
||||
uint32_t clk_source_disp1; /* _CLK_SOURCE_DISP1_0, 0x138 */
|
||||
uint32_t clk_source_disp2; /* _CLK_SOURCE_DISP2_0, 0x13c */
|
||||
uint32_t _0x140;
|
||||
uint32_t clk_source_isp; /* _CLK_SOURCE_ISP_0, 0x144 */
|
||||
uint32_t clk_source_vi; /* _CLK_SOURCE_VI_0, 0x148 */
|
||||
uint32_t _0x14c;
|
||||
uint32_t clk_source_sdmmc1; /* _CLK_SOURCE_SDMMC1_0, 0x150 */
|
||||
uint32_t clk_source_sdmmc2; /* _CLK_SOURCE_SDMMC2_0, 0x154 */
|
||||
uint32_t _0x158[3];
|
||||
uint32_t clk_source_sdmmc4; /* _CLK_SOURCE_SDMMC4_0, 0x164 */
|
||||
uint32_t _0x168[4];
|
||||
uint32_t clk_source_uarta; /* _CLK_SOURCE_UARTA_0, 0x178 */
|
||||
uint32_t clk_source_uartb; /* _CLK_SOURCE_UARTB_0, 0x17c */
|
||||
uint32_t clk_source_host1x; /* _CLK_SOURCE_HOST1X_0, 0x180 */
|
||||
uint32_t _0x184[5];
|
||||
uint32_t clk_source_i2c2; /* _CLK_SOURCE_I2C2_0, 0x198 */
|
||||
uint32_t clk_source_emc; /* _CLK_SOURCE_EMC_0, 0x19c */
|
||||
uint32_t clk_source_uartc; /* _CLK_SOURCE_UARTC_0, 0x1a0 */
|
||||
uint32_t _0x1a4;
|
||||
uint32_t clk_source_vi_sensor; /* _CLK_SOURCE_VI_SENSOR_0, 0x1a8 */
|
||||
uint32_t _0x1ac[2];
|
||||
uint32_t clk_source_spi4; /* _CLK_SOURCE_SPI4_0, 0x1b4 */
|
||||
uint32_t clk_source_i2c3; /* _CLK_SOURCE_I2C3_0, 0x1b8 */
|
||||
uint32_t clk_source_sdmmc3; /* _CLK_SOURCE_SDMMC3_0, 0x1bc */
|
||||
uint32_t clk_source_uartd; /* _CLK_SOURCE_UARTD_0, 0x1c0 */
|
||||
uint32_t _0x1c4[2];
|
||||
uint32_t clk_source_owr; /* _CLK_SOURCE_OWR_0, 0x1cc */
|
||||
uint32_t _0x1d0;
|
||||
uint32_t clk_source_csite; /* _CLK_SOURCE_CSITE_0, 0x1d4 */
|
||||
uint32_t clk_source_i2s1; /* _CLK_SOURCE_I2S1_0, 0x1d8 */
|
||||
uint32_t clk_source_dtv; /* _CLK_SOURCE_DTV_0, 0x1dc */
|
||||
uint32_t _0x1e0[5];
|
||||
uint32_t clk_source_tsec; /* _CLK_SOURCE_TSEC_0, 0x1f4 */
|
||||
uint32_t _0x1f8;
|
||||
|
||||
uint32_t clk_spare2; /* _CLK_SPARE2_0, 0x1fc */
|
||||
uint32_t _0x200[32];
|
||||
|
||||
uint32_t clk_out_enb_x; /* _CLK_OUT_ENB_X_0, 0x280 */
|
||||
uint32_t clk_enb_x_set; /* _CLK_ENB_X_SET_0, 0x284 */
|
||||
uint32_t clk_enb_x_clr; /* _CLK_ENB_X_CLR_0, 0x288 */
|
||||
|
||||
uint32_t rst_devices_x; /* _RST_DEVICES_X_0, 0x28c */
|
||||
uint32_t rst_dev_x_set; /* _RST_DEV_X_SET_0, 0x290 */
|
||||
uint32_t rst_dev_x_clr; /* _RST_DEV_X_CLR_0, 0x294 */
|
||||
|
||||
uint32_t clk_out_enb_y; /* _CLK_OUT_ENB_Y_0, 0x298 */
|
||||
uint32_t clk_enb_y_set; /* _CLK_ENB_Y_SET_0, 0x29c */
|
||||
uint32_t clk_enb_y_clr; /* _CLK_ENB_Y_CLR_0, 0x2a0 */
|
||||
|
||||
uint32_t rst_devices_y; /* _RST_DEVICES_Y_0, 0x2a4 */
|
||||
uint32_t rst_dev_y_set; /* _RST_DEV_Y_SET_0, 0x2a8 */
|
||||
uint32_t rst_dev_y_clr; /* _RST_DEV_Y_CLR_0, 0x2ac */
|
||||
|
||||
uint32_t _0x2b0[17];
|
||||
uint32_t dfll_base; /* _DFLL_BASE_0, 0x2f4 */
|
||||
uint32_t _0x2f8[2];
|
||||
|
||||
/* _RST_DEV_L/H/U_SET_0 0x300-0x314 */
|
||||
uint32_t rst_dev_l_set;
|
||||
uint32_t rst_dev_l_clr;
|
||||
uint32_t rst_dev_h_set;
|
||||
uint32_t rst_dev_h_clr;
|
||||
uint32_t rst_dev_u_set;
|
||||
uint32_t rst_dev_u_clr;
|
||||
|
||||
uint32_t _0x318[2];
|
||||
|
||||
/* _CLK_ENB_L/H/U_CLR_0 0x320-0x334 */
|
||||
uint32_t clk_enb_l_set;
|
||||
uint32_t clk_enb_l_clr;
|
||||
uint32_t clk_enb_h_set;
|
||||
uint32_t clk_enb_h_clr;
|
||||
uint32_t clk_enb_u_set;
|
||||
uint32_t clk_enb_u_clr;
|
||||
|
||||
uint32_t _0x338;
|
||||
uint32_t ccplex_pg_sm_ovrd; /* _CCPLEX_PG_SM_OVRD_0, 0x33c */
|
||||
uint32_t rst_cpu_cmplx_set; /* _RST_CPU_CMPLX_SET_0, 0x340 */
|
||||
uint32_t rst_cpu_cmplx_clr; /* _RST_CPU_CMPLX_CLR_0, 0x344 */
|
||||
|
||||
/* Additional (T30) registers */
|
||||
uint32_t clk_cpu_cmplx_set; /* _CLK_CPU_CMPLX_SET_0, 0x348 */
|
||||
uint32_t clk_cpu_cmplx_clr; /* _CLK_CPU_CMPLX_SET_0, 0x34c */
|
||||
|
||||
uint32_t _0x350[2];
|
||||
uint32_t rst_dev_v; /* _RST_DEVICES_V_0, 0x358 */
|
||||
uint32_t rst_dev_w; /* _RST_DEVICES_W_0, 0x35c */
|
||||
uint32_t clk_out_enb_v; /* _CLK_OUT_ENB_V_0, 0x360 */
|
||||
uint32_t clk_out_enb_w; /* _CLK_OUT_ENB_W_0, 0x364 */
|
||||
uint32_t cclkg_brst_pol; /* _CCLKG_BURST_POLICY_0, 0x368 */
|
||||
uint32_t super_cclkg_div; /* _SUPER_CCLKG_DIVIDER_0, 0x36c */
|
||||
uint32_t cclklp_brst_pol; /* _CCLKLP_BURST_POLICY_0, 0x370 */
|
||||
uint32_t super_cclkp_div; /* _SUPER_CCLKLP_DIVIDER_0, 0x374 */
|
||||
uint32_t clk_cpug_cmplx; /* _CLK_CPUG_CMPLX_0, 0x378 */
|
||||
uint32_t clk_cpulp_cmplx; /* _CLK_CPULP_CMPLX_0, 0x37c */
|
||||
uint32_t cpu_softrst_ctrl; /* _CPU_SOFTRST_CTRL_0, 0x380 */
|
||||
uint32_t cpu_softrst_ctrl1; /* _CPU_SOFTRST_CTRL1_0, 0x384 */
|
||||
uint32_t cpu_softrst_ctrl2; /* _CPU_SOFTRST_CTRL2_0, 0x388 */
|
||||
uint32_t _0x38c[5];
|
||||
uint32_t lvl2_clk_gate_ovrc; /* _LVL2_CLK_GATE_OVRC, 0x3a0 */
|
||||
uint32_t lvl2_clk_gate_ovrd; /* _LVL2_CLK_GATE_OVRD, 0x3a4 */
|
||||
uint32_t _0x3a8[2];
|
||||
|
||||
uint32_t _0x3b0;
|
||||
uint32_t clk_source_mselect; /* _CLK_SOURCE_MSELECT_0, 0x3b4 */
|
||||
uint32_t clk_source_tsensor; /* _CLK_SOURCE_TSENSOR_0, 0x3b8 */
|
||||
uint32_t clk_source_i2s4; /* _CLK_SOURCE_I2S4_0, 0x3bc */
|
||||
uint32_t clk_source_i2s5; /* _CLK_SOURCE_I2S5_0, 0x3c0 */
|
||||
uint32_t clk_source_i2c4; /* _CLK_SOURCE_I2C4_0, 0x3c4 */
|
||||
uint32_t _0x3c8[2];
|
||||
uint32_t clk_source_ahub; /* _CLK_SOURCE_AHUB_0, 0x3d0 */
|
||||
uint32_t _0x3d4[4];
|
||||
uint32_t clk_source_hda2codec_2x; /* _CLK_SOURCE_HDA2CODEC_2X_0, 0x3e4 */
|
||||
uint32_t clk_source_actmon; /* _CLK_SOURCE_ACTMON_0, 0x3e8 */
|
||||
uint32_t clk_source_extperiph1; /* _CLK_SOURCE_EXTPERIPH1_0, 0x3ec */
|
||||
uint32_t clk_source_extperiph2; /* _CLK_SOURCE_EXTPERIPH2_0, 0x3f0 */
|
||||
uint32_t clk_source_extperiph3; /* _CLK_SOURCE_EXTPERIPH3_0, 0x3f4 */
|
||||
uint32_t _0x3f8;
|
||||
uint32_t clk_source_i2c_slow; /* _CLK_SOURCE_I2C_SLOW_0, 0x3fc */
|
||||
uint32_t clk_source_sys; /* _CLK_SOURCE_SYS_0, 0x400 */
|
||||
uint32_t clk_source_ispb; /* _CLK_SOURCE_ISPB_0, 0x404 */
|
||||
uint32_t _0x408[2];
|
||||
uint32_t clk_source_sor1; /* _CLK_SOURCE_SOR1_0, 0x410 */
|
||||
uint32_t clk_source_sor0; /* _CLK_SOURCE_SOR0_0, 0x414 */
|
||||
uint32_t _0x418[2];
|
||||
uint32_t clk_source_sata_oob; /* _CLK_SOURCE_SATA_OOB_0, 0x420 */
|
||||
uint32_t clk_source_sata; /* _CLK_SOURCE_SATA_0, 0x424 */
|
||||
uint32_t clk_source_hda; /* _CLK_SOURCE_HDA_0, 0x428 */
|
||||
uint32_t _0x42c;
|
||||
|
||||
/* _RST_DEV_V/W_SET_0 0x430-0x43c */
|
||||
uint32_t rst_dev_v_set;
|
||||
uint32_t rst_dev_v_clr;
|
||||
uint32_t rst_dev_w_set;
|
||||
uint32_t rst_dev_w_clr;
|
||||
|
||||
/* _CLK_ENB_V/W_CLR_0 0x440-0x44c */
|
||||
uint32_t clk_enb_v_set;
|
||||
uint32_t clk_enb_v_clr;
|
||||
uint32_t clk_enb_w_set;
|
||||
uint32_t clk_enb_w_clr;
|
||||
|
||||
/* Additional (T114+) registers */
|
||||
uint32_t rst_cpug_cmplx_set; /* _RST_CPUG_CMPLX_SET_0, 0x450 */
|
||||
uint32_t rst_cpug_cmplx_clr; /* _RST_CPUG_CMPLX_CLR_0, 0x454 */
|
||||
uint32_t rst_cpulp_cmplx_set; /* _RST_CPULP_CMPLX_SET_0, 0x458 */
|
||||
uint32_t rst_cpulp_cmplx_clr; /* _RST_CPULP_CMPLX_CLR_0, 0x45c */
|
||||
uint32_t clk_cpug_cmplx_set; /* _CLK_CPUG_CMPLX_SET_0, 0x460 */
|
||||
uint32_t clk_cpug_cmplx_clr; /* _CLK_CPUG_CMPLX_CLR_0, 0x464 */
|
||||
uint32_t clk_cpulp_cmplx_set; /* _CLK_CPULP_CMPLX_SET_0, 0x468 */
|
||||
uint32_t clk_cpulp_cmplx_clr; /* _CLK_CPULP_CMPLX_CLR_0, 0x46c */
|
||||
uint32_t cpu_cmplx_status; /* _CPU_CMPLX_STATUS_0, 0x470 */
|
||||
uint32_t _0x474;
|
||||
uint32_t intstatus; /* _INTSTATUS_0, 0x478 */
|
||||
uint32_t intmask; /* _INTMASK_0, 0x47c */
|
||||
uint32_t utmip_pll_cfg0; /* _UTMIP_PLL_CFG0_0, 0x480 */
|
||||
uint32_t utmip_pll_cfg1; /* _UTMIP_PLL_CFG1_0, 0x484 */
|
||||
uint32_t utmip_pll_cfg2; /* _UTMIP_PLL_CFG2_0, 0x488 */
|
||||
|
||||
uint32_t plle_aux; /* _PLLE_AUX_0, 0x48c */
|
||||
uint32_t sata_pll_cfg0; /* _SATA_PLL_CFG0_0, 0x490 */
|
||||
uint32_t sata_pll_cfg1; /* _SATA_PLL_CFG1_0, 0x494 */
|
||||
uint32_t pcie_pll_cfg0; /* _PCIE_PLL_CFG0_0, 0x498 */
|
||||
|
||||
uint32_t prog_audio_dly_clk; /* _PROG_AUDIO_DLY_CLK_0, 0x49c */
|
||||
uint32_t audio_sync_clk_i2s0; /* _AUDIO_SYNC_CLK_I2S0_0, 0x4a0 */
|
||||
uint32_t audio_sync_clk_i2s1; /* _AUDIO_SYNC_CLK_I2S1_0, 0x4a4 */
|
||||
uint32_t audio_sync_clk_i2s2; /* _AUDIO_SYNC_CLK_I2S2_0, 0x4a8 */
|
||||
uint32_t audio_sync_clk_i2s3; /* _AUDIO_SYNC_CLK_I2S3_0, 0x4ac */
|
||||
uint32_t audio_sync_clk_i2s4; /* _AUDIO_SYNC_CLK_I2S4_0, 0x4b0 */
|
||||
uint32_t audio_sync_clk_spdif; /* _AUDIO_SYNC_CLK_SPDIF_0, 0x4b4 */
|
||||
|
||||
uint32_t plld2_base; /* _PLLD2_BASE_0, 0x4b8 */
|
||||
uint32_t plld2_misc; /* _PLLD2_MISC_0, 0x4bc */
|
||||
uint32_t utmip_pll_cfg3; /* _UTMIP_PLL_CFG3_0, 0x4c0 */
|
||||
uint32_t pllrefe_base; /* _PLLREFE_BASE_0, 0x4c4 */
|
||||
uint32_t pllrefe_misc; /* _PLLREFE_MISC_0, 0x4c8 */
|
||||
uint32_t pllrefe_out; /* _PLLREFE_OUT_0, 0x4cc */
|
||||
uint32_t cpu_finetrim_byp; /* _CPU_FINETRIM_BYP_0, 0x4d0 */
|
||||
uint32_t cpu_finetrim_select; /* _CPU_FINETRIM_SELECT_0, 0x4d4 */
|
||||
uint32_t cpu_finetrim_dr; /* _CPU_FINETRIM_DR_0, 0x4d8 */
|
||||
uint32_t cpu_finetrim_df; /* _CPU_FINETRIM_DF_0, 0x4dc */
|
||||
uint32_t cpu_finetrim_f; /* _CPU_FINETRIM_F_0, 0x4e0 */
|
||||
uint32_t cpu_finetrim_r; /* _CPU_FINETRIM_R_0, 0x4e4 */
|
||||
uint32_t pllc2_base; /* _PLLC2_BASE_0, 0x4e8 */
|
||||
uint32_t pllc2_misc0; /* _PLLC2_MISC_0_0, 0x4ec */
|
||||
uint32_t pllc2_misc1; /* _PLLC2_MISC_1_0, 0x4f0 */
|
||||
uint32_t pllc2_misc2; /* _PLLC2_MISC_2_0, 0x4f4 */
|
||||
uint32_t pllc2_misc3; /* _PLLC2_MISC_3_0, 0x4f8 */
|
||||
uint32_t pllc3_base; /* _PLLC3_BASE_0, 0x4fc */
|
||||
uint32_t pllc3_misc0; /* _PLLC3_MISC_0_0, 0x500 */
|
||||
uint32_t pllc3_misc1; /* _PLLC3_MISC_1_0, 0x504 */
|
||||
uint32_t pllc3_misc2; /* _PLLC3_MISC_2_0, 0x508 */
|
||||
uint32_t pllc3_misc3; /* _PLLC3_MISC_3_0, 0x50c */
|
||||
uint32_t pllx_misc1; /* _PLLX_MISC_1_0, 0x510 */
|
||||
uint32_t pllx_misc2; /* _PLLX_MISC_2_0, 0x514 */
|
||||
uint32_t pllx_misc3; /* _PLLX_MISC_3_0, 0x518 */
|
||||
uint32_t xusbio_pll_cfg0; /* _XUSBIO_PLL_CFG0_0, 0x51c */
|
||||
uint32_t xusbio_pll_cfg1; /* _XUSBIO_PLL_CFG0_1, 0x520 */
|
||||
uint32_t plle_aux1; /* _PLLE_AUX1_0, 0x524 */
|
||||
uint32_t pllp_reshift; /* _PLLP_RESHIFT_0, 0x528 */
|
||||
uint32_t utmipll_hw_pwrdn_cfg0; /* _UTMIPLL_HW_PWRDN_CFG0_0, 0x52c */
|
||||
uint32_t pllu_hw_pwrdn_cfg0; /* _PLLU_HW_PWRDN_CFG0_0, 0x530 */
|
||||
uint32_t xusb_pll_cfg0; /* _XUSB_PLL_CFG0_0, 0x534 */
|
||||
uint32_t _0x538;
|
||||
uint32_t clk_cpu_misc; /* _CLK_CPU_MISC_0, 0x53c */
|
||||
uint32_t clk_cpug_misc; /* _CLK_CPUG_MISC_0, 0x540 */
|
||||
uint32_t clk_cpulp_misc; /* _CLK_CPULP_MISC_0, 0x544 */
|
||||
uint32_t pllx_hw_ctrl_cfg; /* _PLLX_HW_CTRL_CFG_0, 0x548 */
|
||||
uint32_t pllx_sw_ramp_cfg; /* _PLLX_SW_RAMP_CFG_0, 0x54c */
|
||||
uint32_t pllx_hw_ctrl_status; /* _PLLX_HW_CTRL_STATUS_0, 0x550 */
|
||||
uint32_t lvl2_clk_gate_ovre; /* _LVL2_CLK_GATE_OVRE, 0x554 */
|
||||
uint32_t super_gr3d_clk_div; /* _SUPER_GR3D_CLK_DIVIDER_0, 0x558 */
|
||||
uint32_t spare_reg0; /* _SPARE_REG0_0, 0x55c */
|
||||
uint32_t audio_sync_clk_dmic1; /* _AUDIO_SYNC_CLK_DMIC1_0, 0x560 */
|
||||
uint32_t audio_sync_clk_dmic2; /* _AUDIO_SYNC_CLK_DMIC2_0, 0x564 */
|
||||
|
||||
uint32_t _0x568[2];
|
||||
uint32_t plld2_ss_cfg; /* _PLLD2_SS_CFG, 0x570 */
|
||||
uint32_t plld2_ss_ctrl1; /* _PLLD2_SS_CTRL1_0, 0x574 */
|
||||
uint32_t plld2_ss_ctrl2; /* _PLLD2_SS_CTRL2_0, 0x578 */
|
||||
uint32_t _0x57c[5];
|
||||
|
||||
uint32_t plldp_base; /* _PLLDP_BASE, 0x590*/
|
||||
uint32_t plldp_misc; /* _PLLDP_MISC, 0x594 */
|
||||
uint32_t plldp_ss_cfg; /* _PLLDP_SS_CFG, 0x598 */
|
||||
uint32_t plldp_ss_ctrl1; /* _PLLDP_SS_CTRL1_0, 0x59c */
|
||||
uint32_t plldp_ss_ctrl2; /* _PLLDP_SS_CTRL2_0, 0x5a0 */
|
||||
uint32_t pllc4_base; /* _PLLC4_BASE_0, 0x5a4 */
|
||||
uint32_t pllc4_misc; /* _PLLC4_MISC_0, 0x5a8 */
|
||||
uint32_t _0x5ac[6];
|
||||
uint32_t clk_spare0; /* _CLK_SPARE0_0, 0x5c4 */
|
||||
uint32_t clk_spare1; /* _CLK_SPARE1_0, 0x5c8 */
|
||||
uint32_t gpu_isob_ctrl; /* _GPU_ISOB_CTRL_0, 0x5cc */
|
||||
uint32_t pllc_misc2; /* _PLLC_MISC_2_0, 0x5d0 */
|
||||
uint32_t pllc_misc3; /* _PLLC_MISC_3_0, 0x5d4 */
|
||||
uint32_t plla_misc2; /* _PLLA_MISC2_0, 0x5d8 */
|
||||
uint32_t _0x5dc[2];
|
||||
uint32_t pllc4_out; /* _PLLC4_OUT_0, 0x5e4 */
|
||||
uint32_t pllmb_base; /* _PLLMB_BASE_0, 0x5e8 */
|
||||
uint32_t pllmb_misc1; /* _PLLMB_MISC1_0, 0x5ec */
|
||||
uint32_t pllx_misc4; /* _PLLX_MISC_4_0, 0x5f0 */
|
||||
uint32_t pllx_misc5; /* _PLLX_MISC_5_0, 0x5f4 */
|
||||
uint32_t _0x5f8[2];
|
||||
|
||||
uint32_t clk_source_xusb_core_host; /* _CLK_SOURCE_XUSB_CORE_HOST_0, 0x600 */
|
||||
uint32_t clk_source_xusb_falcon; /* _CLK_SOURCE_XUSB_FALCON_0, 0x604 */
|
||||
uint32_t clk_source_xusb_fs; /* _CLK_SOURCE_XUSB_FS_0, 0x608 */
|
||||
uint32_t clk_source_xusb_core_dev; /* _CLK_SOURCE_XUSB_CORE_DEV_0, 0x60c */
|
||||
uint32_t clk_source_xusb_ss; /* _CLK_SOURCE_XUSB_SS_0, 0x610 */
|
||||
uint32_t clk_source_cilab; /* _CLK_SOURCE_CILAB_0, 0x614 */
|
||||
uint32_t clk_source_cilcd; /* _CLK_SOURCE_CILCD_0, 0x618 */
|
||||
uint32_t clk_source_cilef; /* _CLK_SOURCE_CILEF_0, 0x61c */
|
||||
uint32_t clk_source_dsia_lp; /* _CLK_SOURCE_DSIA_LP_0, 0x620 */
|
||||
uint32_t clk_source_dsib_lp; /* _CLK_SOURCE_DSIB_LP_0, 0x624 */
|
||||
uint32_t clk_source_entropy; /* _CLK_SOURCE_ENTROPY_0, 0x628 */
|
||||
uint32_t clk_source_dvfs_ref; /* _CLK_SOURCE_DVFS_REF_0, 0x62c */
|
||||
uint32_t clk_source_dvfs_soc; /* _CLK_SOURCE_DVFS_SOC_0, 0x630 */
|
||||
uint32_t _0x634[3];
|
||||
uint32_t clk_source_emc_latency; /* _CLK_SOURCE_EMC_LATENCY_0, 0x640 */
|
||||
uint32_t clk_source_soc_therm; /* _CLK_SOURCE_SOC_THERM_0, 0x644 */
|
||||
uint32_t _0x648;
|
||||
uint32_t clk_source_dmic1; /* _CLK_SOURCE_DMIC1_0, 0x64c */
|
||||
uint32_t clk_source_dmic2; /* _CLK_SOURCE_DMIC2_0, 0x650 */
|
||||
uint32_t _0x654;
|
||||
uint32_t clk_source_vi_sensor2; /* _CLK_SOURCE_VI_SENSOR2_0, 0x658 */
|
||||
uint32_t clk_source_i2c6; /* _CLK_SOURCE_I2C6_0, 0x65c */
|
||||
uint32_t clk_source_mipibif; /* _CLK_SOURCE_MIPIBIF_0, 0x660 */
|
||||
uint32_t clk_source_emc_dll; /* _CLK_SOURCE_EMC_DLL_0, 0x664 */
|
||||
uint32_t _0x668;
|
||||
uint32_t clk_source_uart_fst_mipi_cal; /* _CLK_SOURCE_UART_FST_MIPI_CAL_0, 0x66c */
|
||||
uint32_t _0x670[2];
|
||||
uint32_t clk_source_vic; /* _CLK_SOURCE_VIC_0, 0x678 */
|
||||
|
||||
uint32_t pllp_outc; /* _PLLP_OUTC_0, 0x67c */
|
||||
uint32_t pllp_misc1; /* _PLLP_MISC1_0, 0x680 */
|
||||
uint32_t _0x684[2];
|
||||
uint32_t emc_div_clk_shaper_ctrl; /* _EMC_DIV_CLK_SHAPER_CTRL_0, 0x68c */
|
||||
uint32_t emc_pllc_shaper_ctrl; /* _EMC_PLLC_SHAPER_CTRL_0, 0x690 */
|
||||
|
||||
uint32_t clk_source_sdmmc_legacy_tm; /* _CLK_SOURCE_SDMMC_LEGACY_TM_0, 0x694 */
|
||||
uint32_t clk_source_nvdec; /* _CLK_SOURCE_NVDEC_0, 0x698 */
|
||||
uint32_t clk_source_nvjpg; /* _CLK_SOURCE_NVJPG_0, 0x69c */
|
||||
uint32_t clk_source_nvenc; /* _CLK_SOURCE_NVENC_0, 0x6a0 */
|
||||
|
||||
uint32_t plla1_base; /* _PLLA1_BASE_0, 0x6a4 */
|
||||
uint32_t plla1_misc0; /* _PLLA1_MISC_0_0, 0x6a8 */
|
||||
uint32_t plla1_misc1; /* _PLLA1_MISC_1_0, 0x6ac */
|
||||
uint32_t plla1_misc2; /* _PLLA1_MISC_2_0, 0x6b0 */
|
||||
uint32_t plla1_misc3; /* _PLLA1_MISC_3_0, 0x6b4 */
|
||||
uint32_t audio_sync_clk_dmic3; /* _AUDIO_SYNC_CLK_DMIC3_0, 0x6b8 */
|
||||
|
||||
uint32_t clk_source_dmic3; /* _CLK_SOURCE_DMIC3_0, 0x6bc */
|
||||
uint32_t clk_source_ape; /* _CLK_SOURCE_APE_0, 0x6c0 */
|
||||
uint32_t clk_source_qspi; /* _CLK_SOURCE_QSPI_0, 0x6c4 */
|
||||
uint32_t clk_source_vi_i2c; /* _CLK_SOURCE_VI_I2C_0, 0x6c8 */
|
||||
uint32_t clk_source_usb2_hsic_trk; /* _CLK_SOURCE_USB2_HSIC_TRK_0, 0x6cc */
|
||||
uint32_t clk_source_pex_sata_usb_rx_byp; /* _CLK_SOURCE_PEX_SATA_USB_RX_BYP_0, 0x6d0 */
|
||||
uint32_t clk_source_maud; /* _CLK_SOURCE_MAUD_0, 0x6d4 */
|
||||
uint32_t clk_source_tsecb; /* _CLK_SOURCE_TSECB_0, 0x6d8 */
|
||||
|
||||
uint32_t clk_cpug_misc1; /* _CLK_CPUG_MISC1_0, 0x6dc */
|
||||
uint32_t aclk_burst_policy; /* _ACLK_BURST_POLICY_0, 0x6e0 */
|
||||
uint32_t super_aclk_divider; /* _SUPER_ACLK_DIVIDER_0, 0x6e4 */
|
||||
|
||||
uint32_t nvenc_super_clk_divider; /* _NVENC_SUPER_CLK_DIVIDER_0, 0x6e8 */
|
||||
uint32_t vi_super_clk_divider; /* _VI_SUPER_CLK_DIVIDER_0, 0x6ec */
|
||||
uint32_t vic_super_clk_divider; /* _VIC_SUPER_CLK_DIVIDER_0, 0x6f0 */
|
||||
uint32_t nvdec_super_clk_divider; /* _NVDEC_SUPER_CLK_DIVIDER_0, 0x6f4 */
|
||||
uint32_t isp_super_clk_divider; /* _ISP_SUPER_CLK_DIVIDER_0, 0x6f8 */
|
||||
uint32_t ispb_super_clk_divider; /* _ISPB_SUPER_CLK_DIVIDER_0, 0x6fc */
|
||||
uint32_t nvjpg_super_clk_divider; /* _NVJPG_SUPER_CLK_DIVIDER_0, 0x700 */
|
||||
uint32_t se_super_clk_divider; /* _SE_SUPER_CLK_DIVIDER_0, 0x704 */
|
||||
uint32_t tsec_super_clk_divider; /* _TSEC_SUPER_CLK_DIVIDER_0, 0x708 */
|
||||
uint32_t tsecb_super_clk_divider; /* _TSECB_SUPER_CLK_DIVIDER_0, 0x70c */
|
||||
|
||||
uint32_t clk_source_uartape; /* _CLK_SOURCE_UARTAPE_0, 0x710 */
|
||||
uint32_t clk_cpug_misc2; /* _CLK_CPUG_MISC2_0, 0x714 */
|
||||
uint32_t clk_source_dbgapb; /* _CLK_SOURCE_DBGAPB_0, 0x718 */
|
||||
uint32_t clk_ccplex_cc4_ret_clk_enb; /* _CLK_CCPLEX_CC4_RET_CLK_ENB_0, 0x71c */
|
||||
uint32_t actmon_cpu_clk; /* _ACTMON_CPU_CLK_0, 0x720 */
|
||||
uint32_t clk_source_emc_safe; /* _CLK_SOURCE_EMC_SAFE_0, 0x724 */
|
||||
uint32_t sdmmc2_pllc4_out0_shaper_ctrl; /* _SDMMC2_PLLC4_OUT0_SHAPER_CTRL_0, 0x728 */
|
||||
uint32_t sdmmc2_pllc4_out1_shaper_ctrl; /* _SDMMC2_PLLC4_OUT1_SHAPER_CTRL_0, 0x72c */
|
||||
uint32_t sdmmc2_pllc4_out2_shaper_ctrl; /* _SDMMC2_PLLC4_OUT2_SHAPER_CTRL_0, 0x730 */
|
||||
uint32_t sdmmc2_div_clk_shaper_ctrl; /* _SDMMC2_DIV_CLK_SHAPER_CTRL_0, 0x734 */
|
||||
uint32_t sdmmc4_pllc4_out0_shaper_ctrl; /* _SDMMC4_PLLC4_OUT0_SHAPER_CTRL_0, 0x738 */
|
||||
uint32_t sdmmc4_pllc4_out1_shaper_ctrl; /* _SDMMC4_PLLC4_OUT1_SHAPER_CTRL_0, 0x73c */
|
||||
uint32_t sdmmc4_pllc4_out2_shaper_ctrl; /* _SDMMC4_PLLC4_OUT2_SHAPER_CTRL_0, 0x740 */
|
||||
uint32_t sdmmc4_div_clk_shaper_ctrl; /* _SDMMC4_DIV_CLK_SHAPER_CTRL_0, 0x744 */
|
||||
} tegra_car_t;
|
||||
|
||||
static inline volatile tegra_car_t *car_get_regs(void) {
|
||||
return (volatile tegra_car_t *)CAR_BASE;
|
||||
}
|
||||
|
||||
void clk_enable(CarDevice dev);
|
||||
void clk_disable(CarDevice dev);
|
||||
void rst_enable(CarDevice dev);
|
||||
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
|
||||
350
sept/sept-primary/src/di.h
Normal file
350
sept/sept-primary/src/di.h
Normal file
@@ -0,0 +1,350 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 CTCaer
|
||||
* Copyright (c) 2018 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_DI_H_
|
||||
#define FUSEE_DI_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define HOST1X_BASE 0x50000000
|
||||
#define DI_BASE 0x54200000
|
||||
#define DSI_BASE 0x54300000
|
||||
#define VIC_BASE 0x54340000
|
||||
#define MIPI_CAL_BASE 0x700E3000
|
||||
#define MAKE_HOST1X_REG(n) MAKE_REG32(HOST1X_BASE + n)
|
||||
#define MAKE_DI_REG(n) MAKE_REG32(DI_BASE + n * 4)
|
||||
#define MAKE_DSI_REG(n) MAKE_REG32(DSI_BASE + n * 4)
|
||||
#define MAKE_MIPI_CAL_REG(n) MAKE_REG32(MIPI_CAL_BASE + n)
|
||||
#define MAKE_VIC_REG(n) MAKE_REG32(VIC_BASE + n)
|
||||
|
||||
/* Display registers. */
|
||||
#define DC_CMD_GENERAL_INCR_SYNCPT 0x00
|
||||
|
||||
#define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL 0x01
|
||||
#define SYNCPT_CNTRL_NO_STALL (1 << 8)
|
||||
#define SYNCPT_CNTRL_SOFT_RESET (1 << 0)
|
||||
|
||||
#define DC_CMD_CONT_SYNCPT_VSYNC 0x28
|
||||
#define SYNCPT_VSYNC_ENABLE (1 << 8)
|
||||
|
||||
#define DC_CMD_DISPLAY_COMMAND_OPTION0 0x031
|
||||
|
||||
#define DC_CMD_DISPLAY_COMMAND 0x32
|
||||
#define DISP_CTRL_MODE_STOP (0 << 5)
|
||||
#define DISP_CTRL_MODE_C_DISPLAY (1 << 5)
|
||||
#define DISP_CTRL_MODE_NC_DISPLAY (2 << 5)
|
||||
#define DISP_CTRL_MODE_MASK (3 << 5)
|
||||
|
||||
#define DC_CMD_DISPLAY_POWER_CONTROL 0x36
|
||||
#define PW0_ENABLE (1 << 0)
|
||||
#define PW1_ENABLE (1 << 2)
|
||||
#define PW2_ENABLE (1 << 4)
|
||||
#define PW3_ENABLE (1 << 6)
|
||||
#define PW4_ENABLE (1 << 8)
|
||||
#define PM0_ENABLE (1 << 16)
|
||||
#define PM1_ENABLE (1 << 18)
|
||||
|
||||
#define DC_CMD_INT_MASK 0x38
|
||||
#define DC_CMD_INT_ENABLE 0x39
|
||||
|
||||
#define DC_CMD_STATE_ACCESS 0x40
|
||||
#define READ_MUX (1 << 0)
|
||||
#define WRITE_MUX (1 << 2)
|
||||
|
||||
#define DC_CMD_STATE_CONTROL 0x41
|
||||
#define GENERAL_ACT_REQ (1 << 0)
|
||||
#define WIN_A_ACT_REQ (1 << 1)
|
||||
#define WIN_B_ACT_REQ (1 << 2)
|
||||
#define WIN_C_ACT_REQ (1 << 3)
|
||||
#define CURSOR_ACT_REQ (1 << 7)
|
||||
#define GENERAL_UPDATE (1 << 8)
|
||||
#define WIN_A_UPDATE (1 << 9)
|
||||
#define WIN_B_UPDATE (1 << 10)
|
||||
#define WIN_C_UPDATE (1 << 11)
|
||||
#define CURSOR_UPDATE (1 << 15)
|
||||
#define NC_HOST_TRIG (1 << 24)
|
||||
|
||||
#define DC_CMD_DISPLAY_WINDOW_HEADER 0x42
|
||||
#define WINDOW_A_SELECT (1 << 4)
|
||||
#define WINDOW_B_SELECT (1 << 5)
|
||||
#define WINDOW_C_SELECT (1 << 6)
|
||||
|
||||
#define DC_CMD_REG_ACT_CONTROL 0x043
|
||||
|
||||
#define DC_COM_CRC_CONTROL 0x300
|
||||
#define DC_COM_PIN_OUTPUT_ENABLE(x) (0x302 + (x))
|
||||
#define DC_COM_PIN_OUTPUT_POLARITY(x) (0x306 + (x))
|
||||
|
||||
#define DC_COM_DSC_TOP_CTL 0x33E
|
||||
|
||||
#define DC_DISP_DISP_WIN_OPTIONS 0x402
|
||||
#define HDMI_ENABLE (1 << 30)
|
||||
#define DSI_ENABLE (1 << 29)
|
||||
#define SOR1_TIMING_CYA (1 << 27)
|
||||
#define SOR1_ENABLE (1 << 26)
|
||||
#define SOR_ENABLE (1 << 25)
|
||||
#define CURSOR_ENABLE (1 << 16)
|
||||
|
||||
#define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403
|
||||
#define DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER 0x404
|
||||
#define DC_DISP_DISP_TIMING_OPTIONS 0x405
|
||||
#define DC_DISP_REF_TO_SYNC 0x406
|
||||
#define DC_DISP_SYNC_WIDTH 0x407
|
||||
#define DC_DISP_BACK_PORCH 0x408
|
||||
#define DC_DISP_ACTIVE 0x409
|
||||
#define DC_DISP_FRONT_PORCH 0x40A
|
||||
|
||||
#define DC_DISP_DISP_CLOCK_CONTROL 0x42E
|
||||
#define PIXEL_CLK_DIVIDER_PCD1 (0 << 8)
|
||||
#define PIXEL_CLK_DIVIDER_PCD1H (1 << 8)
|
||||
#define PIXEL_CLK_DIVIDER_PCD2 (2 << 8)
|
||||
#define PIXEL_CLK_DIVIDER_PCD3 (3 << 8)
|
||||
#define PIXEL_CLK_DIVIDER_PCD4 (4 << 8)
|
||||
#define PIXEL_CLK_DIVIDER_PCD6 (5 << 8)
|
||||
#define PIXEL_CLK_DIVIDER_PCD8 (6 << 8)
|
||||
#define PIXEL_CLK_DIVIDER_PCD9 (7 << 8)
|
||||
#define PIXEL_CLK_DIVIDER_PCD12 (8 << 8)
|
||||
#define PIXEL_CLK_DIVIDER_PCD16 (9 << 8)
|
||||
#define PIXEL_CLK_DIVIDER_PCD18 (10 << 8)
|
||||
#define PIXEL_CLK_DIVIDER_PCD24 (11 << 8)
|
||||
#define PIXEL_CLK_DIVIDER_PCD13 (12 << 8)
|
||||
#define SHIFT_CLK_DIVIDER(x) ((x) & 0xff)
|
||||
|
||||
#define DC_DISP_DISP_INTERFACE_CONTROL 0x42F
|
||||
#define DISP_DATA_FORMAT_DF1P1C (0 << 0)
|
||||
#define DISP_DATA_FORMAT_DF1P2C24B (1 << 0)
|
||||
#define DISP_DATA_FORMAT_DF1P2C18B (2 << 0)
|
||||
#define DISP_DATA_FORMAT_DF1P2C16B (3 << 0)
|
||||
#define DISP_DATA_FORMAT_DF2S (4 << 0)
|
||||
#define DISP_DATA_FORMAT_DF3S (5 << 0)
|
||||
#define DISP_DATA_FORMAT_DFSPI (6 << 0)
|
||||
#define DISP_DATA_FORMAT_DF1P3C24B (7 << 0)
|
||||
#define DISP_DATA_FORMAT_DF1P3C18B (8 << 0)
|
||||
#define DISP_ALIGNMENT_MSB (0 << 8)
|
||||
#define DISP_ALIGNMENT_LSB (1 << 8)
|
||||
#define DISP_ORDER_RED_BLUE (0 << 9)
|
||||
#define DISP_ORDER_BLUE_RED (1 << 9)
|
||||
|
||||
#define DC_DISP_DISP_COLOR_CONTROL 0x430
|
||||
#define DITHER_CONTROL_MASK (3 << 8)
|
||||
#define DITHER_CONTROL_DISABLE (0 << 8)
|
||||
#define DITHER_CONTROL_ORDERED (2 << 8)
|
||||
#define DITHER_CONTROL_ERRDIFF (3 << 8)
|
||||
#define BASE_COLOR_SIZE_MASK (0xf << 0)
|
||||
#define BASE_COLOR_SIZE_666 (0 << 0)
|
||||
#define BASE_COLOR_SIZE_111 (1 << 0)
|
||||
#define BASE_COLOR_SIZE_222 (2 << 0)
|
||||
#define BASE_COLOR_SIZE_333 (3 << 0)
|
||||
#define BASE_COLOR_SIZE_444 (4 << 0)
|
||||
#define BASE_COLOR_SIZE_555 (5 << 0)
|
||||
#define BASE_COLOR_SIZE_565 (6 << 0)
|
||||
#define BASE_COLOR_SIZE_332 (7 << 0)
|
||||
#define BASE_COLOR_SIZE_888 (8 << 0)
|
||||
|
||||
#define DC_DISP_SHIFT_CLOCK_OPTIONS 0x431
|
||||
#define SC1_H_QUALIFIER_NONE (1 << 16)
|
||||
#define SC0_H_QUALIFIER_NONE (1 << 0)
|
||||
|
||||
#define DC_DISP_DATA_ENABLE_OPTIONS 0x432
|
||||
#define DE_SELECT_ACTIVE_BLANK (0 << 0)
|
||||
#define DE_SELECT_ACTIVE (1 << 0)
|
||||
#define DE_SELECT_ACTIVE_IS (2 << 0)
|
||||
#define DE_CONTROL_ONECLK (0 << 2)
|
||||
#define DE_CONTROL_NORMAL (1 << 2)
|
||||
#define DE_CONTROL_EARLY_EXT (2 << 2)
|
||||
#define DE_CONTROL_EARLY (3 << 2)
|
||||
#define DE_CONTROL_ACTIVE_BLANK (4 << 2)
|
||||
|
||||
#define DC_DISP_DC_MCCIF_FIFOCTRL 0x480
|
||||
#define DC_DISP_BLEND_BACKGROUND_COLOR 0x4E4
|
||||
|
||||
#define DC_WIN_CSC_YOF 0x611
|
||||
#define DC_WIN_CSC_KYRGB 0x612
|
||||
#define DC_WIN_CSC_KUR 0x613
|
||||
#define DC_WIN_CSC_KVR 0x614
|
||||
#define DC_WIN_CSC_KUG 0x615
|
||||
#define DC_WIN_CSC_KVG 0x616
|
||||
#define DC_WIN_CSC_KUB 0x617
|
||||
#define DC_WIN_CSC_KVB 0x618
|
||||
#define DC_WIN_AD_WIN_OPTIONS 0xB80
|
||||
#define DC_WIN_BD_WIN_OPTIONS 0xD80
|
||||
#define DC_WIN_CD_WIN_OPTIONS 0xF80
|
||||
|
||||
/* The following registers are A/B/C shadows of the 0xB80/0xD80/0xF80 registers (see DISPLAY_WINDOW_HEADER). */
|
||||
#define DC_WIN_WIN_OPTIONS 0x700
|
||||
#define H_DIRECTION (1 << 0)
|
||||
#define V_DIRECTION (1 << 2)
|
||||
#define COLOR_EXPAND (1 << 6)
|
||||
#define CSC_ENABLE (1 << 18)
|
||||
#define WIN_ENABLE (1 << 30)
|
||||
|
||||
#define DC_WIN_COLOR_DEPTH 0x703
|
||||
#define WIN_COLOR_DEPTH_P1 0x0
|
||||
#define WIN_COLOR_DEPTH_P2 0x1
|
||||
#define WIN_COLOR_DEPTH_P4 0x2
|
||||
#define WIN_COLOR_DEPTH_P8 0x3
|
||||
#define WIN_COLOR_DEPTH_B4G4R4A4 0x4
|
||||
#define WIN_COLOR_DEPTH_B5G5R5A 0x5
|
||||
#define WIN_COLOR_DEPTH_B5G6R5 0x6
|
||||
#define WIN_COLOR_DEPTH_AB5G5R5 0x7
|
||||
#define WIN_COLOR_DEPTH_B8G8R8A8 0xC
|
||||
#define WIN_COLOR_DEPTH_R8G8B8A8 0xD
|
||||
#define WIN_COLOR_DEPTH_B6x2G6x2R6x2A8 0xE
|
||||
#define WIN_COLOR_DEPTH_R6x2G6x2B6x2A8 0xF
|
||||
#define WIN_COLOR_DEPTH_YCbCr422 0x10
|
||||
#define WIN_COLOR_DEPTH_YUV422 0x11
|
||||
#define WIN_COLOR_DEPTH_YCbCr420P 0x12
|
||||
#define WIN_COLOR_DEPTH_YUV420P 0x13
|
||||
#define WIN_COLOR_DEPTH_YCbCr422P 0x14
|
||||
#define WIN_COLOR_DEPTH_YUV422P 0x15
|
||||
#define WIN_COLOR_DEPTH_YCbCr422R 0x16
|
||||
#define WIN_COLOR_DEPTH_YUV422R 0x17
|
||||
#define WIN_COLOR_DEPTH_YCbCr422RA 0x18
|
||||
#define WIN_COLOR_DEPTH_YUV422RA 0x19
|
||||
|
||||
#define DC_WIN_BUFFER_CONTROL 0x702
|
||||
#define DC_WIN_POSITION 0x704
|
||||
|
||||
#define DC_WIN_SIZE 0x705
|
||||
#define H_SIZE(x) (((x) & 0x1fff) << 0)
|
||||
#define V_SIZE(x) (((x) & 0x1fff) << 16)
|
||||
|
||||
#define DC_WIN_PRESCALED_SIZE 0x706
|
||||
#define H_PRESCALED_SIZE(x) (((x) & 0x7fff) << 0)
|
||||
#define V_PRESCALED_SIZE(x) (((x) & 0x1fff) << 16)
|
||||
|
||||
#define DC_WIN_H_INITIAL_DDA 0x707
|
||||
#define DC_WIN_V_INITIAL_DDA 0x708
|
||||
|
||||
#define DC_WIN_DDA_INC 0x709
|
||||
#define H_DDA_INC(x) (((x) & 0xffff) << 0)
|
||||
#define V_DDA_INC(x) (((x) & 0xffff) << 16)
|
||||
|
||||
#define DC_WIN_LINE_STRIDE 0x70A
|
||||
#define DC_WIN_DV_CONTROL 0x70E
|
||||
|
||||
/* The following registers are A/B/C shadows of the 0xBC0/0xDC0/0xFC0 registers (see DISPLAY_WINDOW_HEADER). */
|
||||
#define DC_WINBUF_START_ADDR 0x800
|
||||
#define DC_WINBUF_ADDR_H_OFFSET 0x806
|
||||
#define DC_WINBUF_ADDR_V_OFFSET 0x808
|
||||
#define DC_WINBUF_SURFACE_KIND 0x80B
|
||||
|
||||
/* Display serial interface registers. */
|
||||
#define DSI_RD_DATA 0x9
|
||||
#define DSI_WR_DATA 0xA
|
||||
|
||||
#define DSI_POWER_CONTROL 0xB
|
||||
#define DSI_POWER_CONTROL_ENABLE 1
|
||||
|
||||
#define DSI_INT_ENABLE 0xC
|
||||
#define DSI_INT_STATUS 0xD
|
||||
#define DSI_INT_MASK 0xE
|
||||
|
||||
#define DSI_HOST_CONTROL 0xF
|
||||
#define DSI_HOST_CONTROL_FIFO_RESET (1 << 21)
|
||||
#define DSI_HOST_CONTROL_CRC_RESET (1 << 20)
|
||||
#define DSI_HOST_CONTROL_TX_TRIG_SOL (0 << 12)
|
||||
#define DSI_HOST_CONTROL_TX_TRIG_FIFO (1 << 12)
|
||||
#define DSI_HOST_CONTROL_TX_TRIG_HOST (2 << 12)
|
||||
#define DSI_HOST_CONTROL_RAW (1 << 6)
|
||||
#define DSI_HOST_CONTROL_HS (1 << 5)
|
||||
#define DSI_HOST_CONTROL_FIFO_SEL (1 << 4)
|
||||
#define DSI_HOST_CONTROL_IMM_BTA (1 << 3)
|
||||
#define DSI_HOST_CONTROL_PKT_BTA (1 << 2)
|
||||
#define DSI_HOST_CONTROL_CS (1 << 1)
|
||||
#define DSI_HOST_CONTROL_ECC (1 << 0)
|
||||
|
||||
#define DSI_CONTROL 0x10
|
||||
#define DSI_CONTROL_HS_CLK_CTRL (1 << 20)
|
||||
#define DSI_CONTROL_CHANNEL(c) (((c) & 0x3) << 16)
|
||||
#define DSI_CONTROL_FORMAT(f) (((f) & 0x3) << 12)
|
||||
#define DSI_CONTROL_TX_TRIG(x) (((x) & 0x3) << 8)
|
||||
#define DSI_CONTROL_LANES(n) (((n) & 0x3) << 4)
|
||||
#define DSI_CONTROL_DCS_ENABLE (1 << 3)
|
||||
#define DSI_CONTROL_SOURCE(s) (((s) & 0x1) << 2)
|
||||
#define DSI_CONTROL_VIDEO_ENABLE (1 << 1)
|
||||
#define DSI_CONTROL_HOST_ENABLE (1 << 0)
|
||||
|
||||
#define DSI_SOL_DELAY 0x11
|
||||
#define DSI_MAX_THRESHOLD 0x12
|
||||
|
||||
#define DSI_TRIGGER 0x13
|
||||
#define DSI_TRIGGER_HOST (1 << 1)
|
||||
#define DSI_TRIGGER_VIDEO (1 << 0)
|
||||
|
||||
#define DSI_TX_CRC 0x14
|
||||
#define DSI_STATUS 0x15
|
||||
#define DSI_INIT_SEQ_CONTROL 0x1A
|
||||
#define DSI_INIT_SEQ_DATA_0 0x1B
|
||||
#define DSI_INIT_SEQ_DATA_1 0x1C
|
||||
#define DSI_INIT_SEQ_DATA_2 0x1D
|
||||
#define DSI_INIT_SEQ_DATA_3 0x1E
|
||||
#define DSI_PKT_SEQ_0_LO 0x23
|
||||
#define DSI_PKT_SEQ_0_HI 0x24
|
||||
#define DSI_PKT_SEQ_1_LO 0x25
|
||||
#define DSI_PKT_SEQ_1_HI 0x26
|
||||
#define DSI_PKT_SEQ_2_LO 0x27
|
||||
#define DSI_PKT_SEQ_2_HI 0x28
|
||||
#define DSI_PKT_SEQ_3_LO 0x29
|
||||
#define DSI_PKT_SEQ_3_HI 0x2A
|
||||
#define DSI_PKT_SEQ_4_LO 0x2B
|
||||
#define DSI_PKT_SEQ_4_HI 0x2C
|
||||
#define DSI_PKT_SEQ_5_LO 0x2D
|
||||
#define DSI_PKT_SEQ_5_HI 0x2E
|
||||
#define DSI_DCS_CMDS 0x33
|
||||
#define DSI_PKT_LEN_0_1 0x34
|
||||
#define DSI_PKT_LEN_2_3 0x35
|
||||
#define DSI_PKT_LEN_4_5 0x36
|
||||
#define DSI_PKT_LEN_6_7 0x37
|
||||
#define DSI_PHY_TIMING_0 0x3C
|
||||
#define DSI_PHY_TIMING_1 0x3D
|
||||
#define DSI_PHY_TIMING_2 0x3E
|
||||
#define DSI_BTA_TIMING 0x3F
|
||||
|
||||
#define DSI_TIMEOUT_0 0x44
|
||||
#define DSI_TIMEOUT_LRX(x) (((x) & 0xffff) << 16)
|
||||
#define DSI_TIMEOUT_HTX(x) (((x) & 0xffff) << 0)
|
||||
|
||||
#define DSI_TIMEOUT_1 0x45
|
||||
#define DSI_TIMEOUT_PR(x) (((x) & 0xffff) << 16)
|
||||
#define DSI_TIMEOUT_TA(x) (((x) & 0xffff) << 0)
|
||||
|
||||
#define DSI_TO_TALLY 0x46
|
||||
|
||||
#define DSI_PAD_CONTROL_0 0x4B
|
||||
#define DSI_PAD_CONTROL_VS1_PULLDN_CLK (1 << 24)
|
||||
#define DSI_PAD_CONTROL_VS1_PULLDN(x) (((x) & 0xf) << 16)
|
||||
#define DSI_PAD_CONTROL_VS1_PDIO_CLK (1 << 8)
|
||||
#define DSI_PAD_CONTROL_VS1_PDIO(x) (((x) & 0xf) << 0)
|
||||
|
||||
#define DSI_PAD_CONTROL_CD 0x4c
|
||||
#define DSI_VIDEO_MODE_CONTROL 0x4E
|
||||
|
||||
#define DSI_PAD_CONTROL_1 0x4F
|
||||
#define DSI_PAD_CONTROL_2 0x50
|
||||
|
||||
#define DSI_PAD_CONTROL_3 0x51
|
||||
#define DSI_PAD_PREEMP_PD_CLK(x) (((x) & 0x3) << 12)
|
||||
#define DSI_PAD_PREEMP_PU_CLK(x) (((x) & 0x3) << 8)
|
||||
#define DSI_PAD_PREEMP_PD(x) (((x) & 0x3) << 4)
|
||||
#define DSI_PAD_PREEMP_PU(x) (((x) & 0x3) << 0)
|
||||
|
||||
#define DSI_PAD_CONTROL_4 0x52
|
||||
|
||||
#endif
|
||||
256
sept/sept-primary/src/fuse.c
Normal file
256
sept/sept-primary/src/fuse.c
Normal file
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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 <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "car.h"
|
||||
#include "fuse.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();
|
||||
}
|
||||
|
||||
/* Make all fuse registers visible */
|
||||
void fuse_make_regs_visible(void) {
|
||||
clkrst_enable_fuse_regs(true);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read a fuse from the hardware array */
|
||||
uint32_t fuse_hw_read(uint32_t addr) {
|
||||
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||
fuse_wait_idle();
|
||||
|
||||
/* Program the target address */
|
||||
fuse->FUSE_REG_ADDR = addr;
|
||||
|
||||
/* Enable read operation in control register */
|
||||
uint32_t ctrl_val = fuse->FUSE_CTRL;
|
||||
ctrl_val &= ~0x3;
|
||||
ctrl_val |= 0x1; /* Set FUSE_READ command */
|
||||
fuse->FUSE_CTRL = ctrl_val;
|
||||
|
||||
fuse_wait_idle();
|
||||
|
||||
return fuse->FUSE_REG_READ;
|
||||
}
|
||||
|
||||
/* 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();
|
||||
fuse_wait_idle();
|
||||
|
||||
/* Program the target address and value */
|
||||
fuse->FUSE_REG_ADDR = addr;
|
||||
fuse->FUSE_REG_WRITE = value;
|
||||
|
||||
/* Enable write operation in control register */
|
||||
uint32_t ctrl_val = fuse->FUSE_CTRL;
|
||||
ctrl_val &= ~0x3;
|
||||
ctrl_val |= 0x2; /* Set FUSE_WRITE command */
|
||||
fuse->FUSE_CTRL = ctrl_val;
|
||||
|
||||
fuse_wait_idle();
|
||||
}
|
||||
|
||||
/* Sense the fuse hardware array into the shadow cache */
|
||||
void fuse_hw_sense(void) {
|
||||
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||
fuse_wait_idle();
|
||||
|
||||
/* Enable sense operation in control register */
|
||||
uint32_t ctrl_val = fuse->FUSE_CTRL;
|
||||
ctrl_val &= ~0x3;
|
||||
ctrl_val |= 0x3; /* Set FUSE_SENSE command */
|
||||
fuse->FUSE_CTRL = ctrl_val;
|
||||
|
||||
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 */
|
||||
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 */
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return fuse_chip->FUSE_SPARE_BIT[idx];
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return fuse_chip->FUSE_RESERVED_ODM[idx];
|
||||
}
|
||||
|
||||
/* 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 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);
|
||||
}
|
||||
derived_lot_code &= 0x03FFFFFF;
|
||||
|
||||
device_id |= y_coord << 0;
|
||||
device_id |= x_coord << 9;
|
||||
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(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 {*/
|
||||
if (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;
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
/* 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);
|
||||
if (retail_type == 4) { /* Standard retail unit, IS_RETAIL | 0. */
|
||||
return 1;
|
||||
} else if (retail_type == 3) { /* Standard dev unit, 0 | DEV_UNIT. */
|
||||
return 0;
|
||||
}
|
||||
return 2; /* IS_RETAIL | DEV_UNIT */
|
||||
}
|
||||
|
||||
/* Derive the 16-byte Hardware Info using values in the shadow cache, and copy to output buffer. */
|
||||
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;
|
||||
|
||||
/* 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));
|
||||
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);
|
||||
|
||||
memcpy(dst, hw_info, 0x10);
|
||||
}
|
||||
213
sept/sept-primary/src/fuse.h
Normal file
213
sept/sept-primary/src/fuse.h
Normal file
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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_FUSE_H
|
||||
#define FUSEE_FUSE_H
|
||||
|
||||
#define FUSE_BASE 0x7000F800
|
||||
#define FUSE_CHIP_BASE (FUSE_BASE + 0x100)
|
||||
#define MAKE_FUSE_REG(n) MAKE_REG32(FUSE_BASE + n)
|
||||
#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_FUSEBYPASS;
|
||||
uint32_t FUSE_PRIVATEKEYDISABLE;
|
||||
uint32_t FUSE_DIS_PGM;
|
||||
uint32_t FUSE_WRITE_ACCESS;
|
||||
uint32_t FUSE_PWR_GOOD_SW;
|
||||
uint32_t _0x38[0x32];
|
||||
} tegra_fuse_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t FUSE_PRODUCTION_MODE;
|
||||
uint32_t _0x4;
|
||||
uint32_t _0x8;
|
||||
uint32_t _0xC;
|
||||
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_FA;
|
||||
uint32_t _0x4C;
|
||||
uint32_t _0x50;
|
||||
uint32_t _0x54;
|
||||
uint32_t _0x58;
|
||||
uint32_t _0x5C;
|
||||
uint32_t _0x60;
|
||||
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_SECURITY_MODE;
|
||||
uint32_t FUSE_PRIVATE_KEY[0x4];
|
||||
uint32_t FUSE_DEVICE_KEY;
|
||||
uint32_t _0xB8;
|
||||
uint32_t _0xBC;
|
||||
uint32_t FUSE_RESERVED_SW;
|
||||
uint32_t FUSE_VP8_ENABLE;
|
||||
uint32_t FUSE_RESERVED_ODM[0x8];
|
||||
uint32_t _0xE8;
|
||||
uint32_t _0xEC;
|
||||
uint32_t FUSE_SKU_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_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_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_PKC_DISABLE;
|
||||
uint32_t _0x16C;
|
||||
uint32_t _0x170;
|
||||
uint32_t _0x174;
|
||||
uint32_t _0x178;
|
||||
uint32_t _0x17C;
|
||||
uint32_t FUSE_TSENSOR_COMMON;
|
||||
uint32_t _0x184;
|
||||
uint32_t _0x188;
|
||||
uint32_t _0x18C;
|
||||
uint32_t _0x190;
|
||||
uint32_t _0x194;
|
||||
uint32_t _0x198;
|
||||
uint32_t FUSE_DEBUG_AUTH_OVERRIDE;
|
||||
uint32_t _0x1A0;
|
||||
uint32_t _0x1A4;
|
||||
uint32_t _0x1A8;
|
||||
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 _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 _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_USB_CALIB_EXT;
|
||||
uint32_t _0x254;
|
||||
uint32_t _0x258;
|
||||
uint32_t _0x25C;
|
||||
uint32_t _0x260;
|
||||
uint32_t _0x264;
|
||||
uint32_t _0x268;
|
||||
uint32_t _0x26C;
|
||||
uint32_t _0x270;
|
||||
uint32_t _0x274;
|
||||
uint32_t _0x278;
|
||||
uint32_t _0x27C;
|
||||
uint32_t FUSE_SPARE_BIT[0x20];
|
||||
} tegra_fuse_chip_t;
|
||||
|
||||
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) {
|
||||
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);
|
||||
|
||||
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_retail_type(void);
|
||||
void fuse_get_hardware_info(void *dst);
|
||||
|
||||
#endif
|
||||
145
sept/sept-primary/src/gpio.c
Normal file
145
sept/sept-primary/src/gpio.c
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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 <stdint.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "gpio.h"
|
||||
#include "utils.h"
|
||||
|
||||
/**
|
||||
* Returns a GPIO bank object that corresponds to the given GPIO pin,
|
||||
* which can be created using the TEGRA_GPIO macro or passed from the name macro.
|
||||
*
|
||||
* @param pin The GPIO to get the bank for.
|
||||
* @return The GPIO bank object to use for working with the given bank.
|
||||
*/
|
||||
static volatile tegra_gpio_bank_t *gpio_get_bank(uint32_t pin)
|
||||
{
|
||||
volatile tegra_gpio_t *gpio = gpio_get_regs();
|
||||
uint32_t bank_number = pin >> GPIO_BANK_SHIFT;
|
||||
|
||||
return &gpio->bank[bank_number];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the port number for working with the given GPIO.
|
||||
*/
|
||||
static volatile uint32_t gpio_get_port(uint32_t pin)
|
||||
{
|
||||
return (pin >> GPIO_PORT_SHIFT) & GPIO_PORT_MASK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a mask to be used to work with the given GPIO
|
||||
*/
|
||||
static volatile uint32_t gpio_get_mask(uint32_t pin)
|
||||
{
|
||||
uint32_t pin_number = pin & GPIO_PIN_MASK;
|
||||
return (1 << pin_number);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a simple GPIO configuration operation.
|
||||
*
|
||||
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
||||
* @param should_be_set True iff the relevant bit should be set; or false if it should be cleared.
|
||||
* @param offset The offset into a gpio_bank structure
|
||||
*/
|
||||
static void gpio_simple_register_set(uint32_t pin, bool should_be_set, uint32_t offset)
|
||||
{
|
||||
// Retrieve the register set that corresponds to the given pin and offset.
|
||||
uintptr_t cluster_addr = (uintptr_t)gpio_get_bank(pin) + offset;
|
||||
uint32_t *cluster = (uint32_t *)cluster_addr;
|
||||
|
||||
// Figure out the offset into the cluster,
|
||||
// and the mask to be used.
|
||||
uint32_t port = gpio_get_port(pin);
|
||||
uint32_t mask = gpio_get_mask(pin);
|
||||
|
||||
// Set or clear the bit, as appropriate.
|
||||
if (should_be_set)
|
||||
cluster[port] |= mask;
|
||||
else
|
||||
cluster[port] &= ~mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a simple GPIO configuration operation.
|
||||
*
|
||||
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
||||
* @param should_be_set True iff the relevant bit should be set; or false if it should be cleared.
|
||||
* @param offset The offset into a gpio_bank structure
|
||||
*/
|
||||
static bool gpio_simple_register_get(uint32_t pin, uint32_t offset)
|
||||
{
|
||||
// Retrieve the register set that corresponds to the given pin and offset.
|
||||
uintptr_t cluster_addr = (uintptr_t)gpio_get_bank(pin) + offset;
|
||||
uint32_t *cluster = (uint32_t *)cluster_addr;
|
||||
|
||||
// Figure out the offset into the cluster,
|
||||
// and the mask to be used.
|
||||
uint32_t port = gpio_get_port(pin);
|
||||
uint32_t mask = gpio_get_mask(pin);
|
||||
|
||||
// Convert the given value to a boolean.
|
||||
return !!(cluster[port] & mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a given pin as either GPIO or SFIO.
|
||||
*
|
||||
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
||||
* @param mode The relevant mode.
|
||||
*/
|
||||
void gpio_configure_mode(uint32_t pin, uint32_t mode)
|
||||
{
|
||||
gpio_simple_register_set(pin, mode == GPIO_MODE_GPIO, offsetof(tegra_gpio_bank_t, config));
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a given pin as either INPUT or OUPUT.
|
||||
*
|
||||
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
||||
* @param direction The relevant direction.
|
||||
*/
|
||||
void gpio_configure_direction(uint32_t pin, uint32_t dir)
|
||||
{
|
||||
gpio_simple_register_set(pin, dir == GPIO_DIRECTION_OUTPUT, offsetof(tegra_gpio_bank_t, direction));
|
||||
}
|
||||
|
||||
/**
|
||||
* Drives a relevant GPIO pin as either HIGH or LOW.
|
||||
*
|
||||
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
||||
* @param mode The relevant mode.
|
||||
*/
|
||||
void gpio_write(uint32_t pin, uint32_t value)
|
||||
{
|
||||
gpio_simple_register_set(pin, value == GPIO_LEVEL_HIGH, offsetof(tegra_gpio_bank_t, out));
|
||||
}
|
||||
|
||||
/**
|
||||
* Drives a relevant GPIO pin as either HIGH or LOW.
|
||||
*
|
||||
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
||||
* @param mode The relevant mode.
|
||||
*/
|
||||
uint32_t gpio_read(uint32_t pin)
|
||||
{
|
||||
return gpio_simple_register_get(pin, offsetof(tegra_gpio_bank_t, in));
|
||||
}
|
||||
127
sept/sept-primary/src/gpio.h
Normal file
127
sept/sept-primary/src/gpio.h
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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_GPIO_H
|
||||
#define FUSEE_GPIO_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define GPIO_BASE 0x6000D000
|
||||
#define MAKE_GPIO_REG(n) MAKE_REG32(GPIO_BASE + n)
|
||||
|
||||
#define TEGRA_GPIO_PORTS 4
|
||||
#define TEGRA_GPIO_BANKS 8
|
||||
#define GPIO_BANK_SHIFT 5
|
||||
#define GPIO_PORT_SHIFT 3
|
||||
#define GPIO_PORT_MASK 0x03
|
||||
#define GPIO_PIN_MASK 0x07
|
||||
|
||||
typedef enum {
|
||||
TEGRA_GPIO_PORT_A = 0,
|
||||
TEGRA_GPIO_PORT_B = 1,
|
||||
TEGRA_GPIO_PORT_C = 2,
|
||||
TEGRA_GPIO_PORT_D = 3,
|
||||
TEGRA_GPIO_PORT_E = 4,
|
||||
TEGRA_GPIO_PORT_F = 5,
|
||||
TEGRA_GPIO_PORT_G = 6,
|
||||
TEGRA_GPIO_PORT_H = 7,
|
||||
TEGRA_GPIO_PORT_I = 8,
|
||||
TEGRA_GPIO_PORT_J = 9,
|
||||
TEGRA_GPIO_PORT_K = 10,
|
||||
TEGRA_GPIO_PORT_L = 11,
|
||||
TEGRA_GPIO_PORT_M = 12,
|
||||
TEGRA_GPIO_PORT_N = 13,
|
||||
TEGRA_GPIO_PORT_O = 14,
|
||||
TEGRA_GPIO_PORT_P = 15,
|
||||
TEGRA_GPIO_PORT_Q = 16,
|
||||
TEGRA_GPIO_PORT_R = 17,
|
||||
TEGRA_GPIO_PORT_S = 18,
|
||||
TEGRA_GPIO_PORT_T = 19,
|
||||
TEGRA_GPIO_PORT_U = 20,
|
||||
TEGRA_GPIO_PORT_V = 21,
|
||||
TEGRA_GPIO_PORT_W = 22,
|
||||
TEGRA_GPIO_PORT_X = 23,
|
||||
TEGRA_GPIO_PORT_Y = 24,
|
||||
TEGRA_GPIO_PORT_Z = 25,
|
||||
TEGRA_GPIO_PORT_AA = 26,
|
||||
TEGRA_GPIO_PORT_BB = 27,
|
||||
TEGRA_GPIO_PORT_CC = 28,
|
||||
TEGRA_GPIO_PORT_DD = 29,
|
||||
TEGRA_GPIO_PORT_EE = 30,
|
||||
TEGRA_GPIO_PORT_FF = 31,
|
||||
} tegra_gpio_port;
|
||||
|
||||
typedef struct {
|
||||
uint32_t config[TEGRA_GPIO_PORTS];
|
||||
uint32_t direction[TEGRA_GPIO_PORTS];
|
||||
uint32_t out[TEGRA_GPIO_PORTS];
|
||||
uint32_t in[TEGRA_GPIO_PORTS];
|
||||
uint32_t int_status[TEGRA_GPIO_PORTS];
|
||||
uint32_t int_enable[TEGRA_GPIO_PORTS];
|
||||
uint32_t int_level[TEGRA_GPIO_PORTS];
|
||||
uint32_t int_clear[TEGRA_GPIO_PORTS];
|
||||
uint32_t masked_config[TEGRA_GPIO_PORTS];
|
||||
uint32_t masked_dir_out[TEGRA_GPIO_PORTS];
|
||||
uint32_t masked_out[TEGRA_GPIO_PORTS];
|
||||
uint32_t masked_in[TEGRA_GPIO_PORTS];
|
||||
uint32_t masked_int_status[TEGRA_GPIO_PORTS];
|
||||
uint32_t masked_int_enable[TEGRA_GPIO_PORTS];
|
||||
uint32_t masked_int_level[TEGRA_GPIO_PORTS];
|
||||
uint32_t masked_int_clear[TEGRA_GPIO_PORTS];
|
||||
} tegra_gpio_bank_t;
|
||||
|
||||
typedef struct {
|
||||
tegra_gpio_bank_t bank[TEGRA_GPIO_BANKS];
|
||||
} tegra_gpio_t;
|
||||
|
||||
static inline volatile tegra_gpio_t *gpio_get_regs(void)
|
||||
{
|
||||
return (volatile tegra_gpio_t *)GPIO_BASE;
|
||||
}
|
||||
|
||||
#define TEGRA_GPIO(port, offset) \
|
||||
((TEGRA_GPIO_PORT_##port * 8) + offset)
|
||||
|
||||
/* Mode select */
|
||||
#define GPIO_MODE_GPIO 0
|
||||
#define GPIO_MODE_SFIO 1
|
||||
|
||||
/* Direction */
|
||||
#define GPIO_DIRECTION_INPUT 0
|
||||
#define GPIO_DIRECTION_OUTPUT 1
|
||||
|
||||
/* Level */
|
||||
#define GPIO_LEVEL_LOW 0
|
||||
#define GPIO_LEVEL_HIGH 1
|
||||
|
||||
/* Named GPIOs */
|
||||
#define GPIO_BUTTON_VOL_DOWN TEGRA_GPIO(X, 7)
|
||||
#define GPIO_BUTTON_VOL_UP TEGRA_GPIO(X, 6)
|
||||
#define GPIO_MICROSD_CARD_DETECT TEGRA_GPIO(Z, 1)
|
||||
#define GPIO_MICROSD_WRITE_PROTECT TEGRA_GPIO(Z, 4)
|
||||
#define GPIO_MICROSD_SUPPLY_ENABLE TEGRA_GPIO(E, 4)
|
||||
#define GPIO_LCD_BL_P5V TEGRA_GPIO(I, 0)
|
||||
#define GPIO_LCD_BL_N5V TEGRA_GPIO(I, 1)
|
||||
#define GPIO_LCD_BL_PWM TEGRA_GPIO(V, 0)
|
||||
#define GPIO_LCD_BL_EN TEGRA_GPIO(V, 1)
|
||||
#define GPIO_LCD_BL_RST TEGRA_GPIO(V, 2)
|
||||
|
||||
void gpio_configure_mode(uint32_t pin, uint32_t mode);
|
||||
void gpio_configure_direction(uint32_t pin, uint32_t dir);
|
||||
void gpio_write(uint32_t pin, uint32_t value);
|
||||
uint32_t gpio_read(uint32_t pin);
|
||||
|
||||
#endif
|
||||
219
sept/sept-primary/src/i2c.c
Normal file
219
sept/sept-primary/src/i2c.c
Normal file
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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 "i2c.h"
|
||||
#include "utils.h"
|
||||
#include "timers.h"
|
||||
|
||||
/* Prototypes for internal commands. */
|
||||
volatile tegra_i2c_t *i2c_get_registers_from_id(unsigned int id);
|
||||
void i2c_load_config(volatile tegra_i2c_t *regs);
|
||||
|
||||
bool i2c_query(unsigned int id, uint8_t device, uint8_t r, void *dst, size_t dst_size);
|
||||
bool i2c_send(unsigned int id, uint8_t device, uint8_t r, void *src, size_t src_size);
|
||||
|
||||
bool i2c_write(volatile tegra_i2c_t *regs, uint8_t device, void *src, size_t src_size);
|
||||
bool i2c_read(volatile tegra_i2c_t *regs, uint8_t device, void *dst, size_t dst_size);
|
||||
|
||||
/* Initialize I2C based on registers. */
|
||||
void i2c_init(unsigned int id) {
|
||||
volatile tegra_i2c_t *regs = i2c_get_registers_from_id(id);
|
||||
|
||||
/* Setup divisor, and clear the bus. */
|
||||
regs->I2C_I2C_CLK_DIVISOR_REGISTER_0 = 0x50001;
|
||||
regs->I2C_I2C_BUS_CLEAR_CONFIG_0 = 0x90003;
|
||||
|
||||
/* Load hardware configuration. */
|
||||
i2c_load_config(regs);
|
||||
|
||||
/* Wait a while until BUS_CLEAR_DONE is set. */
|
||||
for (unsigned int i = 0; i < 10; i++) {
|
||||
udelay(20000);
|
||||
if (regs->I2C_INTERRUPT_STATUS_REGISTER_0 & 0x800) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the BUS_CLEAR_STATUS. Result doesn't matter. */
|
||||
regs->I2C_I2C_BUS_CLEAR_STATUS_0;
|
||||
|
||||
/* Read and set the Interrupt Status. */
|
||||
uint32_t int_status = regs->I2C_INTERRUPT_STATUS_REGISTER_0;
|
||||
regs->I2C_INTERRUPT_STATUS_REGISTER_0 = int_status;
|
||||
}
|
||||
|
||||
/* Sets a bit in a PMIC register over I2C during CPU shutdown. */
|
||||
void i2c_send_pmic_cpu_shutdown_cmd(void) {
|
||||
uint32_t val = 0;
|
||||
/* PMIC == Device 4:3C. */
|
||||
i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, 0x41, &val, 1);
|
||||
val |= 4;
|
||||
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, 0x41, &val, 1);
|
||||
}
|
||||
|
||||
/* Queries the value of TI charger bit over I2C. */
|
||||
bool i2c_query_ti_charger_bit_7(void) {
|
||||
uint32_t val = 0;
|
||||
/* TI Charger = Device 0:6B. */
|
||||
i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1);
|
||||
return (val & 0x80) != 0;
|
||||
}
|
||||
|
||||
/* Clears TI charger bit over I2C. */
|
||||
void i2c_clear_ti_charger_bit_7(void) {
|
||||
uint32_t val = 0;
|
||||
/* TI Charger = Device 0:6B. */
|
||||
i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1);
|
||||
val &= 0x7F;
|
||||
i2c_send(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1);
|
||||
}
|
||||
|
||||
/* Sets TI charger bit over I2C. */
|
||||
void i2c_set_ti_charger_bit_7(void) {
|
||||
uint32_t val = 0;
|
||||
/* TI Charger = Device 0:6B. */
|
||||
i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1);
|
||||
val |= 0x80;
|
||||
i2c_send(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1);
|
||||
}
|
||||
|
||||
/* Get registers pointer based on I2C ID. */
|
||||
volatile tegra_i2c_t *i2c_get_registers_from_id(unsigned int id) {
|
||||
switch (id) {
|
||||
case I2C_1:
|
||||
return I2C1_REGS;
|
||||
case I2C_2:
|
||||
return I2C2_REGS;
|
||||
case I2C_3:
|
||||
return I2C3_REGS;
|
||||
case I2C_4:
|
||||
return I2C4_REGS;
|
||||
case I2C_5:
|
||||
return I2C5_REGS;
|
||||
case I2C_6:
|
||||
return I2C6_REGS;
|
||||
default:
|
||||
generic_panic();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Load hardware config for I2C4. */
|
||||
void i2c_load_config(volatile tegra_i2c_t *regs) {
|
||||
/* Set MSTR_CONFIG_LOAD, TIMEOUT_CONFIG_LOAD, undocumented bit. */
|
||||
regs->I2C_I2C_CONFIG_LOAD_0 = 0x25;
|
||||
|
||||
/* Wait a bit for master config to be loaded. */
|
||||
for (unsigned int i = 0; i < 20; i++) {
|
||||
udelay(1);
|
||||
if (!(regs->I2C_I2C_CONFIG_LOAD_0 & 1)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Reads a register from a device over I2C, writes result to output. */
|
||||
bool i2c_query(unsigned int id, uint8_t device, uint8_t r, void *dst, size_t dst_size) {
|
||||
volatile tegra_i2c_t *regs = i2c_get_registers_from_id(id);
|
||||
uint32_t val = r;
|
||||
|
||||
/* Write single byte register ID to device. */
|
||||
if (!i2c_write(regs, device, &val, 1)) {
|
||||
return false;
|
||||
}
|
||||
/* Limit output size to 32-bits. */
|
||||
if (dst_size > 4) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return i2c_read(regs, device, dst, dst_size);
|
||||
}
|
||||
|
||||
/* Writes a value to a register over I2C. */
|
||||
bool i2c_send(unsigned int id, uint8_t device, uint8_t r, void *src, size_t src_size) {
|
||||
uint32_t val = r;
|
||||
if (src_size == 0) {
|
||||
return true;
|
||||
} else if (src_size <= 3) {
|
||||
memcpy(((uint8_t *)&val) + 1, src, src_size);
|
||||
return i2c_write(i2c_get_registers_from_id(id), device, &val, src_size + 1);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Writes bytes to device over I2C. */
|
||||
bool i2c_write(volatile tegra_i2c_t *regs, uint8_t device, void *src, size_t src_size) {
|
||||
if (src_size > 4) {
|
||||
return false;
|
||||
} else if (src_size == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Set device for 7-bit write mode. */
|
||||
regs->I2C_I2C_CMD_ADDR0_0 = device << 1;
|
||||
|
||||
/* Load in data to write. */
|
||||
regs->I2C_I2C_CMD_DATA1_0 = read32le(src, 0);
|
||||
|
||||
/* Set config with LENGTH = src_size, NEW_MASTER_FSM, DEBOUNCE_CNT = 4T. */
|
||||
regs->I2C_I2C_CNFG_0 = ((src_size << 1) - 2) | 0x2800;
|
||||
|
||||
i2c_load_config(regs);
|
||||
|
||||
/* Config |= SEND; */
|
||||
regs->I2C_I2C_CNFG_0 = ((regs->I2C_I2C_CNFG_0 & 0xFFFFFDFF) | 0x200);
|
||||
|
||||
while (regs->I2C_I2C_STATUS_0 & 0x100) {
|
||||
/* Wait until not busy. */
|
||||
}
|
||||
|
||||
/* Return CMD1_STAT == SL1_XFER_SUCCESSFUL. */
|
||||
return (regs->I2C_I2C_STATUS_0 & 0xF) == 0;
|
||||
}
|
||||
|
||||
/* Reads bytes from device over I2C. */
|
||||
bool i2c_read(volatile tegra_i2c_t *regs, uint8_t device, void *dst, size_t dst_size) {
|
||||
if (dst_size > 4) {
|
||||
return false;
|
||||
} else if (dst_size == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Set device for 7-bit read mode. */
|
||||
regs->I2C_I2C_CMD_ADDR0_0 = (device << 1) | 1;
|
||||
|
||||
/* Set config with LENGTH = dst_size, NEW_MASTER_FSM, DEBOUNCE_CNT = 4T. */
|
||||
regs->I2C_I2C_CNFG_0 = ((dst_size << 1) - 2) | 0x2840;
|
||||
|
||||
i2c_load_config(regs);
|
||||
|
||||
/* Config |= SEND; */
|
||||
regs->I2C_I2C_CNFG_0 = ((regs->I2C_I2C_CNFG_0 & 0xFFFFFDFF) | 0x200);
|
||||
|
||||
while (regs->I2C_I2C_STATUS_0 & 0x100) {
|
||||
/* Wait until not busy. */
|
||||
}
|
||||
|
||||
/* Ensure success. */
|
||||
if ((regs->I2C_I2C_STATUS_0 & 0xF) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t val = regs->I2C_I2C_CMD_DATA1_0;
|
||||
memcpy(dst, &val, dst_size);
|
||||
return true;
|
||||
}
|
||||
101
sept/sept-primary/src/i2c.h
Normal file
101
sept/sept-primary/src/i2c.h
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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_I2C_H
|
||||
#define FUSEE_I2C_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#define I2C1234_BASE 0x7000C000
|
||||
#define I2C56_BASE 0x7000D000
|
||||
|
||||
#define I2C_1 0
|
||||
#define I2C_2 1
|
||||
#define I2C_3 2
|
||||
#define I2C_4 3
|
||||
#define I2C_5 4
|
||||
#define I2C_6 5
|
||||
|
||||
#define MAX77621_CPU_I2C_ADDR 0x1B
|
||||
#define MAX77621_GPU_I2C_ADDR 0x1C
|
||||
#define MAX17050_I2C_ADDR 0x36
|
||||
#define MAX77620_PWR_I2C_ADDR 0x3C
|
||||
#define MAX77620_RTC_I2C_ADDR 0x68
|
||||
#define BQ24193_I2C_ADDR 0x6B
|
||||
|
||||
typedef struct {
|
||||
uint32_t I2C_I2C_CNFG_0;
|
||||
uint32_t I2C_I2C_CMD_ADDR0_0;
|
||||
uint32_t I2C_I2C_CMD_ADDR1_0;
|
||||
uint32_t I2C_I2C_CMD_DATA1_0;
|
||||
uint32_t I2C_I2C_CMD_DATA2_0;
|
||||
uint32_t _0x14;
|
||||
uint32_t _0x18;
|
||||
uint32_t I2C_I2C_STATUS_0;
|
||||
uint32_t I2C_I2C_SL_CNFG_0;
|
||||
uint32_t I2C_I2C_SL_RCVD_0;
|
||||
uint32_t I2C_I2C_SL_STATUS_0;
|
||||
uint32_t I2C_I2C_SL_ADDR1_0;
|
||||
uint32_t I2C_I2C_SL_ADDR2_0;
|
||||
uint32_t I2C_I2C_TLOW_SEXT_0;
|
||||
uint32_t _0x38;
|
||||
uint32_t I2C_I2C_SL_DELAY_COUNT_0;
|
||||
uint32_t I2C_I2C_SL_INT_MASK_0;
|
||||
uint32_t I2C_I2C_SL_INT_SOURCE_0;
|
||||
uint32_t I2C_I2C_SL_INT_SET_0;
|
||||
uint32_t _0x4C;
|
||||
uint32_t I2C_I2C_TX_PACKET_FIFO_0;
|
||||
uint32_t I2C_I2C_RX_FIFO_0;
|
||||
uint32_t I2C_PACKET_TRANSFER_STATUS_0;
|
||||
uint32_t I2C_FIFO_CONTROL_0;
|
||||
uint32_t I2C_FIFO_STATUS_0;
|
||||
uint32_t I2C_INTERRUPT_MASK_REGISTER_0;
|
||||
uint32_t I2C_INTERRUPT_STATUS_REGISTER_0;
|
||||
uint32_t I2C_I2C_CLK_DIVISOR_REGISTER_0;
|
||||
uint32_t I2C_I2C_INTERRUPT_SOURCE_REGISTER_0;
|
||||
uint32_t I2C_I2C_INTERRUPT_SET_REGISTER_0;
|
||||
uint32_t I2C_I2C_SLV_TX_PACKET_FIFO_0;
|
||||
uint32_t I2C_I2C_SLV_RX_FIFO_0;
|
||||
uint32_t I2C_I2C_SLV_PACKET_STATUS_0;
|
||||
uint32_t I2C_I2C_BUS_CLEAR_CONFIG_0;
|
||||
uint32_t I2C_I2C_BUS_CLEAR_STATUS_0;
|
||||
uint32_t I2C_I2C_CONFIG_LOAD_0;
|
||||
uint32_t _0x90;
|
||||
uint32_t I2C_I2C_INTERFACE_TIMING_0_0;
|
||||
uint32_t I2C_I2C_INTERFACE_TIMING_1_0;
|
||||
uint32_t I2C_I2C_HS_INTERFACE_TIMING_0_0;
|
||||
uint32_t I2C_I2C_HS_INTERFACE_TIMING_1_0;
|
||||
} tegra_i2c_t;
|
||||
|
||||
#define I2C1_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x000))
|
||||
#define I2C2_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x400))
|
||||
#define I2C3_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x500))
|
||||
#define I2C4_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x700))
|
||||
#define I2C5_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x000))
|
||||
#define I2C6_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x100))
|
||||
|
||||
void i2c_init(unsigned int id);
|
||||
bool i2c_query(unsigned int id, uint8_t device, uint8_t r, void *dst, size_t dst_size);
|
||||
bool i2c_send(unsigned int id, uint8_t device, uint8_t r, void *src, size_t src_size);
|
||||
|
||||
void i2c_send_pmic_cpu_shutdown_cmd(void);
|
||||
bool i2c_query_ti_charger_bit_7(void);
|
||||
void i2c_clear_ti_charger_bit_7(void);
|
||||
void i2c_set_ti_charger_bit_7(void);
|
||||
|
||||
#endif
|
||||
224
sept/sept-primary/src/main.c
Normal file
224
sept/sept-primary/src/main.c
Normal file
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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 <stdint.h>
|
||||
#include "utils.h"
|
||||
#include "car.h"
|
||||
#include "timers.h"
|
||||
#include "di.h"
|
||||
#include "se.h"
|
||||
#include "fuse.h"
|
||||
#include "pmc.h"
|
||||
#include "mc.h"
|
||||
#include "sysreg.h"
|
||||
#include "tsec.h"
|
||||
|
||||
#define I2S_BASE 0x702D1000
|
||||
#define MAKE_I2S_REG(n) MAKE_REG32(I2S_BASE + n)
|
||||
|
||||
static void setup_exception_vectors(void) {
|
||||
for (unsigned int i = 0; i < 0x20; i += 4) {
|
||||
MAKE_REG32(0x6000F200u + i) = (uint32_t)generic_panic;
|
||||
}
|
||||
}
|
||||
|
||||
static void mbist_workaround(void)
|
||||
{
|
||||
volatile tegra_car_t *car = car_get_regs();
|
||||
|
||||
car->clk_source_sor1 = ((car->clk_source_sor1 | 0x8000) & 0xFFFFBFFF);
|
||||
car->plld_base |= 0x40800000u;
|
||||
car->rst_dev_y_clr = 0x40;
|
||||
car->rst_dev_x_clr = 0x40000;
|
||||
car->rst_dev_l_clr = 0x18000000;
|
||||
udelay(3);
|
||||
|
||||
/* Setup I2S. */
|
||||
MAKE_I2S_REG(0x0A0) |= 0x400;
|
||||
MAKE_I2S_REG(0x088) &= 0xFFFFFFFE;
|
||||
MAKE_I2S_REG(0x1A0) |= 0x400;
|
||||
MAKE_I2S_REG(0x188) &= 0xFFFFFFFE;
|
||||
MAKE_I2S_REG(0x2A0) |= 0x400;
|
||||
MAKE_I2S_REG(0x288) &= 0xFFFFFFFE;
|
||||
MAKE_I2S_REG(0x3A0) |= 0x400;
|
||||
MAKE_I2S_REG(0x388) &= 0xFFFFFFFE;
|
||||
MAKE_I2S_REG(0x4A0) |= 0x400;
|
||||
MAKE_I2S_REG(0x488) &= 0xFFFFFFFE;
|
||||
|
||||
MAKE_DI_REG(DC_COM_DSC_TOP_CTL) |= 4;
|
||||
MAKE_VIC_REG(0x8C) = 0xFFFFFFFF;
|
||||
udelay(3);
|
||||
|
||||
/* Set devices in reset. */
|
||||
car->rst_dev_y_set = 0x40;
|
||||
car->rst_dev_l_set = 0x18000000;
|
||||
car->rst_dev_x_set = 0x40000;
|
||||
|
||||
/* Clock out enables. */
|
||||
car->clk_out_enb_h = 0xC0;
|
||||
car->clk_out_enb_l = 0x80000130;
|
||||
car->clk_out_enb_u = 0x1F00200;
|
||||
car->clk_out_enb_v = 0x80400808;
|
||||
car->clk_out_enb_w = 0x402000FC;
|
||||
car->clk_out_enb_x = 0x23000780;
|
||||
car->clk_out_enb_y = 0x300;
|
||||
|
||||
/* LVL2 clock gate overrides. */
|
||||
car->lvl2_clk_gate_ovra = 0;
|
||||
car->lvl2_clk_gate_ovrb = 0;
|
||||
car->lvl2_clk_gate_ovrc = 0;
|
||||
car->lvl2_clk_gate_ovrd = 0;
|
||||
car->lvl2_clk_gate_ovre = 0;
|
||||
|
||||
/* Configure clock sources. */
|
||||
car->plld_base &= 0x1F7FFFFF;
|
||||
car->clk_source_sor1 &= 0xFFFF3FFF;
|
||||
car->clk_source_vi = ((car->clk_source_vi & 0x1FFFFFFF) | 0x80000000);
|
||||
car->clk_source_host1x = ((car->clk_source_host1x & 0x1FFFFFFF) | 0x80000000);
|
||||
car->clk_source_nvenc = ((car->clk_source_nvenc & 0x1FFFFFFF) | 0x80000000);
|
||||
}
|
||||
|
||||
static int tsec_dma_wait_idle()
|
||||
{
|
||||
volatile tegra_tsec_t *tsec = tsec_get_regs();
|
||||
uint32_t timeout = (get_time_us() + 10000000);
|
||||
|
||||
while (!(tsec->FALCON_DMATRFCMD & 2))
|
||||
if (get_time_us() > timeout)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tsec_dma_phys_to_flcn(bool is_imem, uint32_t flcn_offset, uint32_t phys_offset)
|
||||
{
|
||||
volatile tegra_tsec_t *tsec = tsec_get_regs();
|
||||
uint32_t cmd = 0;
|
||||
|
||||
if (!is_imem)
|
||||
cmd = 0x600;
|
||||
else
|
||||
cmd = 0x10;
|
||||
|
||||
tsec->FALCON_DMATRFMOFFS = flcn_offset;
|
||||
tsec->FALCON_DMATRFFBOFFS = phys_offset;
|
||||
tsec->FALCON_DMATRFCMD = cmd;
|
||||
|
||||
return tsec_dma_wait_idle();
|
||||
}
|
||||
|
||||
int load_tsec_fw(void) {
|
||||
volatile uint32_t* tsec_fw = (volatile uint32_t*)0x40010F00;
|
||||
const uint32_t tsec_fw_length = MAKE_REG32(0x40010EFC);
|
||||
|
||||
volatile tegra_tsec_t *tsec = tsec_get_regs();
|
||||
|
||||
/* Enable clocks. */
|
||||
clkrst_reboot(CARDEVICE_HOST1X);
|
||||
clkrst_reboot(CARDEVICE_TSEC);
|
||||
clkrst_reboot(CARDEVICE_SOR_SAFE);
|
||||
clkrst_reboot(CARDEVICE_SOR0);
|
||||
clkrst_reboot(CARDEVICE_SOR1);
|
||||
clkrst_reboot(CARDEVICE_KFUSE);
|
||||
|
||||
/* Configure Falcon. */
|
||||
tsec->FALCON_DMACTL = 0;
|
||||
tsec->FALCON_IRQMSET = 0xFFF2;
|
||||
tsec->FALCON_IRQDEST = 0xFFF0;
|
||||
tsec->FALCON_ITFEN = 3;
|
||||
|
||||
if (!tsec_dma_wait_idle())
|
||||
{
|
||||
/* Disable clocks. */
|
||||
clkrst_disable(CARDEVICE_KFUSE);
|
||||
clkrst_disable(CARDEVICE_SOR1);
|
||||
clkrst_disable(CARDEVICE_SOR0);
|
||||
clkrst_disable(CARDEVICE_SOR_SAFE);
|
||||
clkrst_disable(CARDEVICE_TSEC);
|
||||
clkrst_disable(CARDEVICE_HOST1X);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Load firmware. */
|
||||
tsec->FALCON_DMATRFBASE = (uint32_t)tsec_fw >> 8;
|
||||
for (uint32_t addr = 0; addr < tsec_fw_length; addr += 0x100)
|
||||
{
|
||||
if (!tsec_dma_phys_to_flcn(true, addr, addr))
|
||||
{
|
||||
/* Disable clocks. */
|
||||
clkrst_disable(CARDEVICE_KFUSE);
|
||||
clkrst_disable(CARDEVICE_SOR1);
|
||||
clkrst_disable(CARDEVICE_SOR0);
|
||||
clkrst_disable(CARDEVICE_SOR_SAFE);
|
||||
clkrst_disable(CARDEVICE_TSEC);
|
||||
clkrst_disable(CARDEVICE_HOST1X);
|
||||
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Unknown host1x write. */
|
||||
MAKE_HOST1X_REG(0x3300) = 0x34C2E1DA;
|
||||
|
||||
|
||||
/* Execute firmware. */
|
||||
tsec->FALCON_SCRATCH1 = 0;
|
||||
tsec->FALCON_SCRATCH0 = 1;
|
||||
tsec->FALCON_BOOTVEC = 0;
|
||||
tsec->FALCON_CPUCTL = 2;
|
||||
|
||||
while (true) {
|
||||
/* Yield to Nintendo's TSEC firmware. */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(void) {
|
||||
/* Setup vectors */
|
||||
setup_exception_vectors();
|
||||
|
||||
volatile tegra_pmc_t *pmc = pmc_get_regs();
|
||||
volatile tegra_car_t *car = car_get_regs();
|
||||
|
||||
/* Clear the boot reason to avoid problems later */
|
||||
pmc->scratch200 = 0;
|
||||
pmc->reset_status = 0;
|
||||
|
||||
//AHB_AHB_SPARE_REG_0 &= 0xFFFFFF9F;
|
||||
//pmc->scratch49 = (((pmc->scratch49 >> 1) << 1) & 0xFFFFFFFD);
|
||||
|
||||
/* Apply the memory built-in self test workaround. */
|
||||
mbist_workaround();
|
||||
|
||||
/* Reboot SE. */
|
||||
clkrst_reboot(CARDEVICE_SE);
|
||||
|
||||
/* Initialize the fuse driver. */
|
||||
fuse_init();
|
||||
|
||||
/* Don't bother checking SKU, fuses, or bootloader version. */
|
||||
mc_enable_for_tsec();
|
||||
|
||||
/* 7.0.0 package1ldr holds I2C5 in reset, clears SYS clock. */
|
||||
car->clk_source_sys = 0;
|
||||
rst_enable(CARDEVICE_I2C5);
|
||||
|
||||
load_tsec_fw();
|
||||
|
||||
while (true) { }
|
||||
return 0;
|
||||
}
|
||||
50
sept/sept-primary/src/mc.c
Normal file
50
sept/sept-primary/src/mc.c
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 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 "mc.h"
|
||||
#include "car.h"
|
||||
#include "timers.h"
|
||||
|
||||
void mc_enable_for_tsec()
|
||||
{
|
||||
volatile tegra_car_t *car = car_get_regs();
|
||||
|
||||
/* Set EMC clock source. */
|
||||
car->clk_source_emc = ((car->clk_source_emc & 0x1FFFFFFF) | 0x40000000);
|
||||
|
||||
/* Enable MIPI CAL clock. */
|
||||
car->clk_enb_h_set = ((car->clk_enb_h_set & 0xFDFFFFFF) | 0x2000000);
|
||||
|
||||
/* Enable MC clock. */
|
||||
car->clk_enb_h_set = ((car->clk_enb_h_set & 0xFFFFFFFE) | 1);
|
||||
|
||||
/* Enable EMC DLL clock. */
|
||||
car->clk_enb_x_set = ((car->clk_enb_x_set & 0xFFFFBFFF) | 0x4000);
|
||||
|
||||
/* Clear EMC and MC reset. */
|
||||
/* NOTE: [4.0.0+] This was changed to use the right register. */
|
||||
/* car->rst_dev_h_set = 0x2000001; */
|
||||
car->rst_dev_h_clr = 0x2000001;
|
||||
udelay(5);
|
||||
|
||||
/* Enable AHB redirect, weird boundaries for new TSEC firmware. */
|
||||
car->lvl2_clk_gate_ovrd = ((car->lvl2_clk_gate_ovrd & 0xFFF7FFFF) | 0x80000);
|
||||
|
||||
MAKE_MC_REG(MC_IRAM_REG_CTRL) &= 0xFFFFFFFE;
|
||||
MAKE_MC_REG(MC_IRAM_BOM) = 0x40000000;
|
||||
MAKE_MC_REG(MC_IRAM_TOM) = 0x80000000;
|
||||
}
|
||||
593
sept/sept-primary/src/mc.h
Normal file
593
sept/sept-primary/src/mc.h
Normal file
@@ -0,0 +1,593 @@
|
||||
/*
|
||||
* Copyright (c) 2014, NVIDIA Corporation. All rights reserved.
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 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_MC_H_
|
||||
#define FUSEE_MC_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define MC_BASE 0x70019000
|
||||
#define MAKE_MC_REG(n) MAKE_REG32(MC_BASE + n)
|
||||
|
||||
#define MC_INTSTATUS 0x0
|
||||
#define MC_INTMASK 0x4
|
||||
#define MC_ERR_STATUS 0x8
|
||||
#define MC_ERR_ADR 0xc
|
||||
#define MC_SMMU_CONFIG 0x10
|
||||
#define MC_SMMU_TLB_CONFIG 0x14
|
||||
#define MC_SMMU_PTC_CONFIG 0x18
|
||||
#define MC_SMMU_PTB_ASID 0x1c
|
||||
#define MC_SMMU_PTB_DATA 0x20
|
||||
#define MC_SMMU_TLB_FLUSH 0x30
|
||||
#define MC_SMMU_PTC_FLUSH 0x34
|
||||
#define MC_SMMU_ASID_SECURITY 0x38
|
||||
#define MC_SMMU_AFI_ASID 0x238
|
||||
#define MC_SMMU_AVPC_ASID 0x23c
|
||||
#define MC_SMMU_TSEC_ASID 0x294
|
||||
#define MC_SMMU_PPCS1_ASID 0x298
|
||||
#define MC_SMMU_TRANSLATION_ENABLE_0 0x228
|
||||
#define MC_SMMU_TRANSLATION_ENABLE_1 0x22c
|
||||
#define MC_SMMU_TRANSLATION_ENABLE_2 0x230
|
||||
#define MC_SMMU_TRANSLATION_ENABLE_3 0x234
|
||||
#define MC_SMMU_TRANSLATION_ENABLE_4 0xb98
|
||||
#define MC_PCFIFO_CLIENT_CONFIG0 0xdd0
|
||||
#define MC_PCFIFO_CLIENT_CONFIG1 0xdd4
|
||||
#define MC_PCFIFO_CLIENT_CONFIG2 0xdd8
|
||||
#define MC_PCFIFO_CLIENT_CONFIG3 0xddc
|
||||
#define MC_PCFIFO_CLIENT_CONFIG4 0xde0
|
||||
#define MC_EMEM_CFG 0x50
|
||||
#define MC_EMEM_ADR_CFG 0x54
|
||||
#define MC_EMEM_ADR_CFG_DEV0 0x58
|
||||
#define MC_EMEM_ADR_CFG_DEV1 0x5c
|
||||
#define MC_EMEM_ADR_CFG_CHANNEL_MASK 0x60
|
||||
#define MC_EMEM_ADR_CFG_BANK_MASK_0 0x64
|
||||
#define MC_EMEM_ADR_CFG_BANK_MASK_1 0x68
|
||||
#define MC_EMEM_ADR_CFG_BANK_MASK_2 0x6c
|
||||
#define MC_SECURITY_CFG0 0x70
|
||||
#define MC_SECURITY_CFG1 0x74
|
||||
#define MC_SECURITY_CFG3 0x9bc
|
||||
#define MC_SECURITY_RSV 0x7c
|
||||
#define MC_EMEM_ARB_CFG 0x90
|
||||
#define MC_EMEM_ARB_OUTSTANDING_REQ 0x94
|
||||
#define MC_EMEM_ARB_TIMING_RCD 0x98
|
||||
#define MC_EMEM_ARB_TIMING_RP 0x9c
|
||||
#define MC_EMEM_ARB_TIMING_RC 0xa0
|
||||
#define MC_EMEM_ARB_TIMING_RAS 0xa4
|
||||
#define MC_EMEM_ARB_TIMING_FAW 0xa8
|
||||
#define MC_EMEM_ARB_TIMING_RRD 0xac
|
||||
#define MC_EMEM_ARB_TIMING_RAP2PRE 0xb0
|
||||
#define MC_EMEM_ARB_TIMING_WAP2PRE 0xb4
|
||||
#define MC_EMEM_ARB_TIMING_R2R 0xb8
|
||||
#define MC_EMEM_ARB_TIMING_W2W 0xbc
|
||||
#define MC_EMEM_ARB_TIMING_R2W 0xc0
|
||||
#define MC_EMEM_ARB_TIMING_W2R 0xc4
|
||||
#define MC_EMEM_ARB_TIMING_RFCPB 0x6c0
|
||||
#define MC_EMEM_ARB_TIMING_CCDMW 0x6c4
|
||||
#define MC_EMEM_ARB_REFPB_HP_CTRL 0x6f0
|
||||
#define MC_EMEM_ARB_REFPB_BANK_CTRL 0x6f4
|
||||
#define MC_EMEM_ARB_DA_TURNS 0xd0
|
||||
#define MC_EMEM_ARB_DA_COVERS 0xd4
|
||||
#define MC_EMEM_ARB_MISC0 0xd8
|
||||
#define MC_EMEM_ARB_MISC1 0xdc
|
||||
#define MC_EMEM_ARB_MISC2 0xc8
|
||||
#define MC_EMEM_ARB_RING1_THROTTLE 0xe0
|
||||
#define MC_EMEM_ARB_RING3_THROTTLE 0xe4
|
||||
#define MC_EMEM_ARB_NISO_THROTTLE 0x6b0
|
||||
#define MC_EMEM_ARB_OVERRIDE 0xe8
|
||||
#define MC_EMEM_ARB_RSV 0xec
|
||||
#define MC_CLKEN_OVERRIDE 0xf4
|
||||
#define MC_TIMING_CONTROL_DBG 0xf8
|
||||
#define MC_TIMING_CONTROL 0xfc
|
||||
#define MC_STAT_CONTROL 0x100
|
||||
#define MC_STAT_STATUS 0x104
|
||||
#define MC_STAT_EMC_CLOCK_LIMIT 0x108
|
||||
#define MC_STAT_EMC_CLOCK_LIMIT_MSBS 0x10c
|
||||
#define MC_STAT_EMC_CLOCKS 0x110
|
||||
#define MC_STAT_EMC_CLOCKS_MSBS 0x114
|
||||
#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_LO 0x118
|
||||
#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_LO 0x158
|
||||
#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_HI 0x11c
|
||||
#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_HI 0x15c
|
||||
#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_UPPER 0xa20
|
||||
#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_UPPER 0xa24
|
||||
#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_LO 0x198
|
||||
#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_LO 0x1a8
|
||||
#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_HI 0x19c
|
||||
#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_HI 0x1ac
|
||||
#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_UPPER 0xa28
|
||||
#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_UPPER 0xa2c
|
||||
#define MC_STAT_EMC_FILTER_SET0_ASID 0x1a0
|
||||
#define MC_STAT_EMC_FILTER_SET1_ASID 0x1b0
|
||||
#define MC_STAT_EMC_FILTER_SET0_SLACK_LIMIT 0x120
|
||||
#define MC_STAT_EMC_FILTER_SET1_SLACK_LIMIT 0x160
|
||||
#define MC_STAT_EMC_FILTER_SET0_CLIENT_0 0x128
|
||||
#define MC_STAT_EMC_FILTER_SET1_CLIENT_0 0x168
|
||||
#define MC_STAT_EMC_FILTER_SET0_CLIENT_1 0x12c
|
||||
#define MC_STAT_EMC_FILTER_SET1_CLIENT_1 0x16c
|
||||
#define MC_STAT_EMC_FILTER_SET0_CLIENT_2 0x130
|
||||
#define MC_STAT_EMC_FILTER_SET1_CLIENT_2 0x170
|
||||
#define MC_STAT_EMC_FILTER_SET0_CLIENT_3 0x134
|
||||
#define MC_STAT_EMC_FILTER_SET0_CLIENT_4 0xb88
|
||||
#define MC_STAT_EMC_FILTER_SET1_CLIENT_3 0x174
|
||||
#define MC_STAT_EMC_FILTER_SET1_CLIENT_4 0xb8c
|
||||
#define MC_STAT_EMC_SET0_COUNT 0x138
|
||||
#define MC_STAT_EMC_SET0_COUNT_MSBS 0x13c
|
||||
#define MC_STAT_EMC_SET1_COUNT 0x178
|
||||
#define MC_STAT_EMC_SET1_COUNT_MSBS 0x17c
|
||||
#define MC_STAT_EMC_SET0_SLACK_ACCUM 0x140
|
||||
#define MC_STAT_EMC_SET0_SLACK_ACCUM_MSBS 0x144
|
||||
#define MC_STAT_EMC_SET1_SLACK_ACCUM 0x180
|
||||
#define MC_STAT_EMC_SET1_SLACK_ACCUM_MSBS 0x184
|
||||
#define MC_STAT_EMC_SET0_HISTO_COUNT 0x148
|
||||
#define MC_STAT_EMC_SET0_HISTO_COUNT_MSBS 0x14c
|
||||
#define MC_STAT_EMC_SET1_HISTO_COUNT 0x188
|
||||
#define MC_STAT_EMC_SET1_HISTO_COUNT_MSBS 0x18c
|
||||
#define MC_STAT_EMC_SET0_MINIMUM_SLACK_OBSERVED 0x150
|
||||
#define MC_STAT_EMC_SET1_MINIMUM_SLACK_OBSERVED 0x190
|
||||
#define MC_STAT_EMC_SET0_IDLE_CYCLE_COUNT 0x1b8
|
||||
#define MC_STAT_EMC_SET0_IDLE_CYCL_COUNT_MSBS 0x1bc
|
||||
#define MC_STAT_EMC_SET1_IDLE_CYCLE_COUNT 0x1c8
|
||||
#define MC_STAT_EMC_SET1_IDLE_CYCL_COUNT_MSBS 0x1cc
|
||||
#define MC_STAT_EMC_SET0_IDLE_CYCLE_PARTITION_SELECT 0x1c0
|
||||
#define MC_STAT_EMC_SET1_IDLE_CYCLE_PARTITION_SELECT 0x1d0
|
||||
#define MC_CLIENT_HOTRESET_CTRL 0x200
|
||||
#define MC_CLIENT_HOTRESET_CTRL_1 0x970
|
||||
#define MC_CLIENT_HOTRESET_STATUS 0x204
|
||||
#define MC_CLIENT_HOTRESET_STATUS_1 0x974
|
||||
#define MC_EMEM_ARB_ISOCHRONOUS_0 0x208
|
||||
#define MC_EMEM_ARB_ISOCHRONOUS_1 0x20c
|
||||
#define MC_EMEM_ARB_ISOCHRONOUS_2 0x210
|
||||
#define MC_EMEM_ARB_ISOCHRONOUS_3 0x214
|
||||
#define MC_EMEM_ARB_ISOCHRONOUS_4 0xb94
|
||||
#define MC_EMEM_ARB_HYSTERESIS_0 0x218
|
||||
#define MC_EMEM_ARB_HYSTERESIS_1 0x21c
|
||||
#define MC_EMEM_ARB_HYSTERESIS_2 0x220
|
||||
#define MC_EMEM_ARB_HYSTERESIS_3 0x224
|
||||
#define MC_EMEM_ARB_HYSTERESIS_4 0xb84
|
||||
#define MC_EMEM_ARB_DHYSTERESIS_0 0xbb0
|
||||
#define MC_EMEM_ARB_DHYSTERESIS_1 0xbb4
|
||||
#define MC_EMEM_ARB_DHYSTERESIS_2 0xbb8
|
||||
#define MC_EMEM_ARB_DHYSTERESIS_3 0xbbc
|
||||
#define MC_EMEM_ARB_DHYSTERESIS_4 0xbc0
|
||||
#define MC_EMEM_ARB_DHYST_CTRL 0xbcc
|
||||
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_0 0xbd0
|
||||
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_1 0xbd4
|
||||
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_2 0xbd8
|
||||
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_3 0xbdc
|
||||
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_4 0xbe0
|
||||
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_5 0xbe4
|
||||
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_6 0xbe8
|
||||
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_7 0xbec
|
||||
#define MC_RESERVED_RSV 0x3fc
|
||||
#define MC_DISB_EXTRA_SNAP_LEVELS 0x408
|
||||
#define MC_APB_EXTRA_SNAP_LEVELS 0x2a4
|
||||
#define MC_AHB_EXTRA_SNAP_LEVELS 0x2a0
|
||||
#define MC_USBD_EXTRA_SNAP_LEVELS 0xa18
|
||||
#define MC_ISP_EXTRA_SNAP_LEVELS 0xa08
|
||||
#define MC_AUD_EXTRA_SNAP_LEVELS 0xa10
|
||||
#define MC_MSE_EXTRA_SNAP_LEVELS 0x40c
|
||||
#define MC_GK2_EXTRA_SNAP_LEVELS 0xa40
|
||||
#define MC_A9AVPPC_EXTRA_SNAP_LEVELS 0x414
|
||||
#define MC_FTOP_EXTRA_SNAP_LEVELS 0x2bc
|
||||
#define MC_JPG_EXTRA_SNAP_LEVELS 0xa3c
|
||||
#define MC_HOST_EXTRA_SNAP_LEVELS 0xa14
|
||||
#define MC_SAX_EXTRA_SNAP_LEVELS 0x2c0
|
||||
#define MC_DIS_EXTRA_SNAP_LEVELS 0x2ac
|
||||
#define MC_VICPC_EXTRA_SNAP_LEVELS 0xa1c
|
||||
#define MC_HDAPC_EXTRA_SNAP_LEVELS 0xa48
|
||||
#define MC_AVP_EXTRA_SNAP_LEVELS 0x2a8
|
||||
#define MC_USBX_EXTRA_SNAP_LEVELS 0x404
|
||||
#define MC_PCX_EXTRA_SNAP_LEVELS 0x2b8
|
||||
#define MC_SD_EXTRA_SNAP_LEVELS 0xa04
|
||||
#define MC_DFD_EXTRA_SNAP_LEVELS 0xa4c
|
||||
#define MC_VE_EXTRA_SNAP_LEVELS 0x2d8
|
||||
#define MC_GK_EXTRA_SNAP_LEVELS 0xa00
|
||||
#define MC_VE2_EXTRA_SNAP_LEVELS 0x410
|
||||
#define MC_SDM_EXTRA_SNAP_LEVELS 0xa44
|
||||
#define MC_VIDEO_PROTECT_BOM 0x648
|
||||
#define MC_VIDEO_PROTECT_SIZE_MB 0x64c
|
||||
#define MC_VIDEO_PROTECT_BOM_ADR_HI 0x978
|
||||
#define MC_VIDEO_PROTECT_REG_CTRL 0x650
|
||||
#define MC_ERR_VPR_STATUS 0x654
|
||||
#define MC_ERR_VPR_ADR 0x658
|
||||
#define MC_VIDEO_PROTECT_VPR_OVERRIDE 0x418
|
||||
#define MC_VIDEO_PROTECT_VPR_OVERRIDE1 0x590
|
||||
#define MC_IRAM_BOM 0x65c
|
||||
#define MC_IRAM_TOM 0x660
|
||||
#define MC_IRAM_ADR_HI 0x980
|
||||
#define MC_IRAM_REG_CTRL 0x964
|
||||
#define MC_EMEM_CFG_ACCESS_CTRL 0x664
|
||||
#define MC_TZ_SECURITY_CTRL 0x668
|
||||
#define MC_EMEM_ARB_OUTSTANDING_REQ_RING3 0x66c
|
||||
#define MC_EMEM_ARB_OUTSTANDING_REQ_NISO 0x6b4
|
||||
#define MC_EMEM_ARB_RING0_THROTTLE_MASK 0x6bc
|
||||
#define MC_EMEM_ARB_NISO_THROTTLE_MASK 0x6b8
|
||||
#define MC_EMEM_ARB_NISO_THROTTLE_MASK_1 0xb80
|
||||
#define MC_SEC_CARVEOUT_BOM 0x670
|
||||
#define MC_SEC_CARVEOUT_SIZE_MB 0x674
|
||||
#define MC_SEC_CARVEOUT_ADR_HI 0x9d4
|
||||
#define MC_SEC_CARVEOUT_REG_CTRL 0x678
|
||||
#define MC_ERR_SEC_STATUS 0x67c
|
||||
#define MC_ERR_SEC_ADR 0x680
|
||||
#define MC_PC_IDLE_CLOCK_GATE_CONFIG 0x684
|
||||
#define MC_STUTTER_CONTROL 0x688
|
||||
#define MC_RESERVED_RSV_1 0x958
|
||||
#define MC_DVFS_PIPE_SELECT 0x95c
|
||||
#define MC_AHB_PTSA_MIN 0x4e0
|
||||
#define MC_AUD_PTSA_MIN 0x54c
|
||||
#define MC_MLL_MPCORER_PTSA_RATE 0x44c
|
||||
#define MC_RING2_PTSA_RATE 0x440
|
||||
#define MC_USBD_PTSA_RATE 0x530
|
||||
#define MC_USBX_PTSA_MIN 0x528
|
||||
#define MC_USBD_PTSA_MIN 0x534
|
||||
#define MC_APB_PTSA_MAX 0x4f0
|
||||
#define MC_JPG_PTSA_RATE 0x584
|
||||
#define MC_DIS_PTSA_MIN 0x420
|
||||
#define MC_AVP_PTSA_MAX 0x4fc
|
||||
#define MC_AVP_PTSA_RATE 0x4f4
|
||||
#define MC_RING1_PTSA_MIN 0x480
|
||||
#define MC_DIS_PTSA_MAX 0x424
|
||||
#define MC_SD_PTSA_MAX 0x4d8
|
||||
#define MC_MSE_PTSA_RATE 0x4c4
|
||||
#define MC_VICPC_PTSA_MIN 0x558
|
||||
#define MC_PCX_PTSA_MAX 0x4b4
|
||||
#define MC_ISP_PTSA_RATE 0x4a0
|
||||
#define MC_A9AVPPC_PTSA_MIN 0x48c
|
||||
#define MC_RING2_PTSA_MAX 0x448
|
||||
#define MC_AUD_PTSA_RATE 0x548
|
||||
#define MC_HOST_PTSA_MIN 0x51c
|
||||
#define MC_MLL_MPCORER_PTSA_MAX 0x454
|
||||
#define MC_SD_PTSA_MIN 0x4d4
|
||||
#define MC_RING1_PTSA_RATE 0x47c
|
||||
#define MC_JPG_PTSA_MIN 0x588
|
||||
#define MC_HDAPC_PTSA_MIN 0x62c
|
||||
#define MC_AVP_PTSA_MIN 0x4f8
|
||||
#define MC_JPG_PTSA_MAX 0x58c
|
||||
#define MC_VE_PTSA_MAX 0x43c
|
||||
#define MC_DFD_PTSA_MAX 0x63c
|
||||
#define MC_VICPC_PTSA_RATE 0x554
|
||||
#define MC_GK_PTSA_MAX 0x544
|
||||
#define MC_VICPC_PTSA_MAX 0x55c
|
||||
#define MC_SDM_PTSA_MAX 0x624
|
||||
#define MC_SAX_PTSA_RATE 0x4b8
|
||||
#define MC_PCX_PTSA_MIN 0x4b0
|
||||
#define MC_APB_PTSA_MIN 0x4ec
|
||||
#define MC_GK2_PTSA_MIN 0x614
|
||||
#define MC_PCX_PTSA_RATE 0x4ac
|
||||
#define MC_RING1_PTSA_MAX 0x484
|
||||
#define MC_HDAPC_PTSA_RATE 0x628
|
||||
#define MC_MLL_MPCORER_PTSA_MIN 0x450
|
||||
#define MC_GK2_PTSA_MAX 0x618
|
||||
#define MC_AUD_PTSA_MAX 0x550
|
||||
#define MC_GK2_PTSA_RATE 0x610
|
||||
#define MC_ISP_PTSA_MAX 0x4a8
|
||||
#define MC_DISB_PTSA_RATE 0x428
|
||||
#define MC_VE2_PTSA_MAX 0x49c
|
||||
#define MC_DFD_PTSA_MIN 0x638
|
||||
#define MC_FTOP_PTSA_RATE 0x50c
|
||||
#define MC_A9AVPPC_PTSA_RATE 0x488
|
||||
#define MC_VE2_PTSA_MIN 0x498
|
||||
#define MC_USBX_PTSA_MAX 0x52c
|
||||
#define MC_DIS_PTSA_RATE 0x41c
|
||||
#define MC_USBD_PTSA_MAX 0x538
|
||||
#define MC_A9AVPPC_PTSA_MAX 0x490
|
||||
#define MC_USBX_PTSA_RATE 0x524
|
||||
#define MC_FTOP_PTSA_MAX 0x514
|
||||
#define MC_HDAPC_PTSA_MAX 0x630
|
||||
#define MC_SD_PTSA_RATE 0x4d0
|
||||
#define MC_DFD_PTSA_RATE 0x634
|
||||
#define MC_FTOP_PTSA_MIN 0x510
|
||||
#define MC_SDM_PTSA_RATE 0x61c
|
||||
#define MC_AHB_PTSA_RATE 0x4dc
|
||||
#define MC_SMMU_SMMU_PTSA_MAX 0x460
|
||||
#define MC_RING2_PTSA_MIN 0x444
|
||||
#define MC_SDM_PTSA_MIN 0x620
|
||||
#define MC_APB_PTSA_RATE 0x4e8
|
||||
#define MC_MSE_PTSA_MIN 0x4c8
|
||||
#define MC_HOST_PTSA_RATE 0x518
|
||||
#define MC_VE_PTSA_RATE 0x434
|
||||
#define MC_AHB_PTSA_MAX 0x4e4
|
||||
#define MC_SAX_PTSA_MIN 0x4bc
|
||||
#define MC_SMMU_SMMU_PTSA_MIN 0x45c
|
||||
#define MC_ISP_PTSA_MIN 0x4a4
|
||||
#define MC_HOST_PTSA_MAX 0x520
|
||||
#define MC_SAX_PTSA_MAX 0x4c0
|
||||
#define MC_VE_PTSA_MIN 0x438
|
||||
#define MC_GK_PTSA_MIN 0x540
|
||||
#define MC_MSE_PTSA_MAX 0x4cc
|
||||
#define MC_DISB_PTSA_MAX 0x430
|
||||
#define MC_DISB_PTSA_MIN 0x42c
|
||||
#define MC_SMMU_SMMU_PTSA_RATE 0x458
|
||||
#define MC_VE2_PTSA_RATE 0x494
|
||||
#define MC_GK_PTSA_RATE 0x53c
|
||||
#define MC_PTSA_GRANT_DECREMENT 0x960
|
||||
#define MC_LATENCY_ALLOWANCE_AVPC_0 0x2e4
|
||||
#define MC_LATENCY_ALLOWANCE_AXIAP_0 0x3a0
|
||||
#define MC_LATENCY_ALLOWANCE_XUSB_1 0x380
|
||||
#define MC_LATENCY_ALLOWANCE_ISP2B_0 0x384
|
||||
#define MC_LATENCY_ALLOWANCE_SDMMCAA_0 0x3bc
|
||||
#define MC_LATENCY_ALLOWANCE_SDMMCA_0 0x3b8
|
||||
#define MC_LATENCY_ALLOWANCE_ISP2_0 0x370
|
||||
#define MC_LATENCY_ALLOWANCE_SE_0 0x3e0
|
||||
#define MC_LATENCY_ALLOWANCE_ISP2_1 0x374
|
||||
#define MC_LATENCY_ALLOWANCE_DC_0 0x2e8
|
||||
#define MC_LATENCY_ALLOWANCE_VIC_0 0x394
|
||||
#define MC_LATENCY_ALLOWANCE_DCB_1 0x2f8
|
||||
#define MC_LATENCY_ALLOWANCE_NVDEC_0 0x3d8
|
||||
#define MC_LATENCY_ALLOWANCE_DCB_2 0x2fc
|
||||
#define MC_LATENCY_ALLOWANCE_TSEC_0 0x390
|
||||
#define MC_LATENCY_ALLOWANCE_DC_2 0x2f0
|
||||
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0AB 0x694
|
||||
#define MC_LATENCY_ALLOWANCE_PPCS_1 0x348
|
||||
#define MC_LATENCY_ALLOWANCE_XUSB_0 0x37c
|
||||
#define MC_LATENCY_ALLOWANCE_PPCS_0 0x344
|
||||
#define MC_LATENCY_ALLOWANCE_TSECB_0 0x3f0
|
||||
#define MC_LATENCY_ALLOWANCE_AFI_0 0x2e0
|
||||
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0B 0x698
|
||||
#define MC_LATENCY_ALLOWANCE_DC_1 0x2ec
|
||||
#define MC_LATENCY_ALLOWANCE_APE_0 0x3dc
|
||||
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0C 0x6a0
|
||||
#define MC_LATENCY_ALLOWANCE_A9AVP_0 0x3a4
|
||||
#define MC_LATENCY_ALLOWANCE_GPU2_0 0x3e8
|
||||
#define MC_LATENCY_ALLOWANCE_DCB_0 0x2f4
|
||||
#define MC_LATENCY_ALLOWANCE_HC_1 0x314
|
||||
#define MC_LATENCY_ALLOWANCE_SDMMC_0 0x3c0
|
||||
#define MC_LATENCY_ALLOWANCE_NVJPG_0 0x3e4
|
||||
#define MC_LATENCY_ALLOWANCE_PTC_0 0x34c
|
||||
#define MC_LATENCY_ALLOWANCE_ETR_0 0x3ec
|
||||
#define MC_LATENCY_ALLOWANCE_MPCORE_0 0x320
|
||||
#define MC_LATENCY_ALLOWANCE_VI2_0 0x398
|
||||
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0BB 0x69c
|
||||
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0CB 0x6a4
|
||||
#define MC_LATENCY_ALLOWANCE_SATA_0 0x350
|
||||
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0A 0x690
|
||||
#define MC_LATENCY_ALLOWANCE_HC_0 0x310
|
||||
#define MC_LATENCY_ALLOWANCE_DC_3 0x3c8
|
||||
#define MC_LATENCY_ALLOWANCE_GPU_0 0x3ac
|
||||
#define MC_LATENCY_ALLOWANCE_SDMMCAB_0 0x3c4
|
||||
#define MC_LATENCY_ALLOWANCE_ISP2B_1 0x388
|
||||
#define MC_LATENCY_ALLOWANCE_NVENC_0 0x328
|
||||
#define MC_LATENCY_ALLOWANCE_HDA_0 0x318
|
||||
#define MC_MIN_LENGTH_APE_0 0xb34
|
||||
#define MC_MIN_LENGTH_DCB_2 0x8a8
|
||||
#define MC_MIN_LENGTH_A9AVP_0 0x950
|
||||
#define MC_MIN_LENGTH_TSEC_0 0x93c
|
||||
#define MC_MIN_LENGTH_DC_1 0x898
|
||||
#define MC_MIN_LENGTH_AXIAP_0 0x94c
|
||||
#define MC_MIN_LENGTH_ISP2B_0 0x930
|
||||
#define MC_MIN_LENGTH_VI2_0 0x944
|
||||
#define MC_MIN_LENGTH_DCB_0 0x8a0
|
||||
#define MC_MIN_LENGTH_DCB_1 0x8a4
|
||||
#define MC_MIN_LENGTH_PPCS_1 0x8f4
|
||||
#define MC_MIN_LENGTH_NVJPG_0 0xb3c
|
||||
#define MC_MIN_LENGTH_HDA_0 0x8c4
|
||||
#define MC_MIN_LENGTH_NVENC_0 0x8d4
|
||||
#define MC_MIN_LENGTH_SDMMC_0 0xb18
|
||||
#define MC_MIN_LENGTH_ISP2B_1 0x934
|
||||
#define MC_MIN_LENGTH_HC_1 0x8c0
|
||||
#define MC_MIN_LENGTH_DC_3 0xb20
|
||||
#define MC_MIN_LENGTH_AVPC_0 0x890
|
||||
#define MC_MIN_LENGTH_VIC_0 0x940
|
||||
#define MC_MIN_LENGTH_ISP2_0 0x91c
|
||||
#define MC_MIN_LENGTH_HC_0 0x8bc
|
||||
#define MC_MIN_LENGTH_SE_0 0xb38
|
||||
#define MC_MIN_LENGTH_NVDEC_0 0xb30
|
||||
#define MC_MIN_LENGTH_SATA_0 0x8fc
|
||||
#define MC_MIN_LENGTH_DC_0 0x894
|
||||
#define MC_MIN_LENGTH_XUSB_1 0x92c
|
||||
#define MC_MIN_LENGTH_DC_2 0x89c
|
||||
#define MC_MIN_LENGTH_SDMMCAA_0 0xb14
|
||||
#define MC_MIN_LENGTH_GPU_0 0xb04
|
||||
#define MC_MIN_LENGTH_ETR_0 0xb44
|
||||
#define MC_MIN_LENGTH_AFI_0 0x88c
|
||||
#define MC_MIN_LENGTH_PPCS_0 0x8f0
|
||||
#define MC_MIN_LENGTH_ISP2_1 0x920
|
||||
#define MC_MIN_LENGTH_XUSB_0 0x928
|
||||
#define MC_MIN_LENGTH_MPCORE_0 0x8cc
|
||||
#define MC_MIN_LENGTH_TSECB_0 0xb48
|
||||
#define MC_MIN_LENGTH_SDMMCA_0 0xb10
|
||||
#define MC_MIN_LENGTH_GPU2_0 0xb40
|
||||
#define MC_MIN_LENGTH_SDMMCAB_0 0xb1c
|
||||
#define MC_MIN_LENGTH_PTC_0 0x8f8
|
||||
#define MC_EMEM_ARB_OVERRIDE_1 0x968
|
||||
#define MC_VIDEO_PROTECT_GPU_OVERRIDE_0 0x984
|
||||
#define MC_VIDEO_PROTECT_GPU_OVERRIDE_1 0x988
|
||||
#define MC_EMEM_ARB_STATS_0 0x990
|
||||
#define MC_EMEM_ARB_STATS_1 0x994
|
||||
#define MC_MTS_CARVEOUT_BOM 0x9a0
|
||||
#define MC_MTS_CARVEOUT_SIZE_MB 0x9a4
|
||||
#define MC_MTS_CARVEOUT_ADR_HI 0x9a8
|
||||
#define MC_MTS_CARVEOUT_REG_CTRL 0x9ac
|
||||
#define MC_ERR_MTS_STATUS 0x9b0
|
||||
#define MC_ERR_MTS_ADR 0x9b4
|
||||
#define MC_ERR_GENERALIZED_CARVEOUT_STATUS 0xc00
|
||||
#define MC_ERR_GENERALIZED_CARVEOUT_ADR 0xc04
|
||||
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS2 0xd74
|
||||
#define MC_SECURITY_CARVEOUT4_CFG0 0xcf8
|
||||
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS2 0xd10
|
||||
#define MC_SECURITY_CARVEOUT4_SIZE_128KB 0xd04
|
||||
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS4 0xc28
|
||||
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS1 0xc30
|
||||
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS4 0xc8c
|
||||
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS0 0xd1c
|
||||
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS1 0xd70
|
||||
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS0 0xc2c
|
||||
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS4 0xd7c
|
||||
#define MC_SECURITY_CARVEOUT3_SIZE_128KB 0xcb4
|
||||
#define MC_SECURITY_CARVEOUT2_CFG0 0xc58
|
||||
#define MC_SECURITY_CARVEOUT1_CFG0 0xc08
|
||||
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS2 0xc84
|
||||
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS0 0xc68
|
||||
#define MC_SECURITY_CARVEOUT3_BOM 0xcac
|
||||
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2 0xc70
|
||||
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS3 0xd78
|
||||
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS0 0xc7c
|
||||
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS4 0xd18
|
||||
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS1 0xcbc
|
||||
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS3 0xc38
|
||||
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS2 0xc34
|
||||
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS2 0xcc0
|
||||
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS2 0xd60
|
||||
#define MC_SECURITY_CARVEOUT3_CFG0 0xca8
|
||||
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS0 0xcb8
|
||||
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS3 0xc88
|
||||
#define MC_SECURITY_CARVEOUT2_SIZE_128KB 0xc64
|
||||
#define MC_SECURITY_CARVEOUT5_BOM_HI 0xd50
|
||||
#define MC_SECURITY_CARVEOUT1_SIZE_128KB 0xc14
|
||||
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS3 0xd14
|
||||
#define MC_SECURITY_CARVEOUT1_BOM 0xc0c
|
||||
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS4 0xd2c
|
||||
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS4 0xd68
|
||||
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS4 0xcc8
|
||||
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS0 0xd58
|
||||
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS2 0xd24
|
||||
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS3 0xcc4
|
||||
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4 0xc78
|
||||
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS1 0xc1c
|
||||
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS0 0xc18
|
||||
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS3 0xd28
|
||||
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS1 0xd5c
|
||||
#define MC_SECURITY_CARVEOUT3_BOM_HI 0xcb0
|
||||
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS3 0xcd8
|
||||
#define MC_SECURITY_CARVEOUT2_BOM_HI 0xc60
|
||||
#define MC_SECURITY_CARVEOUT4_BOM_HI 0xd00
|
||||
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS3 0xd64
|
||||
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS4 0xcdc
|
||||
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS1 0xc80
|
||||
#define MC_SECURITY_CARVEOUT5_SIZE_128KB 0xd54
|
||||
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS1 0xd20
|
||||
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS2 0xcd4
|
||||
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS1 0xd0c
|
||||
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS3 0xc74
|
||||
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS0 0xccc
|
||||
#define MC_SECURITY_CARVEOUT4_BOM 0xcfc
|
||||
#define MC_SECURITY_CARVEOUT5_CFG0 0xd48
|
||||
#define MC_SECURITY_CARVEOUT2_BOM 0xc5c
|
||||
#define MC_SECURITY_CARVEOUT5_BOM 0xd4c
|
||||
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS3 0xc24
|
||||
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS0 0xd6c
|
||||
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS1 0xcd0
|
||||
#define MC_SECURITY_CARVEOUT1_BOM_HI 0xc10
|
||||
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS2 0xc20
|
||||
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS4 0xc3c
|
||||
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS1 0xc6c
|
||||
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS0 0xd08
|
||||
#define MC_ERR_APB_ASID_UPDATE_STATUS 0x9d0
|
||||
#define MC_DA_CONFIG0 0x9dc
|
||||
|
||||
/* Memory Controller clients */
|
||||
#define CLIENT_ACCESS_NUM_CLIENTS 32
|
||||
typedef enum {
|
||||
/* _ACCESS0 */
|
||||
CSR_PTCR = (0 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||
CSR_DISPLAY0A = (1 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||
CSR_DISPLAY0AB = (2 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||
CSR_DISPLAY0B = (3 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||
CSR_DISPLAY0BB = (4 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||
CSR_DISPLAY0C = (5 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||
CSR_DISPLAY0CB = (6 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||
CSR_AFIR = (14 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||
CSR_AVPCARM7R = (15 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||
CSR_DISPLAYHC = (16 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||
CSR_DISPLAYHCB = (17 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||
CSR_HDAR = (21 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||
CSR_HOST1XDMAR = (22 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||
CSR_HOST1XR = (23 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||
CSR_NVENCSRD = (28 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||
CSR_PPCSAHBDMAR = (29 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||
CSR_PPCSAHBSLVR = (30 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||
CSR_SATAR = (31 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||
|
||||
/* _ACCESS1 */
|
||||
CSR_VDEBSEVR = (34 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||
CSR_VDEMBER = (35 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||
CSR_VDEMCER = (36 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||
CSR_VDETPER = (37 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||
CSR_MPCORELPR = (38 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||
CSR_MPCORER = (39 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||
CSW_NVENCSWR = (43 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||
CSW_AFIW = (49 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||
CSW_AVPCARM7W = (50 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||
CSW_HDAW = (53 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||
CSW_HOST1XW = (54 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||
CSW_MPCORELPW = (56 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||
CSW_MPCOREW = (57 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||
CSW_PPCSAHBDMAW = (59 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||
CSW_PPCSAHBSLVW = (60 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||
CSW_SATAW = (61 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||
CSW_VDEBSEVW = (62 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||
CSW_VDEDBGW = (63 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||
|
||||
/* _ACCESS2 */
|
||||
CSW_VDEMBEW = (64 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||
CSW_VDETPMW = (65 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||
CSR_ISPRA = (68 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||
CSW_ISPWA = (70 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||
CSW_ISPWB = (71 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||
CSR_XUSB_HOSTR = (74 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||
CSW_XUSB_HOSTW = (75 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||
CSR_XUSB_DEVR = (76 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||
CSW_XUSB_DEVW = (77 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||
CSR_ISPRAB = (78 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||
CSW_ISPWAB = (80 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||
CSW_ISPWBB = (81 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||
CSR_TSECSRD = (84 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||
CSW_TSECSWR = (85 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||
CSR_A9AVPSCR = (86 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||
CSW_A9AVPSCW = (87 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||
CSR_GPUSRD = (88 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||
CSW_GPUSWR = (89 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||
CSR_DISPLAYT = (90 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||
|
||||
/* _ACCESS3 */
|
||||
CSR_SDMMCRA = (96 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||
CSR_SDMMCRAA = (97 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||
CSR_SDMMCR = (98 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||
CSR_SDMMCRAB = (99 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||
CSW_SDMMCWA = (100 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||
CSW_SDMMCWAA = (101 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||
CSW_SDMMCW = (102 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||
CSW_SDMMCWAB = (103 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||
CSR_VICSRD = (108 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||
CSW_VICSWR = (109 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||
CSW_VIW = (114 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||
CSR_DISPLAYD = (115 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||
CSR_NVDECSRD = (120 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||
CSW_NVDECSWR = (121 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||
CSR_APER = (122 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||
CSW_APEW = (123 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||
CSR_NVJPGSRD = (126 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||
CSW_NVJPGSWR = (127 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||
|
||||
/* _ACCESS4 */
|
||||
CSR_SESRD = (128 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
|
||||
CSW_SESWR = (129 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
|
||||
CSR_AXIAPR = (130 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
|
||||
CSW_AXIAPW = (131 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
|
||||
CSR_ETRR = (132 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
|
||||
CSW_ETRW = (133 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
|
||||
CSR_TSECSRDB = (134 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
|
||||
CSW_TSECSWRB = (135 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
|
||||
CSR_GPUSRD2 = (136 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
|
||||
CSW_GPUSWR2 = (137 - (CLIENT_ACCESS_NUM_CLIENTS * 4))
|
||||
} McClient;
|
||||
|
||||
void mc_enable_for_tsec();
|
||||
|
||||
#endif
|
||||
93
sept/sept-primary/src/panic.c
Normal file
93
sept/sept-primary/src/panic.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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 "panic.h"
|
||||
#include "di.h"
|
||||
#include "pmc.h"
|
||||
#include "fuse.h"
|
||||
#include "utils.h"
|
||||
|
||||
static uint32_t g_panic_code = 0;
|
||||
|
||||
void check_panic(void) {
|
||||
/* We also handle our own panics. */
|
||||
/* In the case of our own panics, we assume that the display has already been initialized. */
|
||||
bool has_panic = APBDEV_PMC_RST_STATUS_0 != 0 || g_panic_code != 0;
|
||||
uint32_t code = g_panic_code == 0 ? APBDEV_PMC_SCRATCH200_0 : g_panic_code;
|
||||
|
||||
has_panic = has_panic && !(APBDEV_PMC_RST_STATUS_0 != 1 && code == PANIC_CODE_SAFEMODE);
|
||||
|
||||
if (has_panic) {
|
||||
uint32_t color;
|
||||
|
||||
/* Check for predefined codes: */
|
||||
switch (code & MASK(20)) {
|
||||
case 0x01: /* Package2 signature verification failed. */
|
||||
case 0x02: /* Package2 meta verification failed. */
|
||||
case 0x03: /* Package2 version check failed. */
|
||||
case 0x04: /* Package2 payload verification failed. */
|
||||
color = PANIC_COLOR_KERNEL;
|
||||
break;
|
||||
case 0x05: /* Unknown SMC. */
|
||||
case 0x06: /* Unknown Abort. */
|
||||
color = PANIC_COLOR_SECMON_GENERIC;
|
||||
break;
|
||||
case 0x07: /* Invalid CPU context. */
|
||||
case 0x08: /* Invalid SE state. */
|
||||
case 0x09: /* CPU is already awake (2.0.0+). */
|
||||
color = PANIC_COLOR_SECMON_DEEPSLEEP;
|
||||
break;
|
||||
case 0x10: /* Unknown exception. */
|
||||
color = PANIC_COLOR_SECMON_EXCEPTION;
|
||||
break;
|
||||
case 0x30: /* General bootloader error. */
|
||||
case 0x31: /* Invalid DRAM ID. */
|
||||
case 0x32: /* Invalid size. */
|
||||
case 0x33: /* Invalid arguement. */
|
||||
case 0x34: /* Bad GPT. */
|
||||
case 0x35: /* Failed to boot SafeMode. */
|
||||
case 0x36: /* Activity monitor fired (4.0.0+). */
|
||||
color = PANIC_COLOR_BOOTLOADER_GENERIC;
|
||||
break;
|
||||
case 0x40: /* Kernel panic. */
|
||||
color = PANIC_COLOR_KERNEL;
|
||||
break;
|
||||
default:
|
||||
color = code >> 20;
|
||||
color |= color << 4;
|
||||
break;
|
||||
}
|
||||
|
||||
wait_for_button_and_reboot();
|
||||
} else {
|
||||
g_panic_code = 0;
|
||||
APBDEV_PMC_SCRATCH200_0 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__ ((noreturn)) void panic(uint32_t code) {
|
||||
/* Set panic code. */
|
||||
if (g_panic_code == 0) {
|
||||
g_panic_code = code;
|
||||
APBDEV_PMC_SCRATCH200_0 = code;
|
||||
}
|
||||
|
||||
fuse_disable_programming();
|
||||
APBDEV_PMC_CRYPTO_OP_0 = 1; /* Disable all SE operations. */
|
||||
|
||||
check_panic();
|
||||
while(true);
|
||||
}
|
||||
34
sept/sept-primary/src/panic.h
Normal file
34
sept/sept-primary/src/panic.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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_PANIC_H
|
||||
#define FUSEE_PANIC_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define PANIC_COLOR_KERNEL 0x0000FF
|
||||
#define PANIC_COLOR_SECMON_EXCEPTION 0xFF7700
|
||||
#define PANIC_COLOR_SECMON_GENERIC 0x00FFFF
|
||||
#define PANIC_COLOR_SECMON_DEEPSLEEP 0xFF77FF /* 4.0+ color */
|
||||
#define PANIC_COLOR_BOOTLOADER_GENERIC 0xAA00FF
|
||||
#define PANIC_COLOR_BOOTLOADER_SAFEMODE 0xFFFFAA /* Removed */
|
||||
|
||||
#define PANIC_CODE_SAFEMODE 0x00000020
|
||||
|
||||
void check_and_display_panic(void);
|
||||
__attribute__ ((noreturn)) void panic(uint32_t code);
|
||||
|
||||
#endif
|
||||
626
sept/sept-primary/src/pmc.h
Normal file
626
sept/sept-primary/src/pmc.h
Normal file
@@ -0,0 +1,626 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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
|
||||
649
sept/sept-primary/src/se.c
Normal file
649
sept/sept-primary/src/se.c
Normal file
@@ -0,0 +1,649 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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 "utils.h"
|
||||
#include "se.h"
|
||||
|
||||
void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const void *src, size_t src_size);
|
||||
|
||||
/* Globals for driver. */
|
||||
static unsigned int g_se_modulus_sizes[KEYSLOT_RSA_MAX];
|
||||
static unsigned int g_se_exp_sizes[KEYSLOT_RSA_MAX];
|
||||
|
||||
/* Initialize a SE linked list. */
|
||||
void NOINLINE ll_init(volatile se_ll_t *ll, void *buffer, size_t size) {
|
||||
ll->num_entries = 0; /* 1 Entry. */
|
||||
|
||||
if (buffer != NULL) {
|
||||
ll->addr_info.address = (uint32_t) get_physical_address(buffer);
|
||||
ll->addr_info.size = (uint32_t) size;
|
||||
} else {
|
||||
ll->addr_info.address = 0;
|
||||
ll->addr_info.size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void se_check_error_status_reg(void) {
|
||||
if (se_get_regs()->ERR_STATUS_REG) {
|
||||
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) {
|
||||
generic_panic();
|
||||
}
|
||||
}
|
||||
|
||||
void se_verify_flags_cleared(void) {
|
||||
if (se_get_regs()->FLAGS_REG & 3) {
|
||||
generic_panic();
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the flags for an AES keyslot. */
|
||||
void set_aes_keyslot_flags(unsigned int keyslot, unsigned int flags) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
|
||||
if (keyslot >= KEYSLOT_AES_MAX) {
|
||||
generic_panic();
|
||||
}
|
||||
|
||||
/* Misc flags. */
|
||||
if (flags & ~0x80) {
|
||||
se->AES_KEYSLOT_FLAGS[keyslot] = ~flags;
|
||||
}
|
||||
|
||||
/* Disable keyslot reads. */
|
||||
if (flags & 0x80) {
|
||||
se->AES_KEY_READ_DISABLE_REG &= ~(1 << keyslot);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the flags for an RSA keyslot. */
|
||||
void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
|
||||
if (keyslot >= KEYSLOT_RSA_MAX) {
|
||||
generic_panic();
|
||||
}
|
||||
|
||||
/* Misc flags. */
|
||||
if (flags & ~0x80) {
|
||||
/* TODO: Why are flags assigned this way? */
|
||||
se->RSA_KEYSLOT_FLAGS[keyslot] = (((flags >> 4) & 4) | (flags & 3)) ^ 7;
|
||||
}
|
||||
|
||||
/* Disable keyslot reads. */
|
||||
if (flags & 0x80) {
|
||||
se->RSA_KEY_READ_DISABLE_REG &= ~(1 << keyslot);
|
||||
}
|
||||
}
|
||||
|
||||
void clear_aes_keyslot(unsigned int keyslot) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
|
||||
if (keyslot >= KEYSLOT_AES_MAX) {
|
||||
generic_panic();
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
void clear_rsa_keyslot(unsigned int keyslot) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
|
||||
if (keyslot >= KEYSLOT_RSA_MAX) {
|
||||
generic_panic();
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
for (unsigned int i = 0; i < 0x40; i++) {
|
||||
/* Select Keyslot Expontent[i] */
|
||||
se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i;
|
||||
se->RSA_KEYTABLE_DATA = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void set_aes_keyslot(unsigned int keyslot, const void *key, size_t key_size) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
|
||||
if (keyslot >= KEYSLOT_AES_MAX || key_size > KEYSIZE_AES_MAX) {
|
||||
generic_panic();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_size, const void *exponent, size_t exp_size) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
|
||||
if (keyslot >= KEYSLOT_RSA_MAX || modulus_size > KEYSIZE_RSA_MAX || exp_size > KEYSIZE_RSA_MAX) {
|
||||
generic_panic();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
g_se_modulus_sizes[keyslot] = modulus_size;
|
||||
g_se_exp_sizes[keyslot] = exp_size;
|
||||
}
|
||||
|
||||
void set_aes_keyslot_iv(unsigned int keyslot, const void *iv, size_t iv_size) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
|
||||
if (keyslot >= KEYSLOT_AES_MAX || iv_size > 0x10) {
|
||||
generic_panic();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void clear_aes_keyslot_iv(unsigned int keyslot) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
|
||||
if (keyslot >= KEYSLOT_AES_MAX) {
|
||||
generic_panic();
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < (0x10 >> 2); i++) {
|
||||
se->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i;
|
||||
se->AES_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);
|
||||
}
|
||||
}
|
||||
|
||||
void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_src, const void *wrapped_key, size_t wrapped_key_size) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
|
||||
if (keyslot_dst >= KEYSLOT_AES_MAX || keyslot_src >= KEYSLOT_AES_MAX || wrapped_key_size > KEYSIZE_AES_MAX) {
|
||||
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;
|
||||
|
||||
trigger_se_blocking_op(OP_START, NULL, 0, wrapped_key, wrapped_key_size);
|
||||
}
|
||||
|
||||
void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
uint8_t ALIGN(16) stack_buf[KEYSIZE_RSA_MAX];
|
||||
|
||||
if (keyslot >= KEYSLOT_RSA_MAX || src_size > KEYSIZE_RSA_MAX || dst_size > KEYSIZE_RSA_MAX) {
|
||||
generic_panic();
|
||||
}
|
||||
|
||||
/* Endian swap the input. */
|
||||
for (size_t i = 0; i < src_size; i++) {
|
||||
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;
|
||||
|
||||
trigger_se_blocking_op(OP_START, NULL, 0, stack_buf, src_size);
|
||||
se_get_exp_mod_output(dst, dst_size);
|
||||
}
|
||||
|
||||
void se_get_exp_mod_output(void *buf, size_t size) {
|
||||
size_t num_dwords = (size >> 2);
|
||||
|
||||
if (num_dwords < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t *p_out = ((uint32_t *)buf) + num_dwords - 1;
|
||||
uint32_t offset = 0;
|
||||
|
||||
/* Copy endian swapped output. */
|
||||
while (num_dwords) {
|
||||
*p_out = read32be(se_get_regs()->RSA_OUTPUT, offset);
|
||||
offset += 4;
|
||||
p_out--;
|
||||
num_dwords--;
|
||||
}
|
||||
}
|
||||
|
||||
bool se_rsa2048_pss_verify(const void *signature, size_t signature_size, const void *modulus, size_t modulus_size, const void *data, size_t data_size) {
|
||||
uint8_t message[RSA_2048_BYTES];
|
||||
uint8_t h_buf[0x24];
|
||||
|
||||
/* Hardcode RSA with keyslot 0. */
|
||||
const uint8_t public_exponent[4] = {0x00, 0x01, 0x00, 0x01};
|
||||
set_rsa_keyslot(0, modulus, modulus_size, public_exponent, sizeof(public_exponent));
|
||||
se_synchronous_exp_mod(0, message, sizeof(message), signature, signature_size);
|
||||
|
||||
/* Validate sanity byte. */
|
||||
if (message[RSA_2048_BYTES - 1] != 0xBC) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Copy Salt into MGF1 Hash Buffer. */
|
||||
memset(h_buf, 0, sizeof(h_buf));
|
||||
memcpy(h_buf, message + RSA_2048_BYTES - 0x20 - 0x1, 0x20);
|
||||
|
||||
/* Decrypt maskedDB (via inline MGF1). */
|
||||
uint8_t seed = 0;
|
||||
uint8_t mgf1_buf[0x20];
|
||||
for (unsigned int ofs = 0; ofs < RSA_2048_BYTES - 0x20 - 1; ofs += 0x20) {
|
||||
h_buf[sizeof(h_buf) - 1] = seed++;
|
||||
se_calculate_sha256(mgf1_buf, h_buf, sizeof(h_buf));
|
||||
for (unsigned int i = ofs; i < ofs + 0x20 && i < RSA_2048_BYTES - 0x20 - 1; i++) {
|
||||
message[i] ^= mgf1_buf[i - ofs];
|
||||
}
|
||||
}
|
||||
|
||||
/* Constant lmask for rsa-2048-pss. */
|
||||
message[0] &= 0x7F;
|
||||
|
||||
/* Validate DB is of the form 0000...0001. */
|
||||
for (unsigned int i = 0; i < RSA_2048_BYTES - 0x20 - 0x20 - 1 - 1; i++) {
|
||||
if (message[i] != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (message[RSA_2048_BYTES - 0x20 - 0x20 - 1 - 1] != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check hash correctness. */
|
||||
uint8_t validate_buf[8 + 0x20 + 0x20];
|
||||
uint8_t validate_hash[0x20];
|
||||
|
||||
memset(validate_buf, 0, sizeof(validate_buf));
|
||||
se_calculate_sha256(&validate_buf[8], data, data_size);
|
||||
memcpy(&validate_buf[0x28], &message[RSA_2048_BYTES - 0x20 - 0x20 - 1], 0x20);
|
||||
se_calculate_sha256(validate_hash, validate_buf, sizeof(validate_buf));
|
||||
return memcmp(h_buf, validate_hash, 0x20) == 0;
|
||||
}
|
||||
|
||||
void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
se_ll_t in_ll;
|
||||
se_ll_t out_ll;
|
||||
|
||||
ll_init(&in_ll, (void *)src, src_size);
|
||||
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);
|
||||
|
||||
/* Set registers for operation. */
|
||||
se->ERR_STATUS_REG = se->ERR_STATUS_REG;
|
||||
se->INT_STATUS_REG = se->INT_STATUS_REG;
|
||||
se->OPERATION_REG = op;
|
||||
|
||||
while (!(se->INT_STATUS_REG & 0x10)) { /* Wait a while */ }
|
||||
se_check_for_error();
|
||||
}
|
||||
|
||||
/* Secure AES Functionality. */
|
||||
void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
uint8_t block[0x10] = {0};
|
||||
|
||||
if (src_size > sizeof(block) || dst_size > sizeof(block)) {
|
||||
generic_panic();
|
||||
}
|
||||
|
||||
/* Load src data into block. */
|
||||
if (src_size != 0) {
|
||||
memcpy(block, src, src_size);
|
||||
}
|
||||
|
||||
/* Trigger AES operation. */
|
||||
se_get_regs()->BLOCK_COUNT_REG = 0;
|
||||
trigger_se_blocking_op(OP_START, block, sizeof(block), block, sizeof(block));
|
||||
|
||||
/* Copy output data into dst. */
|
||||
if (dst_size != 0) {
|
||||
memcpy(dst, block, dst_size);
|
||||
}
|
||||
}
|
||||
|
||||
void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *ctr, size_t ctr_size) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
|
||||
if (keyslot >= KEYSLOT_AES_MAX || ctr_size != 0x10) {
|
||||
generic_panic();
|
||||
}
|
||||
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;
|
||||
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;
|
||||
trigger_se_blocking_op(OP_START, dst, dst_size, src, aligned_size);
|
||||
}
|
||||
|
||||
/* Handle final, unaligned block. */
|
||||
if (aligned_size < dst_size && aligned_size < src_size) {
|
||||
size_t last_block_size = dst_size - aligned_size;
|
||||
if (src_size < dst_size) {
|
||||
last_block_size = src_size - aligned_size;
|
||||
}
|
||||
se_perform_aes_block_operation(dst + aligned_size, last_block_size, (uint8_t *)src + aligned_size, src_size - aligned_size);
|
||||
}
|
||||
}
|
||||
|
||||
void se_aes_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, unsigned int config_high) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
|
||||
if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) {
|
||||
generic_panic();
|
||||
}
|
||||
|
||||
/* 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_perform_aes_block_operation(dst, 0x10, src, 0x10);
|
||||
}
|
||||
|
||||
void se_aes_128_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
se_aes_ecb_encrypt_block(keyslot, dst, dst_size, src, src_size, 0);
|
||||
}
|
||||
|
||||
void se_aes_256_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
se_aes_ecb_encrypt_block(keyslot, dst, dst_size, src, src_size, 0x202);
|
||||
}
|
||||
|
||||
void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
|
||||
if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) {
|
||||
generic_panic();
|
||||
}
|
||||
|
||||
se->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY);
|
||||
se->CRYPTO_REG = keyslot << 24;
|
||||
se_perform_aes_block_operation(dst, 0x10, src, 0x10);
|
||||
}
|
||||
|
||||
void shift_left_xor_rb(uint8_t *key) {
|
||||
uint8_t prev_high_bit = 0;
|
||||
for (unsigned int i = 0; i < 0x10; i++) {
|
||||
uint8_t cur_byte = key[0xF - i];
|
||||
key[0xF - i] = (cur_byte << 1) | (prev_high_bit);
|
||||
prev_high_bit = cur_byte >> 7;
|
||||
}
|
||||
if (prev_high_bit) {
|
||||
key[0xF] ^= 0x87;
|
||||
}
|
||||
}
|
||||
|
||||
void shift_left_xor_rb_le(uint8_t *key) {
|
||||
uint8_t prev_high_bit = 0;
|
||||
for (unsigned int i = 0; i < 0x10; i++) {
|
||||
uint8_t cur_byte = key[i];
|
||||
key[i] = (cur_byte << 1) | (prev_high_bit);
|
||||
prev_high_bit = cur_byte >> 7;
|
||||
}
|
||||
if (prev_high_bit) {
|
||||
key[0x0] ^= 0x87;
|
||||
}
|
||||
}
|
||||
|
||||
void aes_128_xts_nintendo_get_tweak(uint8_t *tweak, size_t sector) {
|
||||
for (int i = 0xF; i >= 0; i--) { /* Nintendo LE custom tweak... */
|
||||
tweak[i] = (unsigned char)(sector & 0xFF);
|
||||
sector >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
void aes_128_xts_nintendo_xor_with_tweak(unsigned int keyslot, size_t sector, uint8_t *dst, const uint8_t *src, size_t size) {
|
||||
if ((size & 0xF) || size == 0) {
|
||||
generic_panic();
|
||||
}
|
||||
uint8_t tweak[0x10];
|
||||
aes_128_xts_nintendo_get_tweak(tweak, sector);
|
||||
se_aes_128_ecb_encrypt_block(keyslot, tweak, sizeof(tweak), tweak, sizeof(tweak));
|
||||
|
||||
for (unsigned int block = 0; block < (size >> 4); block++) {
|
||||
for (unsigned int i = 0; i < 0x10; i++) {
|
||||
dst[(block << 4) | i] = src[(block << 4) | i] ^ tweak[i];
|
||||
}
|
||||
shift_left_xor_rb_le(tweak);
|
||||
}
|
||||
}
|
||||
|
||||
void aes_128_xts_nintendo_crypt_sector(unsigned int keyslot_1, unsigned int keyslot_2, size_t sector, bool encrypt, void *dst, const void *src, size_t size) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
|
||||
if ((size & 0xF) || size == 0) {
|
||||
generic_panic();
|
||||
}
|
||||
|
||||
/* XOR. */
|
||||
aes_128_xts_nintendo_xor_with_tweak(keyslot_2, sector, dst, src, size);
|
||||
|
||||
/* Encrypt/Decrypt. */
|
||||
if (encrypt) {
|
||||
se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY);
|
||||
se->CRYPTO_REG = keyslot_1 << 24 | 0x100;
|
||||
} else {
|
||||
se->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY);
|
||||
se->CRYPTO_REG = keyslot_1 << 24;
|
||||
}
|
||||
se->BLOCK_COUNT_REG = (size >> 4) - 1;
|
||||
trigger_se_blocking_op(OP_START, dst, size, src, size);
|
||||
|
||||
/* XOR. */
|
||||
aes_128_xts_nintendo_xor_with_tweak(keyslot_2, sector, dst, dst, size);
|
||||
}
|
||||
|
||||
/* Encrypt with AES-XTS (Nintendo's custom tweak). */
|
||||
void se_aes_128_xts_nintendo_encrypt(unsigned int keyslot_1, unsigned int keyslot_2, size_t base_sector, void *dst, const void *src, size_t size, unsigned int sector_size) {
|
||||
if ((size & 0xF) || size == 0) {
|
||||
generic_panic();
|
||||
}
|
||||
size_t sector = base_sector;
|
||||
for (size_t ofs = 0; ofs < size; ofs += sector_size) {
|
||||
aes_128_xts_nintendo_crypt_sector(keyslot_1, keyslot_2, sector, true, dst + ofs, src + ofs, sector_size);
|
||||
sector++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Decrypt with AES-XTS (Nintendo's custom tweak). */
|
||||
void se_aes_128_xts_nintendo_decrypt(unsigned int keyslot_1, unsigned int keyslot_2, size_t base_sector, void *dst, const void *src, size_t size, unsigned int sector_size) {
|
||||
if ((size & 0xF) || size == 0) {
|
||||
generic_panic();
|
||||
}
|
||||
size_t sector = base_sector;
|
||||
for (size_t ofs = 0; ofs < size; ofs += sector_size) {
|
||||
aes_128_xts_nintendo_crypt_sector(keyslot_1, keyslot_2, sector, false, dst + ofs, src + ofs, sector_size);
|
||||
sector++;
|
||||
}
|
||||
}
|
||||
|
||||
void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size, unsigned int config_high) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
|
||||
if (keyslot >= KEYSLOT_AES_MAX) {
|
||||
generic_panic();
|
||||
}
|
||||
|
||||
/* Generate the derived key, to be XOR'd with final output block. */
|
||||
uint8_t ALIGN(16) derived_key[0x10] = {0};
|
||||
se_aes_ecb_encrypt_block(keyslot, derived_key, sizeof(derived_key), derived_key, sizeof(derived_key), config_high);
|
||||
shift_left_xor_rb(derived_key);
|
||||
if (data_size & 0xF) {
|
||||
shift_left_xor_rb(derived_key);
|
||||
}
|
||||
|
||||
se->CONFIG_REG = (ALG_AES_ENC | DST_HASHREG) | (config_high << 16);
|
||||
se->CRYPTO_REG = (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;
|
||||
trigger_se_blocking_op(OP_START, NULL, 0, data, data_size);
|
||||
se->CRYPTO_REG |= 0x80;
|
||||
}
|
||||
|
||||
/* Create final block. */
|
||||
uint8_t ALIGN(16) last_block[0x10] = {0};
|
||||
if (data_size & 0xF) {
|
||||
memcpy(last_block, data + (data_size & ~0xF), data_size & 0xF);
|
||||
last_block[data_size & 0xF] = 0x80; /* Last block = data || 100...0 */
|
||||
} else if (data_size >= 0x10) {
|
||||
memcpy(last_block, data + data_size - 0x10, 0x10);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < 0x10; i++) {
|
||||
last_block[i] ^= derived_key[i];
|
||||
}
|
||||
|
||||
/* Perform last operation. */
|
||||
se->BLOCK_COUNT_REG = 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);
|
||||
}
|
||||
}
|
||||
|
||||
void se_compute_aes_128_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size) {
|
||||
se_compute_aes_cmac(keyslot, cmac, cmac_size, data, data_size, 0);
|
||||
}
|
||||
void se_compute_aes_256_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size) {
|
||||
se_compute_aes_cmac(keyslot, cmac, cmac_size, data, data_size, 0x202);
|
||||
}
|
||||
|
||||
void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *iv) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
|
||||
if (keyslot >= KEYSLOT_AES_MAX || src_size < 0x10) {
|
||||
generic_panic();
|
||||
}
|
||||
|
||||
se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY) | (0x202 << 16);
|
||||
se->CRYPTO_REG = (keyslot << 24) | 0x144;
|
||||
set_aes_keyslot_iv(keyslot, iv, 0x10);
|
||||
se->BLOCK_COUNT_REG = (src_size >> 4) - 1;
|
||||
trigger_se_blocking_op(OP_START, dst, dst_size, src, src_size);
|
||||
}
|
||||
|
||||
/* SHA256 Implementation. */
|
||||
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;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
||||
/* RNG API */
|
||||
void se_initialize_rng(unsigned int keyslot) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
|
||||
if (keyslot >= KEYSLOT_AES_MAX) {
|
||||
generic_panic();
|
||||
}
|
||||
|
||||
/* To initialize the RNG, we'll perform an RNG operation into an output buffer. */
|
||||
/* 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;
|
||||
trigger_se_blocking_op(OP_START, output_buf, 0x10, NULL, 0);
|
||||
}
|
||||
|
||||
void se_generate_random(unsigned int keyslot, void *dst, size_t size) {
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
|
||||
if (keyslot >= KEYSLOT_AES_MAX) {
|
||||
generic_panic();
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (num_blocks >= 1) {
|
||||
se->BLOCK_COUNT_REG = num_blocks - 1;
|
||||
trigger_se_blocking_op(OP_START, dst, aligned_size, NULL, 0);
|
||||
}
|
||||
if (size > aligned_size) {
|
||||
se_perform_aes_block_operation(dst + aligned_size, size - aligned_size, NULL, 0);
|
||||
}
|
||||
}
|
||||
219
sept/sept-primary/src/se.h
Normal file
219
sept/sept-primary/src/se.h
Normal file
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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_SE_H
|
||||
#define FUSEE_SE_H
|
||||
|
||||
#define SE_BASE 0x70012000
|
||||
#define MAKE_SE_REG(n) MAKE_REG32(SE_BASE + n)
|
||||
|
||||
#define KEYSLOT_SWITCH_LP0TZRAMKEY 0x2
|
||||
#define KEYSLOT_SWITCH_SRKGENKEY 0x8
|
||||
#define KEYSLOT_SWITCH_PACKAGE2KEY 0x8
|
||||
#define KEYSLOT_SWITCH_TEMPKEY 0x9
|
||||
#define KEYSLOT_SWITCH_SESSIONKEY 0xA
|
||||
#define KEYSLOT_SWITCH_RNGKEY 0xB
|
||||
#define KEYSLOT_SWITCH_MASTERKEY 0xC
|
||||
#define KEYSLOT_SWITCH_DEVICEKEY 0xD
|
||||
|
||||
/* This keyslot was added in 4.0.0. */
|
||||
#define KEYSLOT_SWITCH_4XNEWDEVICEKEYGENKEY 0xD
|
||||
#define KEYSLOT_SWITCH_4XNEWCONSOLEKEYGENKEY 0xE
|
||||
#define KEYSLOT_SWITCH_4XOLDDEVICEKEY 0xF
|
||||
|
||||
/* This keyslot was added in 5.0.0. */
|
||||
#define KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY 0xA
|
||||
|
||||
#define KEYSLOT_AES_MAX 0x10
|
||||
#define KEYSLOT_RSA_MAX 0x2
|
||||
|
||||
#define KEYSIZE_AES_MAX 0x20
|
||||
#define KEYSIZE_RSA_MAX 0x100
|
||||
|
||||
#define ALG_SHIFT (12)
|
||||
#define ALG_DEC_SHIFT (8)
|
||||
#define ALG_NOP (0 << ALG_SHIFT)
|
||||
#define ALG_AES_ENC (1 << ALG_SHIFT)
|
||||
#define ALG_AES_DEC ((1 << ALG_DEC_SHIFT) | ALG_NOP)
|
||||
#define ALG_RNG (2 << ALG_SHIFT)
|
||||
#define ALG_SHA (3 << ALG_SHIFT)
|
||||
#define ALG_RSA (4 << ALG_SHIFT)
|
||||
|
||||
#define DST_SHIFT (2)
|
||||
#define DST_MEMORY (0 << DST_SHIFT)
|
||||
#define DST_HASHREG (1 << DST_SHIFT)
|
||||
#define DST_KEYTAB (2 << DST_SHIFT)
|
||||
#define DST_SRK (3 << DST_SHIFT)
|
||||
#define DST_RSAREG (4 << DST_SHIFT)
|
||||
|
||||
#define ENCMODE_SHIFT (24)
|
||||
#define DECMODE_SHIFT (16)
|
||||
#define ENCMODE_SHA256 (5 << ENCMODE_SHIFT)
|
||||
|
||||
#define HASH_DISABLE (0x0)
|
||||
#define HASH_ENABLE (0x1)
|
||||
|
||||
#define OP_ABORT 0
|
||||
#define OP_START 1
|
||||
#define OP_RESTART 2
|
||||
#define OP_CTX_SAVE 3
|
||||
#define OP_RESTART_IN 4
|
||||
|
||||
#define CTX_SAVE_SRC_SHIFT 29
|
||||
#define CTX_SAVE_SRC_STICKY_BITS (0 << CTX_SAVE_SRC_SHIFT)
|
||||
#define CTX_SAVE_SRC_KEYTABLE_AES (2 << CTX_SAVE_SRC_SHIFT)
|
||||
#define CTX_SAVE_SRC_KEYTABLE_RSA (1 << CTX_SAVE_SRC_SHIFT)
|
||||
#define CTX_SAVE_SRC_MEM (4 << CTX_SAVE_SRC_SHIFT)
|
||||
#define CTX_SAVE_SRC_SRK (6 << CTX_SAVE_SRC_SHIFT)
|
||||
|
||||
#define CTX_SAVE_KEY_LOW_BITS 0
|
||||
#define CTX_SAVE_KEY_HIGH_BITS 1
|
||||
#define CTX_SAVE_KEY_ORIGINAL_IV 2
|
||||
#define CTX_SAVE_KEY_UPDATED_IV 3
|
||||
|
||||
#define CTX_SAVE_STICKY_BIT_INDEX_SHIFT 24
|
||||
#define CTX_SAVE_KEY_INDEX_SHIFT 8
|
||||
#define CTX_SAVE_RSA_KEY_INDEX_SHIFT 16
|
||||
#define CTX_SAVE_RSA_KEY_BLOCK_INDEX_SHIFT 12
|
||||
|
||||
#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 _0x814;
|
||||
uint32_t _0x818;
|
||||
uint32_t _0x81C;
|
||||
uint8_t _0x820[0x17E0];
|
||||
} tegra_se_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t address;
|
||||
uint32_t size;
|
||||
} se_addr_info_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t num_entries; /* Set to total entries - 1 */
|
||||
se_addr_info_t addr_info; /* This should really be an array...but for our use case it works. */
|
||||
} se_ll_t;
|
||||
|
||||
static inline volatile tegra_se_t *se_get_regs(void) {
|
||||
return (volatile tegra_se_t *)SE_BASE;
|
||||
}
|
||||
|
||||
void se_check_error_status_reg(void);
|
||||
void se_check_for_error(void);
|
||||
void se_trigger_interrupt(void);
|
||||
|
||||
void se_validate_stored_vector(void);
|
||||
void se_generate_stored_vector(void);
|
||||
|
||||
void se_verify_flags_cleared(void);
|
||||
|
||||
void set_aes_keyslot_flags(unsigned int keyslot, unsigned int flags);
|
||||
void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags);
|
||||
void clear_aes_keyslot(unsigned int keyslot);
|
||||
void clear_rsa_keyslot(unsigned int keyslot);
|
||||
|
||||
void set_aes_keyslot(unsigned int keyslot, const void *key, size_t key_size);
|
||||
void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_src, const void *wrapped_key, size_t wrapped_key_size);
|
||||
void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_size, const void *exponent, size_t exp_size);
|
||||
void set_aes_keyslot_iv(unsigned int keyslot, const void *iv, size_t iv_size);
|
||||
void set_se_ctr(const void *ctr);
|
||||
|
||||
/* Secure AES API */
|
||||
void se_aes_128_xts_nintendo_decrypt(unsigned int keyslot_1, unsigned int keyslot_2, unsigned int base_sector, void *dst, const void *src, size_t size, unsigned int sector_size);
|
||||
void se_aes_128_xts_nintendo_encrypt(unsigned int keyslot_1, unsigned int keyslot_2, unsigned int base_sector, void *dst, const void *src, size_t size, unsigned int sector_size);
|
||||
void se_compute_aes_128_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size);
|
||||
void se_compute_aes_256_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size);
|
||||
void se_aes_128_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size);
|
||||
void se_aes_256_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size);
|
||||
void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *ctr, size_t ctr_size);
|
||||
void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size);
|
||||
void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *iv);
|
||||
|
||||
/* Hash API */
|
||||
void se_calculate_sha256(void *dst, const void *src, size_t src_size);
|
||||
|
||||
/* RSA API */
|
||||
void se_get_exp_mod_output(void *buf, size_t size);
|
||||
void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size);
|
||||
bool se_rsa2048_pss_verify(const void *signature, size_t signature_size, const void *modulus, size_t modulus_size, const void *data, size_t data_size);
|
||||
|
||||
/* RNG API */
|
||||
void se_initialize_rng(unsigned int keyslot);
|
||||
void se_generate_random(unsigned int keyslot, void *dst, size_t size);
|
||||
|
||||
#endif
|
||||
100
sept/sept-primary/src/start.s
Normal file
100
sept/sept-primary/src/start.s
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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/>.
|
||||
*/
|
||||
|
||||
.section .text.start, "ax", %progbits
|
||||
.arm
|
||||
.align 5
|
||||
.global _start
|
||||
.type _start, %function
|
||||
_start:
|
||||
/* Set coldboot */
|
||||
mov r0, #0x0
|
||||
ldr r1, =0x7000E400
|
||||
str r0, [r1, #0x50]
|
||||
|
||||
/* Tell pk1ldr normal reboot, no error */
|
||||
str r0, [r1, #0x1B4]
|
||||
str r0, [r1, #0x840]
|
||||
|
||||
/* Cleanup SVC handler address. */
|
||||
ldr r0, =0x40004C30
|
||||
ldr r1, =0x6000F208
|
||||
str r0, [r1]
|
||||
|
||||
/* Disable RCM forcefully */
|
||||
mov r0, #0x4
|
||||
ldr r1, =0x15DC
|
||||
ldr r2, =0xE020
|
||||
bl ipatch_word
|
||||
|
||||
/* Patch BCT signature check */
|
||||
mov r0, #0x5
|
||||
ldr r1, =0x4AEE
|
||||
ldr r2, =0xE05B
|
||||
bl ipatch_word
|
||||
|
||||
/* Patch bootloader read */
|
||||
mov r0, #0x6
|
||||
ldr r1, =0x4E88
|
||||
ldr r2, =0xE018
|
||||
bl ipatch_word
|
||||
|
||||
ldr r0, =__main_phys_start__
|
||||
ldr r1, =__main_start__
|
||||
mov r2, #0x0
|
||||
ldr r3, =(__main_size__)
|
||||
copy_panic_payload:
|
||||
ldr r4, [r0, r2]
|
||||
str r4, [r1, r2]
|
||||
add r2, r2, #0x4
|
||||
cmp r2, r3
|
||||
bne copy_panic_payload
|
||||
|
||||
|
||||
|
||||
/* Jump back to bootrom start. */
|
||||
ldr r0, =0x101010
|
||||
bx r0
|
||||
|
||||
/* Unused, but forces inclusion in binary. */
|
||||
b main
|
||||
|
||||
|
||||
.section .text.ipatch_word, "ax", %progbits
|
||||
.arm
|
||||
.align 5
|
||||
.global ipatch_word
|
||||
.type ipatch_word, %function
|
||||
ipatch_word:
|
||||
ldr r3, =0x6001dc00
|
||||
lsl r0, r0, #0x2
|
||||
lsr r1, r1, #0x1
|
||||
lsl r1, r1, #0x10
|
||||
orr r1, r1, r2
|
||||
str r1, [r3, r0]
|
||||
bx lr
|
||||
|
||||
.section .text.jump_to_main, "ax", %progbits
|
||||
.arm
|
||||
.align 5
|
||||
.global jump_to_main
|
||||
.type jump_to_main, %function
|
||||
jump_to_main:
|
||||
/* Just jump to main */
|
||||
ldr sp, =__stack_top__
|
||||
b main
|
||||
|
||||
|
||||
48
sept/sept-primary/src/sysreg.h
Normal file
48
sept/sept-primary/src/sysreg.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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_SYSREG_H
|
||||
#define FUSEE_SYSREG_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define SYSREG_BASE 0x6000C000
|
||||
#define SB_BASE (SYSREG_BASE + 0x200)
|
||||
#define EXCP_VEC_BASE 0x6000F000
|
||||
|
||||
#define MAKE_SYSREG(n) MAKE_REG32(SYSREG_BASE + n)
|
||||
#define MAKE_SB_REG(n) MAKE_REG32(SB_BASE + n)
|
||||
#define MAKE_EXCP_VEC_REG(n) MAKE_REG32(EXCP_VEC_BASE + n)
|
||||
|
||||
#define AHB_ARBITRATION_DISABLE_0 MAKE_SYSREG(0x004)
|
||||
#define AHB_ARBITRATION_XBAR_CTRL_0 MAKE_SYSREG(0x0E0)
|
||||
#define AHB_AHB_SPARE_REG_0 MAKE_SYSREG(0x110)
|
||||
|
||||
#define SB_CSR_0 MAKE_SB_REG(0x00)
|
||||
#define SB_PIROM_START_0 MAKE_SB_REG(0x04)
|
||||
#define SB_PFCFG_0 MAKE_SB_REG(0x08)
|
||||
#define SB_SECURE_SPAREREG_0_0 MAKE_SB_REG(0x0C)
|
||||
#define SB_SECURE_SPAREREG_1_0 MAKE_SB_REG(0x10)
|
||||
#define SB_SECURE_SPAREREG_2_0 MAKE_SB_REG(0x14)
|
||||
#define SB_SECURE_SPAREREG_3_0 MAKE_SB_REG(0x18)
|
||||
#define SB_SECURE_SPAREREG_4_0 MAKE_SB_REG(0x1C)
|
||||
#define SB_SECURE_SPAREREG_5_0 MAKE_SB_REG(0x20)
|
||||
#define SB_SECURE_SPAREREG_6_0 MAKE_SB_REG(0x24)
|
||||
#define SB_SECURE_SPAREREG_7_0 MAKE_SB_REG(0x28)
|
||||
#define SB_AA64_RESET_LOW_0 MAKE_SB_REG(0x30)
|
||||
#define SB_AA64_RESET_HIGH_0 MAKE_SB_REG(0x34)
|
||||
|
||||
#endif
|
||||
78
sept/sept-primary/src/timers.h
Normal file
78
sept/sept-primary/src/timers.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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_TIMERS_H
|
||||
#define FUSEE_TIMERS_H
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#define TIMERS_BASE 0x60005000
|
||||
#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 0x7000E000
|
||||
#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;
|
||||
uint32_t COMMAND;
|
||||
uint32_t PATTERN;
|
||||
} watchdog_timers_t;
|
||||
|
||||
#define GET_WDT(n) ((volatile watchdog_timers_t *)(TIMERS_BASE + 0x100 + 0x20 * n))
|
||||
#define WDT_REBOOT_PATTERN 0xC45A
|
||||
#define GET_WDT_REBOOT_CFG_REG(n) MAKE_REG32(TIMERS_BASE + 0x60 + 0x8 * n)
|
||||
|
||||
void wait(uint32_t microseconds);
|
||||
|
||||
static inline uint32_t get_time_us(void) {
|
||||
return TIMERUS_CNTR_1US_0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
__attribute__ ((noreturn)) void watchdog_reboot(void);
|
||||
|
||||
#endif
|
||||
119
sept/sept-primary/src/tsec.h
Normal file
119
sept/sept-primary/src/tsec.h
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 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_TSEC_H_
|
||||
#define FUSEE_TSEC_H_
|
||||
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define TSEC_BASE 0x54500000
|
||||
#define SOR1_BASE 0x54580000
|
||||
|
||||
#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)
|
||||
|
||||
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;
|
||||
uint32_t FALCON_PM_SIGNAL;
|
||||
uint32_t FALCON_PM_MODE;
|
||||
uint32_t FALCON_DEBUG1;
|
||||
uint32_t FALCON_DEBUGINFO;
|
||||
uint32_t FALCON_BREAKPOINT0;
|
||||
uint32_t FALCON_BREAKPOINT1;
|
||||
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[0x1430-0x1244]; /* Ignore non Falcon registers. */
|
||||
uint32_t TSEC_SCP_INSN_STAT;
|
||||
uint8_t _0x1434[0x1244+0x5F8-0x1434]; /* Ignore non Falcon registers. */
|
||||
} tegra_tsec_t;
|
||||
|
||||
static inline volatile tegra_tsec_t *tsec_get_regs(void)
|
||||
{
|
||||
return (volatile tegra_tsec_t *)TSEC_BASE;
|
||||
}
|
||||
|
||||
#endif
|
||||
105
sept/sept-primary/src/utils.c
Normal file
105
sept/sept-primary/src/utils.c
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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 <stdbool.h>
|
||||
#include <stdarg.h>
|
||||
#include "utils.h"
|
||||
#include "se.h"
|
||||
#include "fuse.h"
|
||||
#include "pmc.h"
|
||||
#include "timers.h"
|
||||
#include "panic.h"
|
||||
#include "car.h"
|
||||
#include "btn.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#define u8 uint8_t
|
||||
#define u32 uint32_t
|
||||
#include "rebootstub_bin.h"
|
||||
#undef u8
|
||||
#undef u32
|
||||
|
||||
void wait(uint32_t microseconds) {
|
||||
uint32_t old_time = TIMERUS_CNTR_1US_0;
|
||||
while (TIMERUS_CNTR_1US_0 - old_time <= microseconds) {
|
||||
/* Spin-lock. */
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) void watchdog_reboot(void) {
|
||||
volatile watchdog_timers_t *wdt = GET_WDT(4);
|
||||
wdt->PATTERN = WDT_REBOOT_PATTERN;
|
||||
wdt->COMMAND = 2; /* Disable Counter. */
|
||||
GET_WDT_REBOOT_CFG_REG(4) = 0xC0000000;
|
||||
wdt->CONFIG = 0x8019; /* Full System Reset after Fourth Counter expires, using TIMER(9). */
|
||||
wdt->COMMAND = 1; /* Enable Counter. */
|
||||
while (true) {
|
||||
/* Wait for reboot. */
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) void pmc_reboot(uint32_t scratch0) {
|
||||
APBDEV_PMC_SCRATCH0_0 = scratch0;
|
||||
|
||||
/* Reset the processor. */
|
||||
APBDEV_PMC_CONTROL = BIT(4);
|
||||
|
||||
while (true) {
|
||||
/* Wait for reboot. */
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) void reboot_to_self(void) {
|
||||
/* Patch SDRAM init to perform an SVC immediately after second write */
|
||||
APBDEV_PMC_SCRATCH45_0 = 0x2E38DFFF;
|
||||
APBDEV_PMC_SCRATCH46_0 = 0x6001DC28;
|
||||
/* Set SVC handler to jump to reboot stub in IRAM. */
|
||||
APBDEV_PMC_SCRATCH33_0 = 0x4003F000;
|
||||
APBDEV_PMC_SCRATCH40_0 = 0x6000F208;
|
||||
|
||||
/* Copy reboot stub into IRAM high. */
|
||||
for (size_t i = 0; i < rebootstub_bin_size; i += sizeof(uint32_t)) {
|
||||
write32le((void *)0x4003F000, i, read32le(rebootstub_bin, i));
|
||||
}
|
||||
|
||||
/* Trigger warm reboot. */
|
||||
pmc_reboot(1 << 0);
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) void wait_for_button_and_reboot(void) {
|
||||
uint32_t button;
|
||||
while (true) {
|
||||
button = btn_read();
|
||||
if (button & BTN_POWER) {
|
||||
reboot_to_self();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__ ((noreturn)) void generic_panic(void) {
|
||||
panic(0xFF000006);
|
||||
}
|
||||
|
||||
__attribute__((noinline)) bool overlaps(uint64_t as, uint64_t ae, uint64_t bs, uint64_t be)
|
||||
{
|
||||
if(as <= bs && bs <= ae)
|
||||
return true;
|
||||
if(bs <= as && as <= be)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
129
sept/sept-primary/src/utils.h
Normal file
129
sept/sept-primary/src/utils.h
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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_UTILS_H
|
||||
#define FUSEE_UTILS_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#define BIT(n) (1u << (n))
|
||||
#define BITL(n) (1ull << (n))
|
||||
#define MASK(n) (BIT(n) - 1)
|
||||
#define MASKL(n) (BITL(n) - 1)
|
||||
#define MASK2(a,b) (MASK(a) & ~MASK(b))
|
||||
#define MASK2L(a,b) (MASKL(a) & ~MASKL(b))
|
||||
|
||||
#define MAKE_REG32(a) (*(volatile uint32_t *)(a))
|
||||
|
||||
#define ALIGN(m) __attribute__((aligned(m)))
|
||||
#define PACKED __attribute__((packed))
|
||||
|
||||
#define ALINLINE __attribute__((always_inline))
|
||||
#define NOINLINE __attribute__((noinline))
|
||||
|
||||
#define SET_SYSREG(reg, val) do { temp_reg = (val); __asm__ __volatile__ ("msr " #reg ", %0" :: "r"(temp_reg) : "memory"); } while(false)
|
||||
|
||||
static inline uintptr_t get_physical_address(const void *addr) {
|
||||
return (uintptr_t)addr;
|
||||
}
|
||||
|
||||
static inline uint32_t read32le(const volatile void *dword, size_t offset) {
|
||||
uintptr_t addr = (uintptr_t)dword + offset;
|
||||
volatile uint32_t *target = (uint32_t *)addr;
|
||||
return *target;
|
||||
}
|
||||
|
||||
static inline uint32_t read32be(const volatile void *dword, size_t offset) {
|
||||
return __builtin_bswap32(read32le(dword, offset));
|
||||
}
|
||||
|
||||
static inline uint64_t read64le(const volatile void *qword, size_t offset) {
|
||||
uintptr_t addr = (uintptr_t)qword + offset;
|
||||
volatile uint64_t *target = (uint64_t *)addr;
|
||||
return *target;
|
||||
}
|
||||
|
||||
static inline uint64_t read64be(const volatile void *qword, size_t offset) {
|
||||
return __builtin_bswap64(read64le(qword, offset));
|
||||
}
|
||||
|
||||
static inline void write32le(volatile void *dword, size_t offset, uint32_t value) {
|
||||
uintptr_t addr = (uintptr_t)dword + offset;
|
||||
volatile uint32_t *target = (uint32_t *)addr;
|
||||
*target = value;
|
||||
}
|
||||
|
||||
static inline void write32be(volatile void *dword, size_t offset, uint32_t value) {
|
||||
write32le(dword, offset, __builtin_bswap32(value));
|
||||
}
|
||||
|
||||
static inline void write64le(volatile void *qword, size_t offset, uint64_t value) {
|
||||
uintptr_t addr = (uintptr_t)qword + offset;
|
||||
volatile uint64_t *target = (uint64_t *)addr;
|
||||
*target = value;
|
||||
}
|
||||
|
||||
static inline void write64be(volatile void *qword, size_t offset, uint64_t value) {
|
||||
write64le(qword, offset, __builtin_bswap64(value));
|
||||
}
|
||||
|
||||
static inline bool check_32bit_additive_overflow(uint32_t a, uint32_t b) {
|
||||
return __builtin_add_overflow_p(a, b, (uint32_t)0);
|
||||
}
|
||||
|
||||
static inline bool check_32bit_address_loadable(uintptr_t addr) {
|
||||
/* FWIW the bootROM forbids loading anything between 0x40000000 and 0x40010000, using it for itself... */
|
||||
return (addr >= 0x40010000u && addr < 0x40040000u) || addr >= 0x80000000u;
|
||||
}
|
||||
|
||||
static inline bool check_32bit_address_range_loadable(uintptr_t addr, size_t size) {
|
||||
return
|
||||
!__builtin_add_overflow_p(addr, size, (uintptr_t)0) && /* the range doesn't overflow */
|
||||
check_32bit_address_loadable(addr) && check_32bit_address_loadable(addr + size) && /* bounds are valid */
|
||||
!(addr >= 0x40010000u && addr < 0x40040000u && addr + size >= 0x40040000u) /* the range doesn't cross MMIO */
|
||||
;
|
||||
}
|
||||
|
||||
bool overlaps(uint64_t as, uint64_t ae, uint64_t bs, uint64_t be);
|
||||
static inline bool overlaps_a(const void *as, const void *ae, const void *bs, const void *be) {
|
||||
return overlaps((uint64_t)(uintptr_t)as, (uint64_t)(uintptr_t)ae, (uint64_t)(uintptr_t)bs, (uint64_t)(uintptr_t)be);
|
||||
}
|
||||
|
||||
static inline bool check_32bit_address_range_in_program(uintptr_t addr, size_t size) {
|
||||
extern uint8_t __chainloader_start__[], __chainloader_end__[];
|
||||
extern uint8_t __stack_bottom__[], __stack_top__[];
|
||||
extern uint8_t __start__[], __end__[];
|
||||
uint8_t *start = (uint8_t *)addr, *end = start + size;
|
||||
|
||||
return overlaps_a(start, end, __chainloader_start__, __chainloader_end__) ||
|
||||
overlaps_a(start, end, __stack_bottom__, __stack_top__) ||
|
||||
overlaps_a(start, end, (void *)0xC0000000, (void *)0xC03C0000) || /* framebuffer */
|
||||
overlaps_a(start, end, __start__, __end__);
|
||||
}
|
||||
|
||||
void hexdump(const void* data, size_t size, uintptr_t addrbase);
|
||||
|
||||
__attribute__((noreturn)) void watchdog_reboot(void);
|
||||
__attribute__((noreturn)) void pmc_reboot(uint32_t scratch0);
|
||||
__attribute__((noreturn)) void reboot_to_self(void);
|
||||
__attribute__((noreturn)) void wait_for_button_and_reboot(void);
|
||||
|
||||
__attribute__((noreturn)) void generic_panic(void);
|
||||
|
||||
#endif
|
||||
7
sept/sept-secondary/KEYS_template.py
Normal file
7
sept/sept-secondary/KEYS_template.py
Normal file
@@ -0,0 +1,7 @@
|
||||
HOVI_ENC_KEY_PRD = bytearray.fromhex('00000000000000000000000000000000')
|
||||
HOVI_ENC_KEY_DEV = bytearray.fromhex('00000000000000000000000000000000')
|
||||
HOVI_SIG_KEY_PRD = bytearray.fromhex('00000000000000000000000000000000')
|
||||
HOVI_SIG_KEY_DEV = bytearray.fromhex('00000000000000000000000000000000')
|
||||
HOVI_KEK_KEY_PRD = bytearray.fromhex('00000000000000000000000000000000')
|
||||
HOVI_KEK_KEY_DEV = bytearray.fromhex('00000000000000000000000000000000')
|
||||
IV = bytearray.fromhex('00000000000000000000000000000000')
|
||||
173
sept/sept-secondary/Makefile
Normal file
173
sept/sept-secondary/Makefile
Normal file
@@ -0,0 +1,173 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
TOPDIR ?= $(CURDIR)
|
||||
|
||||
AMS := $(TOPDIR)/../../
|
||||
include $(DEVKITARM)/base_rules
|
||||
|
||||
AMSBRANCH := $(shell git symbolic-ref --short HEAD)
|
||||
AMSREV := $(AMSBRANCH)-$(shell git rev-parse --short HEAD)
|
||||
|
||||
ifneq (, $(strip $(shell git status --porcelain 2>/dev/null)))
|
||||
AMSREV := $(AMSREV)-dirty
|
||||
endif
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# 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
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := $(notdir $(CURDIR))
|
||||
BUILD := build
|
||||
SOURCES := src src/sdmmc src/lib src/lib/fatfs src/display
|
||||
DATA := data
|
||||
INCLUDES := include ../../common/include
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork
|
||||
DEFINES := -D__BPMP__ -DFUSEE_STAGE1_SRC -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\"
|
||||
|
||||
CFLAGS := \
|
||||
-g \
|
||||
-O2 \
|
||||
-fomit-frame-pointer \
|
||||
-ffunction-sections \
|
||||
-fdata-sections \
|
||||
-std=gnu11 \
|
||||
-Werror \
|
||||
-Wall \
|
||||
-fstrict-volatile-bitfields \
|
||||
$(ARCH) $(DEFINES)
|
||||
|
||||
CFLAGS += $(INCLUDE)
|
||||
|
||||
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
|
||||
|
||||
ASFLAGS := -g $(ARCH)
|
||||
LDFLAGS = -specs=$(TOPDIR)/linker.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||
|
||||
LIBS :=
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS :=
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# 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 OUTPUT := $(CURDIR)/$(TARGET)
|
||||
export TOPDIR := $(CURDIR)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
|
||||
$(AMS)/exosphere/rebootstub
|
||||
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) rebootstub.bin
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# 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$(CURDIR)/$(BUILD)
|
||||
|
||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
|
||||
.PHONY: $(BUILD) clean all check_rebootstub
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
all: check_rebootstub $(BUILD)
|
||||
|
||||
check_rebootstub:
|
||||
@$(MAKE) -C $(AMS)/exosphere/rebootstub all
|
||||
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@$(MAKE) -C $(AMS)/exosphere/rebootstub clean
|
||||
@rm -fr $(BUILD) $(TARGET).bin $(TARGET).elf
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
.PHONY: all $(OUTPUT).enc
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
all : $(OUTPUT).enc
|
||||
|
||||
$(OUTPUT).enc : $(OUTPUT).bin
|
||||
@python $(TOPDIR)/sept_sign.py $< $@
|
||||
@echo built ... $(notdir $@)
|
||||
|
||||
$(OUTPUT).bin : $(OUTPUT).elf
|
||||
$(OBJCOPY) -S -O binary $< $@
|
||||
@echo built ... $(notdir $@)
|
||||
|
||||
$(OUTPUT).elf : $(OFILES)
|
||||
|
||||
%.elf: $(OFILES)
|
||||
@echo linking $(notdir $@)
|
||||
@$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
|
||||
@$(NM) -CSn $@ > $(notdir $*.lst)
|
||||
|
||||
$(OFILES_SRC) : $(HFILES_BIN)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# you need a rule like this for each extension you use as binary data
|
||||
#---------------------------------------------------------------------------------
|
||||
%.bin.o %_bin.h: %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
||||
193
sept/sept-secondary/linker.ld
Normal file
193
sept/sept-secondary/linker.ld
Normal file
@@ -0,0 +1,193 @@
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
ENTRY(_start)
|
||||
|
||||
PHDRS
|
||||
{
|
||||
crt0 PT_LOAD;
|
||||
chainloader PT_LOAD;
|
||||
main PT_LOAD;
|
||||
}
|
||||
|
||||
/* Mostly copied from https://github.com/devkitPro/buildscripts/blob/master/dkarm-eabi/crtls/3dsx.ld */
|
||||
MEMORY
|
||||
{
|
||||
NULL : ORIGIN = 0x00000000, LENGTH = 0x1000
|
||||
main : ORIGIN = 0x40010000, LENGTH = 0x20000
|
||||
low_iram : ORIGIN = 0x40003000, LENGTH = 0x8000
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
PROVIDE(__start__ = 0x40010000);
|
||||
PROVIDE(__stack_top__ = 0x40010000);
|
||||
PROVIDE(__stack_bottom__ = 0x4000C000);
|
||||
PROVIDE(__heap_start__ = 0);
|
||||
PROVIDE(__heap_end__ = 0);
|
||||
|
||||
. = __start__;
|
||||
|
||||
.crt0 :
|
||||
{
|
||||
KEEP( *(.text.start) )
|
||||
KEEP( *(.init) )
|
||||
. = ALIGN(32);
|
||||
} >main :crt0
|
||||
|
||||
.chainloader_loadable :
|
||||
{
|
||||
. = ALIGN(32);
|
||||
PROVIDE (__chainloader_start__ = ABSOLUTE(.));
|
||||
PROVIDE (__chainloader_lma__ = LOADADDR(.chainloader_loadable));
|
||||
KEEP(*(.chainloader.text.start))
|
||||
chainloader.o(.text*)
|
||||
chainloader.o(.rodata*)
|
||||
chainloader.o(.data*)
|
||||
. = ALIGN(32);
|
||||
} >low_iram AT>main :chainloader
|
||||
|
||||
.chainloader_bss (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(32);
|
||||
PROVIDE (__chainloader_bss_start__ = ABSOLUTE(.));
|
||||
chainloader.o(.bss* COMMON)
|
||||
. = ALIGN(32);
|
||||
PROVIDE (__chainloader_end__ = ABSOLUTE(.));
|
||||
} >low_iram :NONE
|
||||
|
||||
.text :
|
||||
{
|
||||
. = ALIGN(32);
|
||||
/* .text */
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
*(.glue_7)
|
||||
*(.glue_7t)
|
||||
*(.stub)
|
||||
*(.gnu.warning)
|
||||
*(.gnu.linkonce.t*)
|
||||
|
||||
/* .fini */
|
||||
KEEP( *(.fini) )
|
||||
. = ALIGN(8);
|
||||
} >main :main
|
||||
|
||||
.rodata :
|
||||
{
|
||||
*(.rodata)
|
||||
*(.roda)
|
||||
*(.rodata.*)
|
||||
*all.rodata*(*)
|
||||
*(.gnu.linkonce.r*)
|
||||
SORT(CONSTRUCTORS)
|
||||
. = ALIGN(8);
|
||||
} >main
|
||||
|
||||
.preinit_array :
|
||||
{
|
||||
PROVIDE (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE (__preinit_array_end = .);
|
||||
} >main
|
||||
|
||||
.init_array ALIGN(4) :
|
||||
{
|
||||
PROVIDE (__init_array_start = .);
|
||||
KEEP (*(SORT(.init_array.*)))
|
||||
KEEP (*(.init_array))
|
||||
PROVIDE (__init_array_end = .);
|
||||
} >main
|
||||
|
||||
.fini_array ALIGN(4) :
|
||||
{
|
||||
PROVIDE (__fini_array_start = .);
|
||||
KEEP (*(.fini_array))
|
||||
KEEP (*(SORT(.fini_array.*)))
|
||||
PROVIDE (__fini_array_end = .);
|
||||
} >main
|
||||
|
||||
.ctors ALIGN(4) :
|
||||
{
|
||||
KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||
} >main
|
||||
|
||||
.dtors ALIGN(4) :
|
||||
{
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||
} >main
|
||||
|
||||
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) __exidx_start = ABSOLUTE(.);} >main
|
||||
ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) __exidx_end = ABSOLUTE(.);} >main
|
||||
|
||||
.data :
|
||||
{
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d*)
|
||||
CONSTRUCTORS
|
||||
. = ALIGN(32);
|
||||
} >main
|
||||
|
||||
.bss (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(32);
|
||||
PROVIDE (__bss_start__ = ABSOLUTE(.));
|
||||
*(.dynbss)
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
*(.gnu.linkonce.b*)
|
||||
*(COMMON)
|
||||
. = ALIGN(32);
|
||||
PROVIDE (__bss_end__ = ABSOLUTE(.));
|
||||
} >main :NONE
|
||||
. = ALIGN(32);
|
||||
__end__ = ABSOLUTE(.) ;
|
||||
|
||||
/* ==================
|
||||
==== Metadata ====
|
||||
================== */
|
||||
|
||||
/* Discard sections that difficult post-processing */
|
||||
/DISCARD/ : { *(.group .comment .note) }
|
||||
|
||||
/* Stabs debugging sections. */
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
|
||||
/* DWARF debug sections.
|
||||
Symbols in the DWARF debugging sections are relative to the beginning
|
||||
of the section so we begin them at 0. */
|
||||
|
||||
/* DWARF 1 */
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
|
||||
/* GNU DWARF 1 extensions */
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
|
||||
/* DWARF 1.1 and DWARF 2 */
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
|
||||
/* DWARF 2 */
|
||||
.debug_info 0 : { *(.debug_info) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
}
|
||||
7
sept/sept-secondary/linker.specs
Normal file
7
sept/sept-secondary/linker.specs
Normal file
@@ -0,0 +1,7 @@
|
||||
%rename link old_link
|
||||
|
||||
*link:
|
||||
%(old_link) -T %:getenv(TOPDIR /linker.ld) --nmagic --gc-sections
|
||||
|
||||
*startfile:
|
||||
crti%O%s crtbegin%O%s
|
||||
78
sept/sept-secondary/sept_sign.py
Normal file
78
sept/sept-secondary/sept_sign.py
Normal file
@@ -0,0 +1,78 @@
|
||||
#!/usr/bin/env python
|
||||
import sys
|
||||
from struct import pack as pk, unpack as up
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.Hash import CMAC
|
||||
try:
|
||||
import KEYS
|
||||
except ImportError:
|
||||
import KEYS_template as KEYS
|
||||
print('Warning: output will not work on 7.0.0+!')
|
||||
|
||||
|
||||
def shift_left_xor_rb(s):
|
||||
if hasattr(int, "from_bytes"):
|
||||
N = int.from_bytes(s, byteorder="big")
|
||||
else:
|
||||
N = int(s.encode('hex'), 16)
|
||||
|
||||
if N & (1 << 127):
|
||||
N = ((N << 1) ^ 0x87) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
|
||||
else:
|
||||
N = ((N << 1) ^ 0x00) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
|
||||
return bytearray.fromhex('%032x' % N)
|
||||
|
||||
|
||||
def sxor(x, y):
|
||||
return bytearray(a^b for a,b in zip(x, y))
|
||||
|
||||
|
||||
def get_last_block_for_desired_mac(key, data, desired_mac):
|
||||
assert len(desired_mac) == 0x10
|
||||
k1 = shift_left_xor_rb(AES.new(key, AES.MODE_ECB).encrypt(bytearray(0x10)))
|
||||
if len(data) & 0xF:
|
||||
k1 = shift_left_xor_rb(k1)
|
||||
data += b'\x80'
|
||||
data += bytearray((0x10 - (len(data) & 0xF)) & 0xF)
|
||||
num_blocks = (len(data) + 0xF) >> 4
|
||||
last_block = sxor(bytearray(AES.new(key, AES.MODE_ECB).decrypt(desired_mac)), bytearray(k1))
|
||||
if len(data) > 0x0:
|
||||
last_block = sxor(last_block, bytearray(AES.new(key, AES.MODE_CBC, bytearray(0x10)).encrypt(data)[-0x10:]))
|
||||
return last_block
|
||||
|
||||
|
||||
def sign_encrypt_code(code, sig_key, enc_key, iv, desired_mac):
|
||||
# Pad with 0x20 of zeroes.
|
||||
code += bytearray(0x20)
|
||||
code_len = len(code)
|
||||
code_len += 0xFFF
|
||||
code_len &= ~0xFFF
|
||||
code += bytearray(code_len - len(code))
|
||||
|
||||
# Add empty trustzone, warmboot segments.
|
||||
code += bytearray(0x1FE0 - 0x10)
|
||||
pk11_hdr = b'PK11' + pk('<IIIIIII', 0x1000, 0, 0, code_len - 0x20, 0, 0x1000, 0)
|
||||
pk11 = pk11_hdr + code
|
||||
enc_pk11 = AES.new(enc_key, AES.MODE_CBC, iv).encrypt(pk11)
|
||||
enc_pk11 = pk('<IIII', len(pk11) + 0x10, 0, 0, 0) + iv + enc_pk11
|
||||
enc_pk11 += get_last_block_for_desired_mac(sig_key, enc_pk11, desired_mac)
|
||||
enc_pk11 += CMAC.new(sig_key, enc_pk11, AES).digest()
|
||||
return enc_pk11
|
||||
|
||||
|
||||
def main(argc, argv):
|
||||
if argc != 3:
|
||||
print('Usage: %s input output' % argv[0])
|
||||
return 1
|
||||
with open(argv[1], 'rb') as f:
|
||||
code = f.read()
|
||||
if len(code) & 0xF:
|
||||
code += bytearray(0x10 - (len(code) & 0xF))
|
||||
# TODO: Support dev unit crypto
|
||||
with open(argv[2], 'wb') as f:
|
||||
f.write(sign_encrypt_code(code, KEYS.HOVI_SIG_KEY_PRD, KEYS.HOVI_ENC_KEY_PRD, KEYS.IV, b'THANKS_NVIDIA_<3'))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(len(sys.argv), sys.argv))
|
||||
81
sept/sept-secondary/src/apb_misc.h
Normal file
81
sept/sept-secondary/src/apb_misc.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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_APB_MISC_H
|
||||
#define FUSEE_APB_MISC_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define APB_MISC_BASE 0x70000000
|
||||
#define APB_PADCTL_BASE 0x70000810
|
||||
#define MAKE_APB_MISC_REG(n) MAKE_REG32(APB_MISC_BASE + n)
|
||||
#define MAKE_APB_PADCTL_REG(n) MAKE_REG32(APB_PADCTL_BASE + n)
|
||||
|
||||
#define APB_MISC_PP_PINMUX_GLOBAL_0 MAKE_APB_MISC_REG(0x40)
|
||||
#define APB_MISC_GP_WIFI_EN_CFGPADCTRL_0 MAKE_APB_MISC_REG(0xB64)
|
||||
#define APB_MISC_GP_WIFI_RST_CFGPADCTRL_0 MAKE_APB_MISC_REG(0xB68)
|
||||
|
||||
#define SDMMC1_PAD_CAL_DRVUP_SHIFT (20)
|
||||
#define SDMMC1_PAD_CAL_DRVDN_SHIFT (12)
|
||||
#define SDMMC1_PAD_CAL_DRVUP_MASK (0x7Fu << SDMMC1_PAD_CAL_DRVUP_SHIFT)
|
||||
#define SDMMC1_PAD_CAL_DRVDN_MASK (0x7Fu << SDMMC1_PAD_CAL_DRVDN_SHIFT)
|
||||
|
||||
#define CFG2TMC_EMMC4_PAD_DRVUP_COMP_SHIFT (8)
|
||||
#define CFG2TMC_EMMC4_PAD_DRVDN_COMP_SHIFT (2)
|
||||
#define CFG2TMC_EMMC4_PAD_DRVUP_COMP_MASK (0x3Fu << CFG2TMC_EMMC4_PAD_DRVUP_COMP_SHIFT)
|
||||
#define CFG2TMC_EMMC4_PAD_DRVDN_COMP_MASK (0x3Fu << CFG2TMC_EMMC4_PAD_DRVDN_COMP_SHIFT)
|
||||
|
||||
#define PADCTL_SDMMC1_DEEP_LOOPBACK (1 << 0)
|
||||
#define PADCTL_SDMMC3_DEEP_LOOPBACK (1 << 0)
|
||||
#define PADCTL_SDMMC2_ENABLE_DATA_IN (0xFF << 8)
|
||||
#define PADCTL_SDMMC2_ENABLE_CLK_IN (0x3 << 4)
|
||||
#define PADCTL_SDMMC2_DEEP_LOOPBACK (1 << 0)
|
||||
#define PADCTL_SDMMC4_ENABLE_DATA_IN (0xFF << 8)
|
||||
#define PADCTL_SDMMC4_ENABLE_CLK_IN (0x3 << 4)
|
||||
#define PADCTL_SDMMC4_DEEP_LOOPBACK (1 << 0)
|
||||
#define PADCTL_SDMMC1_CD_SOURCE (1 << 0)
|
||||
#define PADCTL_SDMMC1_WP_SOURCE (1 << 1)
|
||||
#define PADCTL_SDMMC3_CD_SOURCE (1 << 2)
|
||||
#define PADCTL_SDMMC3_WP_SOURCE (1 << 3)
|
||||
|
||||
typedef struct {
|
||||
uint32_t asdbgreg; /* 0x810 */
|
||||
uint32_t reserved0[0x31];
|
||||
uint32_t sdmmc1_clk_lpbk_control; /* 0x8D4 */
|
||||
uint32_t sdmmc3_clk_lpbk_control; /* 0x8D8 */
|
||||
uint32_t emmc2_pad_cfg_control; /* 0x8DC */
|
||||
uint32_t emmc4_pad_cfg_control; /* 0x8E0 */
|
||||
uint32_t _todo0[0x6E];
|
||||
uint32_t sdmmc1_pad_cfgpadctrl; /* 0xA98 */
|
||||
uint32_t emmc2_pad_cfgpadctrl; /* 0xA9C */
|
||||
uint32_t emmc2_pad_drv_type_cfgpadctrl; /* 0xAA0 */
|
||||
uint32_t emmc2_pad_pupd_cfgpadctrl; /* 0xAA4 */
|
||||
uint32_t _todo1[0x03];
|
||||
uint32_t sdmmc3_pad_cfgpadctrl; /* 0xAB0 */
|
||||
uint32_t emmc4_pad_cfgpadctrl; /* 0xAB4 */
|
||||
uint32_t emmc4_pad_drv_type_cfgpadctrl; /* 0xAB8 */
|
||||
uint32_t emmc4_pad_pupd_cfgpadctrl; /* 0xABC */
|
||||
uint32_t _todo2[0x2E];
|
||||
uint32_t vgpio_gpio_mux_sel; /* 0xB74 */
|
||||
uint32_t qspi_sck_lpbk_control; /* 0xB78 */
|
||||
} tegra_padctl_t;
|
||||
|
||||
static inline volatile tegra_padctl_t *padctl_get_regs(void)
|
||||
{
|
||||
return (volatile tegra_padctl_t *)APB_PADCTL_BASE;
|
||||
}
|
||||
|
||||
#endif
|
||||
82
sept/sept-secondary/src/btn.c
Normal file
82
sept/sept-secondary/src/btn.c
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 CTCaer
|
||||
* Copyright (c) 2018 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 <stdint.h>
|
||||
|
||||
#include "btn.h"
|
||||
#include "i2c.h"
|
||||
#include "gpio.h"
|
||||
#include "timers.h"
|
||||
|
||||
uint32_t btn_read()
|
||||
{
|
||||
uint32_t res = 0;
|
||||
|
||||
if (!gpio_read(GPIO_BUTTON_VOL_DOWN))
|
||||
res |= BTN_VOL_DOWN;
|
||||
|
||||
if (!gpio_read(GPIO_BUTTON_VOL_UP))
|
||||
res |= BTN_VOL_UP;
|
||||
|
||||
uint32_t val = 0;
|
||||
if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, 0x15, &val, 1))
|
||||
{
|
||||
if (val & 0x4)
|
||||
res |= BTN_POWER;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
uint32_t btn_wait()
|
||||
{
|
||||
uint32_t res = 0, btn = btn_read();
|
||||
int pwr = 0;
|
||||
|
||||
if (btn & BTN_POWER)
|
||||
{
|
||||
pwr = 1;
|
||||
btn &= ~BTN_POWER;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
res = btn_read();
|
||||
|
||||
if (!(res & BTN_POWER) && pwr)
|
||||
pwr = 0;
|
||||
else if (pwr)
|
||||
res &= ~BTN_POWER;
|
||||
} while (btn == res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
uint32_t btn_wait_timeout(uint32_t time_ms, uint32_t mask)
|
||||
{
|
||||
uint32_t timeout = get_time_ms() + time_ms;
|
||||
uint32_t res = btn_read() & mask;
|
||||
|
||||
do
|
||||
{
|
||||
if (!(res & mask))
|
||||
res = btn_read() & mask;
|
||||
} while (get_time_ms() < timeout);
|
||||
|
||||
return res;
|
||||
}
|
||||
30
sept/sept-secondary/src/btn.h
Normal file
30
sept/sept-secondary/src/btn.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 CTCaer
|
||||
* Copyright (c) 2018 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_BTN_H_
|
||||
#define FUSEE_BTN_H_
|
||||
|
||||
#define BTN_POWER 0x1
|
||||
#define BTN_VOL_DOWN 0x2
|
||||
#define BTN_VOL_UP 0x4
|
||||
|
||||
uint32_t btn_read();
|
||||
uint32_t btn_wait();
|
||||
uint32_t btn_wait_timeout(uint32_t time_ms, uint32_t mask);
|
||||
|
||||
#endif
|
||||
139
sept/sept-secondary/src/car.c
Normal file
139
sept/sept-secondary/src/car.c
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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 "car.h"
|
||||
#include "timers.h"
|
||||
#include "utils.h"
|
||||
|
||||
static inline uint32_t get_clk_source_reg(CarDevice dev) {
|
||||
switch (dev) {
|
||||
case CARDEVICE_UARTA: return 0x178;
|
||||
case CARDEVICE_UARTB: return 0x17C;
|
||||
case CARDEVICE_UARTC: return 0x1A0;
|
||||
case CARDEVICE_I2C1: return 0x124;
|
||||
case CARDEVICE_I2C5: return 0x128;
|
||||
case CARDEVICE_UNK: return 0;
|
||||
case CARDEVICE_SE: return 0x42C;
|
||||
case CARDEVICE_HOST1X: return 0x180;
|
||||
case CARDEVICE_TSEC: return 0x1F4;
|
||||
case CARDEVICE_SOR_SAFE: return 0;
|
||||
case CARDEVICE_SOR0: return 0;
|
||||
case CARDEVICE_SOR1: return 0x410;
|
||||
case CARDEVICE_KFUSE: return 0;
|
||||
case CARDEVICE_CL_DVFS: return 0;
|
||||
case CARDEVICE_CORESIGHT: return 0x1D4;
|
||||
case CARDEVICE_ACTMON: return 0x3E8;
|
||||
case CARDEVICE_BPMP: return 0;
|
||||
default: generic_panic();
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t get_clk_source_val(CarDevice dev) {
|
||||
switch (dev) {
|
||||
case CARDEVICE_UARTA: return 0;
|
||||
case CARDEVICE_UARTB: return 0;
|
||||
case CARDEVICE_UARTC: return 0;
|
||||
case CARDEVICE_I2C1: return 6;
|
||||
case CARDEVICE_I2C5: return 6;
|
||||
case CARDEVICE_UNK: return 0;
|
||||
case CARDEVICE_SE: return 0;
|
||||
case CARDEVICE_HOST1X: return 4;
|
||||
case CARDEVICE_TSEC: return 0;
|
||||
case CARDEVICE_SOR_SAFE: return 0;
|
||||
case CARDEVICE_SOR0: return 0;
|
||||
case CARDEVICE_SOR1: return 0;
|
||||
case CARDEVICE_KFUSE: return 0;
|
||||
case CARDEVICE_CL_DVFS: return 0;
|
||||
case CARDEVICE_CORESIGHT: return 0;
|
||||
case CARDEVICE_ACTMON: return 6;
|
||||
case CARDEVICE_BPMP: return 0;
|
||||
default: generic_panic();
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t get_clk_source_div(CarDevice dev) {
|
||||
switch (dev) {
|
||||
case CARDEVICE_UARTA: return 0;
|
||||
case CARDEVICE_UARTB: return 0;
|
||||
case CARDEVICE_UARTC: return 0;
|
||||
case CARDEVICE_I2C1: return 0;
|
||||
case CARDEVICE_I2C5: return 0;
|
||||
case CARDEVICE_UNK: return 0;
|
||||
case CARDEVICE_SE: return 0;
|
||||
case CARDEVICE_HOST1X: return 3;
|
||||
case CARDEVICE_TSEC: return 2;
|
||||
case CARDEVICE_SOR_SAFE: return 0;
|
||||
case CARDEVICE_SOR0: return 0;
|
||||
case CARDEVICE_SOR1: return 2;
|
||||
case CARDEVICE_KFUSE: return 0;
|
||||
case CARDEVICE_CL_DVFS: return 0;
|
||||
case CARDEVICE_CORESIGHT: return 4;
|
||||
case CARDEVICE_ACTMON: return 0;
|
||||
case CARDEVICE_BPMP: return 0;
|
||||
default: generic_panic();
|
||||
}
|
||||
}
|
||||
|
||||
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};
|
||||
|
||||
void clk_enable(CarDevice dev) {
|
||||
uint32_t clk_source_reg;
|
||||
if ((clk_source_reg = get_clk_source_reg(dev))) {
|
||||
MAKE_CAR_REG(clk_source_reg) = (get_clk_source_val(dev) << 29) | get_clk_source_div(dev);
|
||||
}
|
||||
MAKE_CAR_REG(g_clk_reg_offsets[dev >> 5]) |= BIT(dev & 0x1F);
|
||||
}
|
||||
|
||||
void clk_disable(CarDevice dev) {
|
||||
MAKE_CAR_REG(g_clk_reg_offsets[dev >> 5]) &= ~(BIT(dev & 0x1F));
|
||||
}
|
||||
|
||||
void rst_enable(CarDevice dev) {
|
||||
MAKE_CAR_REG(g_rst_reg_offsets[dev >> 5]) |= BIT(dev & 0x1F);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void clkrst_disable(CarDevice dev) {
|
||||
rst_enable(dev);
|
||||
clk_disable(dev);
|
||||
}
|
||||
|
||||
void clkrst_reboot(CarDevice dev) {
|
||||
clkrst_disable(dev);
|
||||
if (dev == CARDEVICE_KFUSE) {
|
||||
/* Workaround for KFUSE clock. */
|
||||
clk_enable(dev);
|
||||
udelay(100);
|
||||
rst_disable(dev);
|
||||
udelay(200);
|
||||
} else {
|
||||
clkrst_enable(dev);
|
||||
}
|
||||
}
|
||||
|
||||
void clkrst_enable_fuse_regs(bool enable) {
|
||||
volatile tegra_car_t *car = car_get_regs();
|
||||
car->misc_clk_enb = ((car->misc_clk_enb & 0xEFFFFFFF) | ((enable & 1) << 28));
|
||||
}
|
||||
505
sept/sept-secondary/src/car.h
Normal file
505
sept/sept-secondary/src/car.h
Normal file
@@ -0,0 +1,505 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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_CAR_H
|
||||
#define FUSEE_CAR_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define CAR_BASE 0x60006000
|
||||
#define MAKE_CAR_REG(n) MAKE_REG32(CAR_BASE + n)
|
||||
|
||||
#define CLK_L_SDMMC1 (1 << 14)
|
||||
#define CLK_L_SDMMC2 (1 << 9)
|
||||
#define CLK_U_SDMMC3 (1 << 5)
|
||||
#define CLK_L_SDMMC4 (1 << 15)
|
||||
|
||||
#define CLK_SOURCE_MASK (0b111 << 29)
|
||||
#define CLK_SOURCE_FIRST (0b000 << 29)
|
||||
#define CLK_DIVIDER_MASK (0xff << 0)
|
||||
#define CLK_DIVIDER_UNITY (0x00 << 0)
|
||||
|
||||
#define NUM_CAR_BANKS 7
|
||||
|
||||
/* Clock and reset devices. */
|
||||
typedef enum {
|
||||
CARDEVICE_UARTA = ((0 << 5) | 0x6),
|
||||
CARDEVICE_UARTB = ((0 << 5) | 0x7),
|
||||
CARDEVICE_UARTC = ((1 << 5) | 0x17),
|
||||
CARDEVICE_I2C1 = ((0 << 5) | 0xC),
|
||||
CARDEVICE_I2C5 = ((1 << 5) | 0xF),
|
||||
CARDEVICE_UNK = ((3 << 5) | 0x1E),
|
||||
CARDEVICE_SE = ((3 << 5) | 0x1F),
|
||||
CARDEVICE_HOST1X = ((0 << 5) | 0x1C),
|
||||
CARDEVICE_TSEC = ((2 << 5) | 0x13),
|
||||
CARDEVICE_SOR_SAFE = ((6 << 5) | 0x1E),
|
||||
CARDEVICE_SOR0 = ((5 << 5) | 0x16),
|
||||
CARDEVICE_SOR1 = ((5 << 5) | 0x17),
|
||||
CARDEVICE_KFUSE = ((1 << 5) | 0x8),
|
||||
CARDEVICE_CL_DVFS = ((4 << 5) | 0x1B),
|
||||
CARDEVICE_CORESIGHT = ((2 << 5) | 0x9),
|
||||
CARDEVICE_ACTMON = ((3 << 5) | 0x17),
|
||||
CARDEVICE_BPMP = ((0 << 5) | 0x1)
|
||||
} CarDevice;
|
||||
|
||||
/* Clock/Reset Controller (CLK_RST_CONTROLLER_) regs */
|
||||
typedef struct {
|
||||
uint32_t rst_src; /* _RST_SOURCE_0, 0x00 */
|
||||
|
||||
/* _RST_DEVICES_L/H/U_0 0x4-0xc */
|
||||
uint32_t rst_dev_l;
|
||||
uint32_t rst_dev_h;
|
||||
uint32_t rst_dev_u;
|
||||
|
||||
/* _CLK_OUT_ENB_L/H/U_0 0x10-0x18 */
|
||||
uint32_t clk_out_enb_l;
|
||||
uint32_t clk_out_enb_h;
|
||||
uint32_t clk_out_enb_u;
|
||||
|
||||
uint32_t _0x1C;
|
||||
uint32_t cclk_brst_pol; /* _CCLK_BURST_POLICY_0, 0x20 */
|
||||
uint32_t super_cclk_div; /* _SUPER_CCLK_DIVIDER_0, 0x24 */
|
||||
uint32_t sclk_brst_pol; /* _SCLK_BURST_POLICY_0, 0x28 */
|
||||
uint32_t super_sclk_div; /* _SUPER_SCLK_DIVIDER_0, 0x2c */
|
||||
uint32_t clk_sys_rate; /* _CLK_SYSTEM_RATE_0, 0x30 */
|
||||
uint32_t prog_dly_clk; /* _PROG_DLY_CLK_0, 0x34 */
|
||||
uint32_t aud_sync_clk_rate; /* _AUDIO_SYNC_CLK_RATE_0, 0x38 */
|
||||
uint32_t _0x3C;
|
||||
uint32_t cop_clk_skip_plcy; /* _COP_CLK_SKIP_POLICY_0, 0x40 */
|
||||
uint32_t clk_mask_arm; /* _CLK_MASK_ARM_0, 0x44 */
|
||||
uint32_t misc_clk_enb; /* _MISC_CLK_ENB_0, 0x48 */
|
||||
uint32_t clk_cpu_cmplx; /* _CLK_CPU_CMPLX_0, 0x4c */
|
||||
uint32_t osc_ctrl; /* _OSC_CTRL_0, 0x50 */
|
||||
uint32_t pll_lfsr; /* _PLL_LFSR_0, 0x54 */
|
||||
uint32_t osc_freq_det; /* _OSC_FREQ_DET_0, 0x58 */
|
||||
uint32_t osc_freq_det_stat; /* _OSC_FREQ_DET_STATUS_0, 0x5c */
|
||||
uint32_t _0x60[2];
|
||||
uint32_t plle_ss_cntl; /* _PLLE_SS_CNTL_0, 0x68 */
|
||||
uint32_t plle_misc1; /* _PLLE_MISC1_0, 0x6c */
|
||||
uint32_t _0x70[4];
|
||||
|
||||
/* PLLC 0x80-0x8c */
|
||||
uint32_t pllc_base;
|
||||
uint32_t pllc_out;
|
||||
uint32_t pllc_misc0;
|
||||
uint32_t pllc_misc1;
|
||||
|
||||
/* PLLM 0x90-0x9c */
|
||||
uint32_t pllm_base;
|
||||
uint32_t pllm_out;
|
||||
uint32_t pllm_misc1;
|
||||
uint32_t pllm_misc2;
|
||||
|
||||
/* PLLP 0xa0-0xac */
|
||||
uint32_t pllp_base;
|
||||
uint32_t pllp_outa;
|
||||
uint32_t pllp_outb;
|
||||
uint32_t pllp_misc;
|
||||
|
||||
/* PLLA 0xb0-0xbc */
|
||||
uint32_t plla_base;
|
||||
uint32_t plla_out;
|
||||
uint32_t plla_misc0;
|
||||
uint32_t plla_misc1;
|
||||
|
||||
/* PLLU 0xc0-0xcc */
|
||||
uint32_t pllu_base;
|
||||
uint32_t pllu_out;
|
||||
uint32_t pllu_misc1;
|
||||
uint32_t pllu_misc2;
|
||||
|
||||
/* PLLD 0xd0-0xdc */
|
||||
uint32_t plld_base;
|
||||
uint32_t plld_out;
|
||||
uint32_t plld_misc1;
|
||||
uint32_t plld_misc2;
|
||||
|
||||
/* PLLX 0xe0-0xe4 */
|
||||
uint32_t pllx_base;
|
||||
uint32_t pllx_misc;
|
||||
|
||||
/* PLLE 0xe8-0xf4 */
|
||||
uint32_t plle_base;
|
||||
uint32_t plle_misc;
|
||||
uint32_t plle_ss_cntl1;
|
||||
uint32_t plle_ss_cntl2;
|
||||
|
||||
uint32_t lvl2_clk_gate_ovra; /* _LVL2_CLK_GATE_OVRA_0, 0xf8 */
|
||||
uint32_t lvl2_clk_gate_ovrb; /* _LVL2_CLK_GATE_OVRB_0, 0xfc */
|
||||
|
||||
uint32_t clk_source_i2s2; /* _CLK_SOURCE_I2S2_0, 0x100 */
|
||||
uint32_t clk_source_i2s3; /* _CLK_SOURCE_I2S3_0, 0x104 */
|
||||
uint32_t clk_source_spdif_out; /* _CLK_SOURCE_SPDIF_OUT_0, 0x108 */
|
||||
uint32_t clk_source_spdif_in; /* _CLK_SOURCE_SPDIF_IN_0, 0x10c */
|
||||
uint32_t clk_source_pwm; /* _CLK_SOURCE_PWM_0, 0x110 */
|
||||
uint32_t _0x114;
|
||||
uint32_t clk_source_spi2; /* _CLK_SOURCE_SPI2_0, 0x118 */
|
||||
uint32_t clk_source_spi3; /* _CLK_SOURCE_SPI3_0, 0x11c */
|
||||
uint32_t _0x120;
|
||||
uint32_t clk_source_i2c1; /* _CLK_SOURCE_I2C1_0, 0x124 */
|
||||
uint32_t clk_source_i2c5; /* _CLK_SOURCE_I2C5_0, 0x128 */
|
||||
uint32_t _0x12c[2];
|
||||
uint32_t clk_source_spi1; /* _CLK_SOURCE_SPI1_0, 0x134 */
|
||||
uint32_t clk_source_disp1; /* _CLK_SOURCE_DISP1_0, 0x138 */
|
||||
uint32_t clk_source_disp2; /* _CLK_SOURCE_DISP2_0, 0x13c */
|
||||
uint32_t _0x140;
|
||||
uint32_t clk_source_isp; /* _CLK_SOURCE_ISP_0, 0x144 */
|
||||
uint32_t clk_source_vi; /* _CLK_SOURCE_VI_0, 0x148 */
|
||||
uint32_t _0x14c;
|
||||
uint32_t clk_source_sdmmc1; /* _CLK_SOURCE_SDMMC1_0, 0x150 */
|
||||
uint32_t clk_source_sdmmc2; /* _CLK_SOURCE_SDMMC2_0, 0x154 */
|
||||
uint32_t _0x158[3];
|
||||
uint32_t clk_source_sdmmc4; /* _CLK_SOURCE_SDMMC4_0, 0x164 */
|
||||
uint32_t _0x168[4];
|
||||
uint32_t clk_source_uarta; /* _CLK_SOURCE_UARTA_0, 0x178 */
|
||||
uint32_t clk_source_uartb; /* _CLK_SOURCE_UARTB_0, 0x17c */
|
||||
uint32_t clk_source_host1x; /* _CLK_SOURCE_HOST1X_0, 0x180 */
|
||||
uint32_t _0x184[5];
|
||||
uint32_t clk_source_i2c2; /* _CLK_SOURCE_I2C2_0, 0x198 */
|
||||
uint32_t clk_source_emc; /* _CLK_SOURCE_EMC_0, 0x19c */
|
||||
uint32_t clk_source_uartc; /* _CLK_SOURCE_UARTC_0, 0x1a0 */
|
||||
uint32_t _0x1a4;
|
||||
uint32_t clk_source_vi_sensor; /* _CLK_SOURCE_VI_SENSOR_0, 0x1a8 */
|
||||
uint32_t _0x1ac[2];
|
||||
uint32_t clk_source_spi4; /* _CLK_SOURCE_SPI4_0, 0x1b4 */
|
||||
uint32_t clk_source_i2c3; /* _CLK_SOURCE_I2C3_0, 0x1b8 */
|
||||
uint32_t clk_source_sdmmc3; /* _CLK_SOURCE_SDMMC3_0, 0x1bc */
|
||||
uint32_t clk_source_uartd; /* _CLK_SOURCE_UARTD_0, 0x1c0 */
|
||||
uint32_t _0x1c4[2];
|
||||
uint32_t clk_source_owr; /* _CLK_SOURCE_OWR_0, 0x1cc */
|
||||
uint32_t _0x1d0;
|
||||
uint32_t clk_source_csite; /* _CLK_SOURCE_CSITE_0, 0x1d4 */
|
||||
uint32_t clk_source_i2s1; /* _CLK_SOURCE_I2S1_0, 0x1d8 */
|
||||
uint32_t clk_source_dtv; /* _CLK_SOURCE_DTV_0, 0x1dc */
|
||||
uint32_t _0x1e0[5];
|
||||
uint32_t clk_source_tsec; /* _CLK_SOURCE_TSEC_0, 0x1f4 */
|
||||
uint32_t _0x1f8;
|
||||
|
||||
uint32_t clk_spare2; /* _CLK_SPARE2_0, 0x1fc */
|
||||
uint32_t _0x200[32];
|
||||
|
||||
uint32_t clk_out_enb_x; /* _CLK_OUT_ENB_X_0, 0x280 */
|
||||
uint32_t clk_enb_x_set; /* _CLK_ENB_X_SET_0, 0x284 */
|
||||
uint32_t clk_enb_x_clr; /* _CLK_ENB_X_CLR_0, 0x288 */
|
||||
|
||||
uint32_t rst_devices_x; /* _RST_DEVICES_X_0, 0x28c */
|
||||
uint32_t rst_dev_x_set; /* _RST_DEV_X_SET_0, 0x290 */
|
||||
uint32_t rst_dev_x_clr; /* _RST_DEV_X_CLR_0, 0x294 */
|
||||
|
||||
uint32_t clk_out_enb_y; /* _CLK_OUT_ENB_Y_0, 0x298 */
|
||||
uint32_t clk_enb_y_set; /* _CLK_ENB_Y_SET_0, 0x29c */
|
||||
uint32_t clk_enb_y_clr; /* _CLK_ENB_Y_CLR_0, 0x2a0 */
|
||||
|
||||
uint32_t rst_devices_y; /* _RST_DEVICES_Y_0, 0x2a4 */
|
||||
uint32_t rst_dev_y_set; /* _RST_DEV_Y_SET_0, 0x2a8 */
|
||||
uint32_t rst_dev_y_clr; /* _RST_DEV_Y_CLR_0, 0x2ac */
|
||||
|
||||
uint32_t _0x2b0[17];
|
||||
uint32_t dfll_base; /* _DFLL_BASE_0, 0x2f4 */
|
||||
uint32_t _0x2f8[2];
|
||||
|
||||
/* _RST_DEV_L/H/U_SET_0 0x300-0x314 */
|
||||
uint32_t rst_dev_l_set;
|
||||
uint32_t rst_dev_l_clr;
|
||||
uint32_t rst_dev_h_set;
|
||||
uint32_t rst_dev_h_clr;
|
||||
uint32_t rst_dev_u_set;
|
||||
uint32_t rst_dev_u_clr;
|
||||
|
||||
uint32_t _0x318[2];
|
||||
|
||||
/* _CLK_ENB_L/H/U_CLR_0 0x320-0x334 */
|
||||
uint32_t clk_enb_l_set;
|
||||
uint32_t clk_enb_l_clr;
|
||||
uint32_t clk_enb_h_set;
|
||||
uint32_t clk_enb_h_clr;
|
||||
uint32_t clk_enb_u_set;
|
||||
uint32_t clk_enb_u_clr;
|
||||
|
||||
uint32_t _0x338;
|
||||
uint32_t ccplex_pg_sm_ovrd; /* _CCPLEX_PG_SM_OVRD_0, 0x33c */
|
||||
uint32_t rst_cpu_cmplx_set; /* _RST_CPU_CMPLX_SET_0, 0x340 */
|
||||
uint32_t rst_cpu_cmplx_clr; /* _RST_CPU_CMPLX_CLR_0, 0x344 */
|
||||
|
||||
/* Additional (T30) registers */
|
||||
uint32_t clk_cpu_cmplx_set; /* _CLK_CPU_CMPLX_SET_0, 0x348 */
|
||||
uint32_t clk_cpu_cmplx_clr; /* _CLK_CPU_CMPLX_SET_0, 0x34c */
|
||||
|
||||
uint32_t _0x350[2];
|
||||
uint32_t rst_dev_v; /* _RST_DEVICES_V_0, 0x358 */
|
||||
uint32_t rst_dev_w; /* _RST_DEVICES_W_0, 0x35c */
|
||||
uint32_t clk_out_enb_v; /* _CLK_OUT_ENB_V_0, 0x360 */
|
||||
uint32_t clk_out_enb_w; /* _CLK_OUT_ENB_W_0, 0x364 */
|
||||
uint32_t cclkg_brst_pol; /* _CCLKG_BURST_POLICY_0, 0x368 */
|
||||
uint32_t super_cclkg_div; /* _SUPER_CCLKG_DIVIDER_0, 0x36c */
|
||||
uint32_t cclklp_brst_pol; /* _CCLKLP_BURST_POLICY_0, 0x370 */
|
||||
uint32_t super_cclkp_div; /* _SUPER_CCLKLP_DIVIDER_0, 0x374 */
|
||||
uint32_t clk_cpug_cmplx; /* _CLK_CPUG_CMPLX_0, 0x378 */
|
||||
uint32_t clk_cpulp_cmplx; /* _CLK_CPULP_CMPLX_0, 0x37c */
|
||||
uint32_t cpu_softrst_ctrl; /* _CPU_SOFTRST_CTRL_0, 0x380 */
|
||||
uint32_t cpu_softrst_ctrl1; /* _CPU_SOFTRST_CTRL1_0, 0x384 */
|
||||
uint32_t cpu_softrst_ctrl2; /* _CPU_SOFTRST_CTRL2_0, 0x388 */
|
||||
uint32_t _0x38c[5];
|
||||
uint32_t lvl2_clk_gate_ovrc; /* _LVL2_CLK_GATE_OVRC, 0x3a0 */
|
||||
uint32_t lvl2_clk_gate_ovrd; /* _LVL2_CLK_GATE_OVRD, 0x3a4 */
|
||||
uint32_t _0x3a8[2];
|
||||
|
||||
uint32_t _0x3b0;
|
||||
uint32_t clk_source_mselect; /* _CLK_SOURCE_MSELECT_0, 0x3b4 */
|
||||
uint32_t clk_source_tsensor; /* _CLK_SOURCE_TSENSOR_0, 0x3b8 */
|
||||
uint32_t clk_source_i2s4; /* _CLK_SOURCE_I2S4_0, 0x3bc */
|
||||
uint32_t clk_source_i2s5; /* _CLK_SOURCE_I2S5_0, 0x3c0 */
|
||||
uint32_t clk_source_i2c4; /* _CLK_SOURCE_I2C4_0, 0x3c4 */
|
||||
uint32_t _0x3c8[2];
|
||||
uint32_t clk_source_ahub; /* _CLK_SOURCE_AHUB_0, 0x3d0 */
|
||||
uint32_t _0x3d4[4];
|
||||
uint32_t clk_source_hda2codec_2x; /* _CLK_SOURCE_HDA2CODEC_2X_0, 0x3e4 */
|
||||
uint32_t clk_source_actmon; /* _CLK_SOURCE_ACTMON_0, 0x3e8 */
|
||||
uint32_t clk_source_extperiph1; /* _CLK_SOURCE_EXTPERIPH1_0, 0x3ec */
|
||||
uint32_t clk_source_extperiph2; /* _CLK_SOURCE_EXTPERIPH2_0, 0x3f0 */
|
||||
uint32_t clk_source_extperiph3; /* _CLK_SOURCE_EXTPERIPH3_0, 0x3f4 */
|
||||
uint32_t _0x3f8;
|
||||
uint32_t clk_source_i2c_slow; /* _CLK_SOURCE_I2C_SLOW_0, 0x3fc */
|
||||
uint32_t clk_source_sys; /* _CLK_SOURCE_SYS_0, 0x400 */
|
||||
uint32_t clk_source_ispb; /* _CLK_SOURCE_ISPB_0, 0x404 */
|
||||
uint32_t _0x408[2];
|
||||
uint32_t clk_source_sor1; /* _CLK_SOURCE_SOR1_0, 0x410 */
|
||||
uint32_t clk_source_sor0; /* _CLK_SOURCE_SOR0_0, 0x414 */
|
||||
uint32_t _0x418[2];
|
||||
uint32_t clk_source_sata_oob; /* _CLK_SOURCE_SATA_OOB_0, 0x420 */
|
||||
uint32_t clk_source_sata; /* _CLK_SOURCE_SATA_0, 0x424 */
|
||||
uint32_t clk_source_hda; /* _CLK_SOURCE_HDA_0, 0x428 */
|
||||
uint32_t _0x42c;
|
||||
|
||||
/* _RST_DEV_V/W_SET_0 0x430-0x43c */
|
||||
uint32_t rst_dev_v_set;
|
||||
uint32_t rst_dev_v_clr;
|
||||
uint32_t rst_dev_w_set;
|
||||
uint32_t rst_dev_w_clr;
|
||||
|
||||
/* _CLK_ENB_V/W_CLR_0 0x440-0x44c */
|
||||
uint32_t clk_enb_v_set;
|
||||
uint32_t clk_enb_v_clr;
|
||||
uint32_t clk_enb_w_set;
|
||||
uint32_t clk_enb_w_clr;
|
||||
|
||||
/* Additional (T114+) registers */
|
||||
uint32_t rst_cpug_cmplx_set; /* _RST_CPUG_CMPLX_SET_0, 0x450 */
|
||||
uint32_t rst_cpug_cmplx_clr; /* _RST_CPUG_CMPLX_CLR_0, 0x454 */
|
||||
uint32_t rst_cpulp_cmplx_set; /* _RST_CPULP_CMPLX_SET_0, 0x458 */
|
||||
uint32_t rst_cpulp_cmplx_clr; /* _RST_CPULP_CMPLX_CLR_0, 0x45c */
|
||||
uint32_t clk_cpug_cmplx_set; /* _CLK_CPUG_CMPLX_SET_0, 0x460 */
|
||||
uint32_t clk_cpug_cmplx_clr; /* _CLK_CPUG_CMPLX_CLR_0, 0x464 */
|
||||
uint32_t clk_cpulp_cmplx_set; /* _CLK_CPULP_CMPLX_SET_0, 0x468 */
|
||||
uint32_t clk_cpulp_cmplx_clr; /* _CLK_CPULP_CMPLX_CLR_0, 0x46c */
|
||||
uint32_t cpu_cmplx_status; /* _CPU_CMPLX_STATUS_0, 0x470 */
|
||||
uint32_t _0x474;
|
||||
uint32_t intstatus; /* _INTSTATUS_0, 0x478 */
|
||||
uint32_t intmask; /* _INTMASK_0, 0x47c */
|
||||
uint32_t utmip_pll_cfg0; /* _UTMIP_PLL_CFG0_0, 0x480 */
|
||||
uint32_t utmip_pll_cfg1; /* _UTMIP_PLL_CFG1_0, 0x484 */
|
||||
uint32_t utmip_pll_cfg2; /* _UTMIP_PLL_CFG2_0, 0x488 */
|
||||
|
||||
uint32_t plle_aux; /* _PLLE_AUX_0, 0x48c */
|
||||
uint32_t sata_pll_cfg0; /* _SATA_PLL_CFG0_0, 0x490 */
|
||||
uint32_t sata_pll_cfg1; /* _SATA_PLL_CFG1_0, 0x494 */
|
||||
uint32_t pcie_pll_cfg0; /* _PCIE_PLL_CFG0_0, 0x498 */
|
||||
|
||||
uint32_t prog_audio_dly_clk; /* _PROG_AUDIO_DLY_CLK_0, 0x49c */
|
||||
uint32_t audio_sync_clk_i2s0; /* _AUDIO_SYNC_CLK_I2S0_0, 0x4a0 */
|
||||
uint32_t audio_sync_clk_i2s1; /* _AUDIO_SYNC_CLK_I2S1_0, 0x4a4 */
|
||||
uint32_t audio_sync_clk_i2s2; /* _AUDIO_SYNC_CLK_I2S2_0, 0x4a8 */
|
||||
uint32_t audio_sync_clk_i2s3; /* _AUDIO_SYNC_CLK_I2S3_0, 0x4ac */
|
||||
uint32_t audio_sync_clk_i2s4; /* _AUDIO_SYNC_CLK_I2S4_0, 0x4b0 */
|
||||
uint32_t audio_sync_clk_spdif; /* _AUDIO_SYNC_CLK_SPDIF_0, 0x4b4 */
|
||||
|
||||
uint32_t plld2_base; /* _PLLD2_BASE_0, 0x4b8 */
|
||||
uint32_t plld2_misc; /* _PLLD2_MISC_0, 0x4bc */
|
||||
uint32_t utmip_pll_cfg3; /* _UTMIP_PLL_CFG3_0, 0x4c0 */
|
||||
uint32_t pllrefe_base; /* _PLLREFE_BASE_0, 0x4c4 */
|
||||
uint32_t pllrefe_misc; /* _PLLREFE_MISC_0, 0x4c8 */
|
||||
uint32_t pllrefe_out; /* _PLLREFE_OUT_0, 0x4cc */
|
||||
uint32_t cpu_finetrim_byp; /* _CPU_FINETRIM_BYP_0, 0x4d0 */
|
||||
uint32_t cpu_finetrim_select; /* _CPU_FINETRIM_SELECT_0, 0x4d4 */
|
||||
uint32_t cpu_finetrim_dr; /* _CPU_FINETRIM_DR_0, 0x4d8 */
|
||||
uint32_t cpu_finetrim_df; /* _CPU_FINETRIM_DF_0, 0x4dc */
|
||||
uint32_t cpu_finetrim_f; /* _CPU_FINETRIM_F_0, 0x4e0 */
|
||||
uint32_t cpu_finetrim_r; /* _CPU_FINETRIM_R_0, 0x4e4 */
|
||||
uint32_t pllc2_base; /* _PLLC2_BASE_0, 0x4e8 */
|
||||
uint32_t pllc2_misc0; /* _PLLC2_MISC_0_0, 0x4ec */
|
||||
uint32_t pllc2_misc1; /* _PLLC2_MISC_1_0, 0x4f0 */
|
||||
uint32_t pllc2_misc2; /* _PLLC2_MISC_2_0, 0x4f4 */
|
||||
uint32_t pllc2_misc3; /* _PLLC2_MISC_3_0, 0x4f8 */
|
||||
uint32_t pllc3_base; /* _PLLC3_BASE_0, 0x4fc */
|
||||
uint32_t pllc3_misc0; /* _PLLC3_MISC_0_0, 0x500 */
|
||||
uint32_t pllc3_misc1; /* _PLLC3_MISC_1_0, 0x504 */
|
||||
uint32_t pllc3_misc2; /* _PLLC3_MISC_2_0, 0x508 */
|
||||
uint32_t pllc3_misc3; /* _PLLC3_MISC_3_0, 0x50c */
|
||||
uint32_t pllx_misc1; /* _PLLX_MISC_1_0, 0x510 */
|
||||
uint32_t pllx_misc2; /* _PLLX_MISC_2_0, 0x514 */
|
||||
uint32_t pllx_misc3; /* _PLLX_MISC_3_0, 0x518 */
|
||||
uint32_t xusbio_pll_cfg0; /* _XUSBIO_PLL_CFG0_0, 0x51c */
|
||||
uint32_t xusbio_pll_cfg1; /* _XUSBIO_PLL_CFG0_1, 0x520 */
|
||||
uint32_t plle_aux1; /* _PLLE_AUX1_0, 0x524 */
|
||||
uint32_t pllp_reshift; /* _PLLP_RESHIFT_0, 0x528 */
|
||||
uint32_t utmipll_hw_pwrdn_cfg0; /* _UTMIPLL_HW_PWRDN_CFG0_0, 0x52c */
|
||||
uint32_t pllu_hw_pwrdn_cfg0; /* _PLLU_HW_PWRDN_CFG0_0, 0x530 */
|
||||
uint32_t xusb_pll_cfg0; /* _XUSB_PLL_CFG0_0, 0x534 */
|
||||
uint32_t _0x538;
|
||||
uint32_t clk_cpu_misc; /* _CLK_CPU_MISC_0, 0x53c */
|
||||
uint32_t clk_cpug_misc; /* _CLK_CPUG_MISC_0, 0x540 */
|
||||
uint32_t clk_cpulp_misc; /* _CLK_CPULP_MISC_0, 0x544 */
|
||||
uint32_t pllx_hw_ctrl_cfg; /* _PLLX_HW_CTRL_CFG_0, 0x548 */
|
||||
uint32_t pllx_sw_ramp_cfg; /* _PLLX_SW_RAMP_CFG_0, 0x54c */
|
||||
uint32_t pllx_hw_ctrl_status; /* _PLLX_HW_CTRL_STATUS_0, 0x550 */
|
||||
uint32_t lvl2_clk_gate_ovre; /* _LVL2_CLK_GATE_OVRE, 0x554 */
|
||||
uint32_t super_gr3d_clk_div; /* _SUPER_GR3D_CLK_DIVIDER_0, 0x558 */
|
||||
uint32_t spare_reg0; /* _SPARE_REG0_0, 0x55c */
|
||||
uint32_t audio_sync_clk_dmic1; /* _AUDIO_SYNC_CLK_DMIC1_0, 0x560 */
|
||||
uint32_t audio_sync_clk_dmic2; /* _AUDIO_SYNC_CLK_DMIC2_0, 0x564 */
|
||||
|
||||
uint32_t _0x568[2];
|
||||
uint32_t plld2_ss_cfg; /* _PLLD2_SS_CFG, 0x570 */
|
||||
uint32_t plld2_ss_ctrl1; /* _PLLD2_SS_CTRL1_0, 0x574 */
|
||||
uint32_t plld2_ss_ctrl2; /* _PLLD2_SS_CTRL2_0, 0x578 */
|
||||
uint32_t _0x57c[5];
|
||||
|
||||
uint32_t plldp_base; /* _PLLDP_BASE, 0x590*/
|
||||
uint32_t plldp_misc; /* _PLLDP_MISC, 0x594 */
|
||||
uint32_t plldp_ss_cfg; /* _PLLDP_SS_CFG, 0x598 */
|
||||
uint32_t plldp_ss_ctrl1; /* _PLLDP_SS_CTRL1_0, 0x59c */
|
||||
uint32_t plldp_ss_ctrl2; /* _PLLDP_SS_CTRL2_0, 0x5a0 */
|
||||
uint32_t pllc4_base; /* _PLLC4_BASE_0, 0x5a4 */
|
||||
uint32_t pllc4_misc; /* _PLLC4_MISC_0, 0x5a8 */
|
||||
uint32_t _0x5ac[6];
|
||||
uint32_t clk_spare0; /* _CLK_SPARE0_0, 0x5c4 */
|
||||
uint32_t clk_spare1; /* _CLK_SPARE1_0, 0x5c8 */
|
||||
uint32_t gpu_isob_ctrl; /* _GPU_ISOB_CTRL_0, 0x5cc */
|
||||
uint32_t pllc_misc2; /* _PLLC_MISC_2_0, 0x5d0 */
|
||||
uint32_t pllc_misc3; /* _PLLC_MISC_3_0, 0x5d4 */
|
||||
uint32_t plla_misc2; /* _PLLA_MISC2_0, 0x5d8 */
|
||||
uint32_t _0x5dc[2];
|
||||
uint32_t pllc4_out; /* _PLLC4_OUT_0, 0x5e4 */
|
||||
uint32_t pllmb_base; /* _PLLMB_BASE_0, 0x5e8 */
|
||||
uint32_t pllmb_misc1; /* _PLLMB_MISC1_0, 0x5ec */
|
||||
uint32_t pllx_misc4; /* _PLLX_MISC_4_0, 0x5f0 */
|
||||
uint32_t pllx_misc5; /* _PLLX_MISC_5_0, 0x5f4 */
|
||||
uint32_t _0x5f8[2];
|
||||
|
||||
uint32_t clk_source_xusb_core_host; /* _CLK_SOURCE_XUSB_CORE_HOST_0, 0x600 */
|
||||
uint32_t clk_source_xusb_falcon; /* _CLK_SOURCE_XUSB_FALCON_0, 0x604 */
|
||||
uint32_t clk_source_xusb_fs; /* _CLK_SOURCE_XUSB_FS_0, 0x608 */
|
||||
uint32_t clk_source_xusb_core_dev; /* _CLK_SOURCE_XUSB_CORE_DEV_0, 0x60c */
|
||||
uint32_t clk_source_xusb_ss; /* _CLK_SOURCE_XUSB_SS_0, 0x610 */
|
||||
uint32_t clk_source_cilab; /* _CLK_SOURCE_CILAB_0, 0x614 */
|
||||
uint32_t clk_source_cilcd; /* _CLK_SOURCE_CILCD_0, 0x618 */
|
||||
uint32_t clk_source_cilef; /* _CLK_SOURCE_CILEF_0, 0x61c */
|
||||
uint32_t clk_source_dsia_lp; /* _CLK_SOURCE_DSIA_LP_0, 0x620 */
|
||||
uint32_t clk_source_dsib_lp; /* _CLK_SOURCE_DSIB_LP_0, 0x624 */
|
||||
uint32_t clk_source_entropy; /* _CLK_SOURCE_ENTROPY_0, 0x628 */
|
||||
uint32_t clk_source_dvfs_ref; /* _CLK_SOURCE_DVFS_REF_0, 0x62c */
|
||||
uint32_t clk_source_dvfs_soc; /* _CLK_SOURCE_DVFS_SOC_0, 0x630 */
|
||||
uint32_t _0x634[3];
|
||||
uint32_t clk_source_emc_latency; /* _CLK_SOURCE_EMC_LATENCY_0, 0x640 */
|
||||
uint32_t clk_source_soc_therm; /* _CLK_SOURCE_SOC_THERM_0, 0x644 */
|
||||
uint32_t _0x648;
|
||||
uint32_t clk_source_dmic1; /* _CLK_SOURCE_DMIC1_0, 0x64c */
|
||||
uint32_t clk_source_dmic2; /* _CLK_SOURCE_DMIC2_0, 0x650 */
|
||||
uint32_t _0x654;
|
||||
uint32_t clk_source_vi_sensor2; /* _CLK_SOURCE_VI_SENSOR2_0, 0x658 */
|
||||
uint32_t clk_source_i2c6; /* _CLK_SOURCE_I2C6_0, 0x65c */
|
||||
uint32_t clk_source_mipibif; /* _CLK_SOURCE_MIPIBIF_0, 0x660 */
|
||||
uint32_t clk_source_emc_dll; /* _CLK_SOURCE_EMC_DLL_0, 0x664 */
|
||||
uint32_t _0x668;
|
||||
uint32_t clk_source_uart_fst_mipi_cal; /* _CLK_SOURCE_UART_FST_MIPI_CAL_0, 0x66c */
|
||||
uint32_t _0x670[2];
|
||||
uint32_t clk_source_vic; /* _CLK_SOURCE_VIC_0, 0x678 */
|
||||
|
||||
uint32_t pllp_outc; /* _PLLP_OUTC_0, 0x67c */
|
||||
uint32_t pllp_misc1; /* _PLLP_MISC1_0, 0x680 */
|
||||
uint32_t _0x684[2];
|
||||
uint32_t emc_div_clk_shaper_ctrl; /* _EMC_DIV_CLK_SHAPER_CTRL_0, 0x68c */
|
||||
uint32_t emc_pllc_shaper_ctrl; /* _EMC_PLLC_SHAPER_CTRL_0, 0x690 */
|
||||
|
||||
uint32_t clk_source_sdmmc_legacy_tm; /* _CLK_SOURCE_SDMMC_LEGACY_TM_0, 0x694 */
|
||||
uint32_t clk_source_nvdec; /* _CLK_SOURCE_NVDEC_0, 0x698 */
|
||||
uint32_t clk_source_nvjpg; /* _CLK_SOURCE_NVJPG_0, 0x69c */
|
||||
uint32_t clk_source_nvenc; /* _CLK_SOURCE_NVENC_0, 0x6a0 */
|
||||
|
||||
uint32_t plla1_base; /* _PLLA1_BASE_0, 0x6a4 */
|
||||
uint32_t plla1_misc0; /* _PLLA1_MISC_0_0, 0x6a8 */
|
||||
uint32_t plla1_misc1; /* _PLLA1_MISC_1_0, 0x6ac */
|
||||
uint32_t plla1_misc2; /* _PLLA1_MISC_2_0, 0x6b0 */
|
||||
uint32_t plla1_misc3; /* _PLLA1_MISC_3_0, 0x6b4 */
|
||||
uint32_t audio_sync_clk_dmic3; /* _AUDIO_SYNC_CLK_DMIC3_0, 0x6b8 */
|
||||
|
||||
uint32_t clk_source_dmic3; /* _CLK_SOURCE_DMIC3_0, 0x6bc */
|
||||
uint32_t clk_source_ape; /* _CLK_SOURCE_APE_0, 0x6c0 */
|
||||
uint32_t clk_source_qspi; /* _CLK_SOURCE_QSPI_0, 0x6c4 */
|
||||
uint32_t clk_source_vi_i2c; /* _CLK_SOURCE_VI_I2C_0, 0x6c8 */
|
||||
uint32_t clk_source_usb2_hsic_trk; /* _CLK_SOURCE_USB2_HSIC_TRK_0, 0x6cc */
|
||||
uint32_t clk_source_pex_sata_usb_rx_byp; /* _CLK_SOURCE_PEX_SATA_USB_RX_BYP_0, 0x6d0 */
|
||||
uint32_t clk_source_maud; /* _CLK_SOURCE_MAUD_0, 0x6d4 */
|
||||
uint32_t clk_source_tsecb; /* _CLK_SOURCE_TSECB_0, 0x6d8 */
|
||||
|
||||
uint32_t clk_cpug_misc1; /* _CLK_CPUG_MISC1_0, 0x6dc */
|
||||
uint32_t aclk_burst_policy; /* _ACLK_BURST_POLICY_0, 0x6e0 */
|
||||
uint32_t super_aclk_divider; /* _SUPER_ACLK_DIVIDER_0, 0x6e4 */
|
||||
|
||||
uint32_t nvenc_super_clk_divider; /* _NVENC_SUPER_CLK_DIVIDER_0, 0x6e8 */
|
||||
uint32_t vi_super_clk_divider; /* _VI_SUPER_CLK_DIVIDER_0, 0x6ec */
|
||||
uint32_t vic_super_clk_divider; /* _VIC_SUPER_CLK_DIVIDER_0, 0x6f0 */
|
||||
uint32_t nvdec_super_clk_divider; /* _NVDEC_SUPER_CLK_DIVIDER_0, 0x6f4 */
|
||||
uint32_t isp_super_clk_divider; /* _ISP_SUPER_CLK_DIVIDER_0, 0x6f8 */
|
||||
uint32_t ispb_super_clk_divider; /* _ISPB_SUPER_CLK_DIVIDER_0, 0x6fc */
|
||||
uint32_t nvjpg_super_clk_divider; /* _NVJPG_SUPER_CLK_DIVIDER_0, 0x700 */
|
||||
uint32_t se_super_clk_divider; /* _SE_SUPER_CLK_DIVIDER_0, 0x704 */
|
||||
uint32_t tsec_super_clk_divider; /* _TSEC_SUPER_CLK_DIVIDER_0, 0x708 */
|
||||
uint32_t tsecb_super_clk_divider; /* _TSECB_SUPER_CLK_DIVIDER_0, 0x70c */
|
||||
|
||||
uint32_t clk_source_uartape; /* _CLK_SOURCE_UARTAPE_0, 0x710 */
|
||||
uint32_t clk_cpug_misc2; /* _CLK_CPUG_MISC2_0, 0x714 */
|
||||
uint32_t clk_source_dbgapb; /* _CLK_SOURCE_DBGAPB_0, 0x718 */
|
||||
uint32_t clk_ccplex_cc4_ret_clk_enb; /* _CLK_CCPLEX_CC4_RET_CLK_ENB_0, 0x71c */
|
||||
uint32_t actmon_cpu_clk; /* _ACTMON_CPU_CLK_0, 0x720 */
|
||||
uint32_t clk_source_emc_safe; /* _CLK_SOURCE_EMC_SAFE_0, 0x724 */
|
||||
uint32_t sdmmc2_pllc4_out0_shaper_ctrl; /* _SDMMC2_PLLC4_OUT0_SHAPER_CTRL_0, 0x728 */
|
||||
uint32_t sdmmc2_pllc4_out1_shaper_ctrl; /* _SDMMC2_PLLC4_OUT1_SHAPER_CTRL_0, 0x72c */
|
||||
uint32_t sdmmc2_pllc4_out2_shaper_ctrl; /* _SDMMC2_PLLC4_OUT2_SHAPER_CTRL_0, 0x730 */
|
||||
uint32_t sdmmc2_div_clk_shaper_ctrl; /* _SDMMC2_DIV_CLK_SHAPER_CTRL_0, 0x734 */
|
||||
uint32_t sdmmc4_pllc4_out0_shaper_ctrl; /* _SDMMC4_PLLC4_OUT0_SHAPER_CTRL_0, 0x738 */
|
||||
uint32_t sdmmc4_pllc4_out1_shaper_ctrl; /* _SDMMC4_PLLC4_OUT1_SHAPER_CTRL_0, 0x73c */
|
||||
uint32_t sdmmc4_pllc4_out2_shaper_ctrl; /* _SDMMC4_PLLC4_OUT2_SHAPER_CTRL_0, 0x740 */
|
||||
uint32_t sdmmc4_div_clk_shaper_ctrl; /* _SDMMC4_DIV_CLK_SHAPER_CTRL_0, 0x744 */
|
||||
} tegra_car_t;
|
||||
|
||||
static inline volatile tegra_car_t *car_get_regs(void) {
|
||||
return (volatile tegra_car_t *)CAR_BASE;
|
||||
}
|
||||
|
||||
void clk_enable(CarDevice dev);
|
||||
void clk_disable(CarDevice dev);
|
||||
void rst_enable(CarDevice dev);
|
||||
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
|
||||
51
sept/sept-secondary/src/chainloader.c
Normal file
51
sept/sept-secondary/src/chainloader.c
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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 "chainloader.h"
|
||||
|
||||
int g_chainloader_argc = 0;
|
||||
char g_chainloader_arg_data[CHAINLOADER_ARG_DATA_MAX_SIZE] = {0};
|
||||
chainloader_entry_t g_chainloader_entries[CHAINLOADER_MAX_ENTRIES] = {0}; /* keep them sorted */
|
||||
size_t g_chainloader_num_entries = 0;
|
||||
uintptr_t g_chainloader_entrypoint = 0;
|
||||
|
||||
#pragma GCC optimize (3)
|
||||
|
||||
static void *xmemmove(void *dst, const void *src, size_t len)
|
||||
{
|
||||
const uint8_t *src8 = (const uint8_t *)src;
|
||||
uint8_t *dst8 = (uint8_t *)dst;
|
||||
|
||||
if (dst8 < src8) {
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
dst8[i] = src8[i];
|
||||
}
|
||||
} else if (dst8 > src8) {
|
||||
for (size_t i = len; len > 0; len--)
|
||||
dst8[i - 1] = src8[i - 1];
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
void relocate_and_chainload_main(void) {
|
||||
for(size_t i = 0; i < g_chainloader_num_entries; i++) {
|
||||
chainloader_entry_t *entry = &g_chainloader_entries[i];
|
||||
xmemmove((void *)entry->load_address, (const void *)entry->src_address, entry->size);
|
||||
}
|
||||
|
||||
((void (*)(int, void *))g_chainloader_entrypoint)(g_chainloader_argc, g_chainloader_arg_data);
|
||||
}
|
||||
42
sept/sept-secondary/src/chainloader.h
Normal file
42
sept/sept-secondary/src/chainloader.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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_CHAINLOADER_H
|
||||
#define FUSEE_CHAINLOADER_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define CHAINLOADER_ARG_DATA_MAX_SIZE 0x6200
|
||||
#define CHAINLOADER_MAX_ENTRIES 128
|
||||
|
||||
typedef struct chainloader_entry_t {
|
||||
uintptr_t load_address;
|
||||
uintptr_t src_address;
|
||||
size_t size;
|
||||
size_t num;
|
||||
} chainloader_entry_t;
|
||||
|
||||
extern int g_chainloader_argc;
|
||||
extern chainloader_entry_t g_chainloader_entries[CHAINLOADER_MAX_ENTRIES]; /* keep them sorted */
|
||||
extern size_t g_chainloader_num_entries;
|
||||
extern uintptr_t g_chainloader_entrypoint;
|
||||
|
||||
extern char g_chainloader_arg_data[CHAINLOADER_ARG_DATA_MAX_SIZE];
|
||||
|
||||
void relocate_and_chainload(void);
|
||||
|
||||
#endif
|
||||
267
sept/sept-secondary/src/di.c
Normal file
267
sept/sept-secondary/src/di.c
Normal file
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 CTCaer
|
||||
* Copyright (c) 2018 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 "di.h"
|
||||
#include "timers.h"
|
||||
#include "i2c.h"
|
||||
#include "pmc.h"
|
||||
#include "max77620.h"
|
||||
#include "gpio.h"
|
||||
#include "pinmux.h"
|
||||
#include "car.h"
|
||||
|
||||
#include "di.inl"
|
||||
|
||||
static uint32_t _display_ver = 0;
|
||||
|
||||
static void exec_cfg(uint32_t *base, const cfg_op_t *ops, uint32_t num_ops)
|
||||
{
|
||||
for (uint32_t i = 0; i < num_ops; i++)
|
||||
base[ops[i].off] = ops[i].val;
|
||||
}
|
||||
|
||||
static void _display_dsi_wait(uint32_t timeout, uint32_t off, uint32_t mask)
|
||||
{
|
||||
uint32_t end = get_time_us() + timeout;
|
||||
while ((get_time_us() < end) && (MAKE_DSI_REG(off) & mask)) {
|
||||
/* Wait. */
|
||||
}
|
||||
udelay(5);
|
||||
}
|
||||
|
||||
void display_init()
|
||||
{
|
||||
volatile tegra_car_t *car = car_get_regs();
|
||||
volatile tegra_pmc_t *pmc = pmc_get_regs();
|
||||
volatile tegra_pinmux_t *pinmux = pinmux_get_regs();
|
||||
|
||||
/* Power on. */
|
||||
uint8_t val = 0xD0;
|
||||
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_LDO0_CFG, &val, 1);
|
||||
val = 0x09;
|
||||
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_GPIO7, &val, 1);
|
||||
|
||||
/* Enable MIPI CAL, DSI, DISP1, HOST1X, UART_FST_MIPI_CAL, DSIA LP clocks. */
|
||||
car->rst_dev_h_clr = 0x1010000;
|
||||
car->clk_enb_h_set = 0x1010000;
|
||||
car->rst_dev_l_clr = 0x18000000;
|
||||
car->clk_enb_l_set = 0x18000000;
|
||||
car->clk_enb_x_set = 0x20000;
|
||||
car->clk_source_uart_fst_mipi_cal = 0xA;
|
||||
car->clk_enb_w_set = 0x80000;
|
||||
car->clk_source_dsia_lp = 0xA;
|
||||
|
||||
/* DPD idle. */
|
||||
pmc->io_dpd_req = 0x40000000;
|
||||
pmc->io_dpd2_req = 0x40000000;
|
||||
|
||||
/* Configure pins. */
|
||||
pinmux->nfc_en &= ~PINMUX_TRISTATE;
|
||||
pinmux->nfc_int &= ~PINMUX_TRISTATE;
|
||||
pinmux->lcd_bl_pwm &= ~PINMUX_TRISTATE;
|
||||
pinmux->lcd_bl_en &= ~PINMUX_TRISTATE;
|
||||
pinmux->lcd_rst &= ~PINMUX_TRISTATE;
|
||||
|
||||
/* Configure Backlight +-5V GPIOs. */
|
||||
gpio_configure_mode(GPIO_LCD_BL_P5V, GPIO_MODE_GPIO);
|
||||
gpio_configure_mode(GPIO_LCD_BL_N5V, GPIO_MODE_GPIO);
|
||||
gpio_configure_direction(GPIO_LCD_BL_P5V, GPIO_DIRECTION_OUTPUT);
|
||||
gpio_configure_direction(GPIO_LCD_BL_N5V, GPIO_DIRECTION_OUTPUT);
|
||||
|
||||
/* Enable Backlight +5V. */
|
||||
gpio_write(GPIO_LCD_BL_P5V, GPIO_LEVEL_HIGH);
|
||||
|
||||
udelay(10000);
|
||||
|
||||
/* Enable Backlight -5V. */
|
||||
gpio_write(GPIO_LCD_BL_N5V, GPIO_LEVEL_HIGH);
|
||||
|
||||
udelay(10000);
|
||||
|
||||
/* Configure Backlight PWM, EN and RST GPIOs. */
|
||||
gpio_configure_mode(GPIO_LCD_BL_PWM, GPIO_MODE_GPIO);
|
||||
gpio_configure_mode(GPIO_LCD_BL_EN, GPIO_MODE_GPIO);
|
||||
gpio_configure_mode(GPIO_LCD_BL_RST, GPIO_MODE_GPIO);
|
||||
gpio_configure_direction(GPIO_LCD_BL_PWM, GPIO_DIRECTION_OUTPUT);
|
||||
gpio_configure_direction(GPIO_LCD_BL_EN, GPIO_DIRECTION_OUTPUT);
|
||||
gpio_configure_direction(GPIO_LCD_BL_RST, GPIO_DIRECTION_OUTPUT);
|
||||
|
||||
/* Enable Backlight EN. */
|
||||
gpio_write(GPIO_LCD_BL_EN, GPIO_LEVEL_HIGH);
|
||||
|
||||
/* Configure display interface and display. */
|
||||
MAKE_MIPI_CAL_REG(0x60) = 0;
|
||||
|
||||
exec_cfg((uint32_t *)CAR_BASE, _display_config_1, 4);
|
||||
exec_cfg((uint32_t *)DI_BASE, _display_config_2, 94);
|
||||
exec_cfg((uint32_t *)DSI_BASE, _display_config_3, 60);
|
||||
|
||||
udelay(10000);
|
||||
|
||||
/* Enable Backlight RST. */
|
||||
gpio_write(GPIO_LCD_BL_RST, GPIO_LEVEL_HIGH);
|
||||
|
||||
udelay(60000);
|
||||
|
||||
MAKE_DSI_REG(DSI_BTA_TIMING) = 0x50204;
|
||||
MAKE_DSI_REG(DSI_WR_DATA) = 0x337;
|
||||
MAKE_DSI_REG(DSI_TRIGGER) = DSI_TRIGGER_HOST;
|
||||
_display_dsi_wait(250000, DSI_TRIGGER, (DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO));
|
||||
|
||||
MAKE_DSI_REG(DSI_WR_DATA) = 0x406;
|
||||
MAKE_DSI_REG(DSI_TRIGGER) = DSI_TRIGGER_HOST;
|
||||
_display_dsi_wait(250000, DSI_TRIGGER, (DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO));
|
||||
|
||||
MAKE_DSI_REG(DSI_HOST_CONTROL) = (DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_IMM_BTA | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC);
|
||||
_display_dsi_wait(150000, DSI_HOST_CONTROL, DSI_HOST_CONTROL_IMM_BTA);
|
||||
|
||||
udelay(5000);
|
||||
|
||||
_display_ver = MAKE_DSI_REG(DSI_RD_DATA);
|
||||
|
||||
if (_display_ver == 0x10)
|
||||
exec_cfg((uint32_t *)DSI_BASE, _display_config_4, 43);
|
||||
|
||||
MAKE_DSI_REG(DSI_WR_DATA) = 0x1105;
|
||||
MAKE_DSI_REG(DSI_TRIGGER) = DSI_TRIGGER_HOST;
|
||||
|
||||
udelay(180000);
|
||||
|
||||
MAKE_DSI_REG(DSI_WR_DATA) = 0x2905;
|
||||
MAKE_DSI_REG(DSI_TRIGGER) = DSI_TRIGGER_HOST;
|
||||
|
||||
udelay(20000);
|
||||
|
||||
exec_cfg((uint32_t *)DSI_BASE, _display_config_5, 21);
|
||||
exec_cfg((uint32_t *)CAR_BASE, _display_config_6, 3);
|
||||
|
||||
MAKE_DI_REG(DC_DISP_DISP_CLOCK_CONTROL) = 4;
|
||||
exec_cfg((uint32_t *)DSI_BASE, _display_config_7, 10);
|
||||
|
||||
udelay(10000);
|
||||
|
||||
exec_cfg((uint32_t *)MIPI_CAL_BASE, _display_config_8, 6);
|
||||
exec_cfg((uint32_t *)DSI_BASE, _display_config_9, 4);
|
||||
exec_cfg((uint32_t *)MIPI_CAL_BASE, _display_config_10, 16);
|
||||
|
||||
udelay(10000);
|
||||
|
||||
exec_cfg((uint32_t *)DI_BASE, _display_config_11, 113);
|
||||
}
|
||||
|
||||
void display_backlight(bool enable)
|
||||
{
|
||||
/* Enable Backlight PWM. */
|
||||
gpio_write(GPIO_LCD_BL_PWM, enable ? GPIO_LEVEL_HIGH : GPIO_LEVEL_LOW);
|
||||
}
|
||||
|
||||
void display_end()
|
||||
{
|
||||
volatile tegra_car_t *car = car_get_regs();
|
||||
volatile tegra_pinmux_t *pinmux = pinmux_get_regs();
|
||||
|
||||
/* Disable Backlight. */
|
||||
display_backlight(false);
|
||||
|
||||
MAKE_DSI_REG(DSI_VIDEO_MODE_CONTROL) = 1;
|
||||
MAKE_DSI_REG(DSI_WR_DATA) = 0x2805;
|
||||
|
||||
MAKE_DI_REG(DC_CMD_STATE_ACCESS) = (READ_MUX | WRITE_MUX);
|
||||
MAKE_DSI_REG(DSI_VIDEO_MODE_CONTROL) = 0;
|
||||
|
||||
exec_cfg((uint32_t *)DI_BASE, _display_config_12, 17);
|
||||
exec_cfg((uint32_t *)DSI_BASE, _display_config_13, 16);
|
||||
|
||||
udelay(10000);
|
||||
|
||||
if (_display_ver == 0x10)
|
||||
exec_cfg((uint32_t *)DSI_BASE, _display_config_14, 22);
|
||||
|
||||
MAKE_DSI_REG(DSI_WR_DATA) = 0x1005;
|
||||
MAKE_DSI_REG(DSI_TRIGGER) = DSI_TRIGGER_HOST;
|
||||
|
||||
udelay(50000);
|
||||
|
||||
/* Disable Backlight RST. */
|
||||
gpio_write(GPIO_LCD_BL_RST, GPIO_LEVEL_LOW);
|
||||
|
||||
udelay(10000);
|
||||
|
||||
/* Disable Backlight -5V. */
|
||||
gpio_write(GPIO_LCD_BL_N5V, GPIO_LEVEL_LOW);
|
||||
|
||||
udelay(10000);
|
||||
|
||||
/* Disable Backlight +5V. */
|
||||
gpio_write(GPIO_LCD_BL_P5V, GPIO_LEVEL_LOW);
|
||||
|
||||
udelay(10000);
|
||||
|
||||
/* Disable clocks. */
|
||||
car->rst_dev_h_set = 0x1010000;
|
||||
car->clk_enb_h_clr = 0x1010000;
|
||||
car->rst_dev_l_set = 0x18000000;
|
||||
car->clk_enb_l_clr = 0x18000000;
|
||||
|
||||
MAKE_DSI_REG(DSI_PAD_CONTROL_0) = (DSI_PAD_CONTROL_VS1_PULLDN_CLK | DSI_PAD_CONTROL_VS1_PULLDN(0xF) | DSI_PAD_CONTROL_VS1_PDIO_CLK | DSI_PAD_CONTROL_VS1_PDIO(0xF));
|
||||
MAKE_DSI_REG(DSI_POWER_CONTROL) = 0;
|
||||
|
||||
/* Backlight PWM. */
|
||||
gpio_configure_mode(GPIO_LCD_BL_PWM, GPIO_MODE_SFIO);
|
||||
|
||||
pinmux->lcd_bl_pwm = ((pinmux->lcd_bl_pwm & ~PINMUX_TRISTATE) | PINMUX_TRISTATE);
|
||||
pinmux->lcd_bl_pwm = (((pinmux->lcd_bl_pwm >> 2) << 2) | 1);
|
||||
}
|
||||
|
||||
void display_color_screen(uint32_t color)
|
||||
{
|
||||
exec_cfg((uint32_t *)DI_BASE, cfg_display_one_color, 8);
|
||||
|
||||
/* Configure display to show single color. */
|
||||
MAKE_DI_REG(DC_WIN_AD_WIN_OPTIONS) = 0;
|
||||
MAKE_DI_REG(DC_WIN_BD_WIN_OPTIONS) = 0;
|
||||
MAKE_DI_REG(DC_WIN_CD_WIN_OPTIONS) = 0;
|
||||
MAKE_DI_REG(DC_DISP_BLEND_BACKGROUND_COLOR) = color;
|
||||
MAKE_DI_REG(DC_CMD_STATE_CONTROL) = ((MAKE_DI_REG(DC_CMD_STATE_CONTROL) & 0xFFFFFFFE) | GENERAL_ACT_REQ);
|
||||
|
||||
udelay(35000);
|
||||
|
||||
display_backlight(true);
|
||||
}
|
||||
|
||||
uint32_t *display_init_framebuffer(void *address)
|
||||
{
|
||||
static cfg_op_t conf[sizeof(cfg_display_framebuffer)/sizeof(cfg_op_t)] = {0};
|
||||
if (conf[0].val == 0) {
|
||||
for (uint32_t i = 0; i < sizeof(cfg_display_framebuffer)/sizeof(cfg_op_t); i++) {
|
||||
conf[i] = cfg_display_framebuffer[i];
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t *lfb_addr = (uint32_t *)address;
|
||||
conf[19].val = (uint32_t)address;
|
||||
|
||||
/* This configures the framebuffer @ address with a resolution of 1280x720 (line stride 768). */
|
||||
exec_cfg((uint32_t *)DI_BASE, conf, 32);
|
||||
|
||||
udelay(35000);
|
||||
|
||||
return lfb_addr;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user