mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 20:31:14 +00:00
exosphere: ...
This commit is contained in:
parent
08e1b4d116
commit
3f5f9b60ea
4 changed files with 169 additions and 46 deletions
32
exosphere/src/mc0.h
Normal file
32
exosphere/src/mc0.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 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_MC0_H
|
||||
#define EXOSPHERE_MC0_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "memory_map.h"
|
||||
|
||||
/* Exosphere driver for the Tegra X1 MC0. */
|
||||
|
||||
static inline uintptr_t get_mc0_base(void) {
|
||||
return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_MC0);
|
||||
}
|
||||
|
||||
#define MC0_BASE (get_mc0_base())
|
||||
#define MAKE_MC0_REG(n) MAKE_REG32(MC0_BASE + n)
|
||||
|
||||
#endif
|
32
exosphere/src/mc1.h
Normal file
32
exosphere/src/mc1.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 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_MC0_H
|
||||
#define EXOSPHERE_MC0_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "memory_map.h"
|
||||
|
||||
/* Exosphere driver for the Tegra X1 MC1. */
|
||||
|
||||
static inline uintptr_t get_mc1_base(void) {
|
||||
return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_MC1);
|
||||
}
|
||||
|
||||
#define MC1_BASE (get_mc1_base())
|
||||
#define MAKE_MC1_REG(n) MAKE_REG32(MC1_BASE + n)
|
||||
|
||||
#endif
|
|
@ -13,7 +13,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef EXOSPHERE_MEMORY_MAP_H
|
||||
#define EXOSPHERE_MEMORY_MAP_H
|
||||
|
||||
|
@ -48,9 +48,11 @@
|
|||
#define _MMAPDEV15 ( 0x6000D000ull, 0x1000ull, true ) /* GPIO-1 - GPIO-8 */
|
||||
#define _MMAPDEV16 ( 0x7000C000ull, 0x1000ull, true ) /* I2C-I2C4 */
|
||||
#define _MMAPDEV17 ( 0x6000F000ull, 0x1000ull, true ) /* Exception vectors */
|
||||
#define _MMAPDEV18 ( 0x00000000ull, 0x1000ull, true ) /* AMS irampage, NOT mapped at startup */
|
||||
#define _MMAPDEV19 ( 0x00000000ull, 0x1000ull, true ) /* AMS userpage, NOT mapped at startup */
|
||||
#define _MMAPDEV20 ( 0x40038000ull, 0x5000ull, true ) /* DEBUG: IRAM */
|
||||
#define _MMAPDEV18 ( 0x7001C000ull, 0x1000ull, true ) /* MC0 */
|
||||
#define _MMAPDEV19 ( 0x7001D000ull, 0x1000ull, true ) /* MC1 */
|
||||
#define _MMAPDEV20 ( 0x00000000ull, 0x1000ull, true ) /* AMS irampage, NOT mapped at startup */
|
||||
#define _MMAPDEV21 ( 0x00000000ull, 0x1000ull, true ) /* AMS userpage, NOT mapped at startup */
|
||||
#define _MMAPDEV22 ( 0x40038000ull, 0x1000ull, true ) /* DEBUG: IRAM */
|
||||
|
||||
/* MMIO 7.0.0+. (addr). */
|
||||
#define _MMAPDEV7X0 ( 0x50041000ull ) /* ARM Interrupt Distributor */
|
||||
|
@ -71,9 +73,11 @@
|
|||
#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 */
|
||||
#define _MMAPDEV7X18 ( 0x7001C000ull ) /* MC0 */
|
||||
#define _MMAPDEV7X19 ( 0x7001D000ull ) /* MC1 */
|
||||
#define _MMAPDEV7X20 ( 0x00000000ull ) /* AMS irampage, NOT mapped at startup */
|
||||
#define _MMAPDEV7X21 ( 0x00000000ull ) /* AMS userpage, NOT mapped at startup */
|
||||
#define _MMAPDEV7X22 ( 0x40038000ull ) /* DEBUG: IRAM */
|
||||
|
||||
/* LP0 entry ram segments (addr, size, additional attributes) */
|
||||
#define _MMAPLP0ES0 ( 0x40020000ull, 0x10000ull, MMU_PTE_BLOCK_NS | ATTRIB_MEMTYPE_DEVICE ) /* Encrypted TZRAM */
|
||||
|
@ -133,10 +137,12 @@
|
|||
#define MMIO_DEVID_GPIO 15
|
||||
#define MMIO_DEVID_DTV_I2C234 16
|
||||
#define MMIO_DEVID_EXCEPTION_VECTORS 17
|
||||
#define MMIO_DEVID_AMS_IRAM_PAGE 18
|
||||
#define MMIO_DEVID_AMS_USER_PAGE 19
|
||||
#define MMIO_DEVID_DEBUG_IRAM 20
|
||||
#define MMIO_DEVID_MAX 21
|
||||
#define MMIO_DEVID_MC0 18
|
||||
#define MMIO_DEVID_MC1 19
|
||||
#define MMIO_DEVID_AMS_IRAM_PAGE 20
|
||||
#define MMIO_DEVID_AMS_USER_PAGE 21
|
||||
#define MMIO_DEVID_DEBUG_IRAM 22
|
||||
#define MMIO_DEVID_MAX 23
|
||||
|
||||
#define LP0_ENTRY_RAM_SEGMENT_ID_ENCRYPTED_TZRAM 0
|
||||
#define LP0_ENTRY_RAM_SEGMENT_ID_LP0_ENTRY_CODE 1
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#include "synchronization.h"
|
||||
#include "masterkey.h"
|
||||
#include "mc.h"
|
||||
#include "mc0.h"
|
||||
#include "mc1.h"
|
||||
#include "memory_map.h"
|
||||
#include "pmc.h"
|
||||
#include "randomcache.h"
|
||||
|
@ -617,7 +619,7 @@ uint32_t smc_read_write_register(smc_args_t *args) {
|
|||
}
|
||||
/* Check for PMC registers. */
|
||||
if (0x7000E400 <= address && address <= 0x7000EFFF) {
|
||||
const uint8_t pmc_whitelist[0x28] = {
|
||||
static const uint8_t pmc_whitelist[0x28] = {
|
||||
0xB9, 0xF9, 0x07, 0x00, 0x00, 0x00, 0x80, 0x03,
|
||||
0x00, 0x00, 0x00, 0x17, 0x00, 0xC4, 0x07, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x00,
|
||||
|
@ -633,39 +635,83 @@ uint32_t smc_read_write_register(smc_args_t *args) {
|
|||
} else {
|
||||
return 2;
|
||||
}
|
||||
} else if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400 && MMIO_GET_DEVICE_PA(MMIO_DEVID_MC) <= address &&
|
||||
address < MMIO_GET_DEVICE_PA(MMIO_DEVID_MC) + MMIO_GET_DEVICE_SIZE(MMIO_DEVID_MC)) {
|
||||
/* Memory Controller RW supported only on 4.0.0+ */
|
||||
const uint8_t mc_whitelist[0x68] = {
|
||||
0x9F, 0x31, 0x30, 0x00, 0xF0, 0xFF, 0xF7, 0x01,
|
||||
0xCD, 0xFE, 0xC0, 0xFE, 0x00, 0x00, 0x00, 0x00,
|
||||
0x03, 0x40, 0x73, 0x3E, 0x2F, 0x00, 0x00, 0x6E,
|
||||
0x30, 0x05, 0x06, 0xB0, 0x71, 0xC8, 0x43, 0x04,
|
||||
0x80, 0x1F, 0x08, 0x80, 0x03, 0x00, 0x0E, 0x00,
|
||||
0x08, 0x00, 0xE0, 0x00, 0x0E, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x30, 0xF0, 0x03, 0x03, 0x30,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x31, 0x00, 0x40, 0x00, 0x00,
|
||||
0x00, 0x03, 0x00, 0x00, 0xE4, 0xFF, 0xFF, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0xFE, 0x0F,
|
||||
0x01, 0x00, 0x80, 0x00, 0x00, 0x08, 0x00, 0x00
|
||||
};
|
||||
uint32_t offset = (uint32_t)(address - 0x70019000);
|
||||
uint32_t wl_ind = (offset >> 5);
|
||||
/* If address is whitelisted, allow write. */
|
||||
if (wl_ind < sizeof(mc_whitelist) && (mc_whitelist[wl_ind] & (1 << ((offset >> 2) & 0x7)))) {
|
||||
p_mmio = (volatile uint32_t *)(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_MC) + offset);
|
||||
} else {
|
||||
/* These addresses are not allowed by the whitelist. */
|
||||
/* They correspond to SMMU DISABLE for the BPMP, and for APB-DMA. */
|
||||
/* However, smcReadWriteRegister returns 0 for these addresses despite not actually performing the write. */
|
||||
/* This is "probably" to fuck with hackers who got access to smcReadWriteRegister and are trying to get */
|
||||
/* control of the BPMP for jamais vu etc., since there's no other reason to return 0 despite failure. */
|
||||
if (address == 0x7001923C || address == 0x70019298) {
|
||||
return 0;
|
||||
} else {
|
||||
if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500) {
|
||||
static const uint8_t mc_whitelist_5x[0xD00/(sizeof(uint32_t) * 8)] = {
|
||||
0x9F, 0x31, 0x30, 0x00, 0xF0, 0xFF, 0xF7, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x03, 0x40, 0x73, 0x3E, 0x2F, 0x00, 0x00, 0x6E,
|
||||
0x30, 0x05, 0x06, 0xB0, 0x71, 0xC8, 0x43, 0x04,
|
||||
0x80, 0xFF, 0x08, 0x80, 0x03, 0x38, 0x8E, 0x1F,
|
||||
0xC8, 0xFF, 0xFF, 0x00, 0x0E, 0x00, 0x00, 0x00,
|
||||
0xF0, 0x1F, 0x00, 0x30, 0xF0, 0x03, 0x03, 0x30,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x31, 0x00, 0x40, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xE4, 0xFF, 0xFF, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x0F,
|
||||
0x01, 0x00, 0x80, 0x00, 0x00, 0x08, 0x00, 0x00
|
||||
};
|
||||
static const uint8_t mc01_whitelist_5x[0xC00/(sizeof(uint32_t) * 8)] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xCD, 0xFE, 0xC0, 0xFE, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00,
|
||||
};
|
||||
static const struct {
|
||||
uint32_t phys_addr;
|
||||
uint32_t size;
|
||||
uint64_t virt_addr;
|
||||
const uint8_t *whitelist;
|
||||
} register_whitelists[3] = {
|
||||
{ MMIO_GET_DEVICE_PA(MMIO_DEVID_MC), sizeof(mc_whitelist_5x) * (sizeof(uint32_t) * 8), MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_MC), mc_whitelist_5x },
|
||||
{ MMIO_GET_DEVICE_PA(MMIO_DEVID_MC0), sizeof(mc01_whitelist_5x) * (sizeof(uint32_t) * 8), MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_MC0), mc01_whitelist_5x },
|
||||
{ MMIO_GET_DEVICE_PA(MMIO_DEVID_MC1), sizeof(mc01_whitelist_5x) * (sizeof(uint32_t) * 8), MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_MC1), mc01_whitelist_5x },
|
||||
};
|
||||
for (unsigned int which = 0; which < 3; which++) {
|
||||
if (register_whitelists[which].phys_addr <= address && address < register_whitelists[which].phys_addr + register_whitelists[which].size) {
|
||||
uint32_t offset = (uint32_t)(address - register_whitelists[which].phys_addr);
|
||||
uint32_t wl_ind = (offset >> 5);
|
||||
/* If address is whitelisted, allow write. */
|
||||
if (register_whitelists[which].whitelist[wl_ind] & (1 << ((offset >> 2) & 0x7))) {
|
||||
p_mmio = (volatile uint32_t *)(register_whitelists[which].virt_addr + offset);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) {
|
||||
if (MMIO_GET_DEVICE_PA(MMIO_DEVID_MC) <= address && address < MMIO_GET_DEVICE_PA(MMIO_DEVID_MC) + 0xD00) {
|
||||
/* Memory Controller RW supported only on 4.0.0+ */
|
||||
static const uint8_t mc_whitelist[0x68] = {
|
||||
0x9F, 0x31, 0x30, 0x00, 0xF0, 0xFF, 0xF7, 0x01,
|
||||
0xCD, 0xFE, 0xC0, 0xFE, 0x00, 0x00, 0x00, 0x00,
|
||||
0x03, 0x40, 0x73, 0x3E, 0x2F, 0x00, 0x00, 0x6E,
|
||||
0x30, 0x05, 0x06, 0xB0, 0x71, 0xC8, 0x43, 0x04,
|
||||
0x80, 0x1F, 0x08, 0x80, 0x03, 0x00, 0x0E, 0x00,
|
||||
0x08, 0x00, 0xE0, 0x00, 0x0E, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x30, 0xF0, 0x03, 0x03, 0x30,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x31, 0x00, 0x40, 0x00, 0x00,
|
||||
0x00, 0x03, 0x00, 0x00, 0xE4, 0xFF, 0xFF, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0xFE, 0x0F,
|
||||
0x01, 0x00, 0x80, 0x00, 0x00, 0x08, 0x00, 0x00
|
||||
};
|
||||
uint32_t offset = (uint32_t)(address - MMIO_GET_DEVICE_PA(MMIO_DEVID_MC));
|
||||
uint32_t wl_ind = (offset >> 5);
|
||||
/* If address is whitelisted, allow write. */
|
||||
if (mc_whitelist[wl_ind] & (1 << ((offset >> 2) & 0x7))) {
|
||||
p_mmio = (volatile uint32_t *)(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_MC) + offset);
|
||||
}
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -684,9 +730,16 @@ uint32_t smc_read_write_register(smc_args_t *args) {
|
|||
/* Return old value. */
|
||||
args->X[1] = old_value;
|
||||
return 0;
|
||||
} else if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400 && (address == 0x7001923C || address == 0x70019298)) {
|
||||
/* These addresses are not allowed by the whitelist. */
|
||||
/* They correspond to SMMU DISABLE for the BPMP, and for APB-DMA. */
|
||||
/* However, smcReadWriteRegister returns 0 for these addresses despite not actually performing the write. */
|
||||
/* This is "probably" to fuck with hackers who got access to smcReadWriteRegister and are trying to get */
|
||||
/* control of the BPMP for jamais vu etc., since there's no other reason to return 0 despite failure. */
|
||||
return 0;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue